Cannot interact with all the textviews in the screen using robotium - java

I am facing a weird problem using robotium, when i use, solo.getCurrentViews() I get the views in a screen. But for some activities thought the views are loaded, i cannot see the views on the screen, they are hidden and some user actions needed to show them. For example, in Amazon home screen, i have to scroll through the product list, only 3 products are shown in the initial screen. But solo.getCurrentViews() loads all the product views. Now if say I click TextViews other than the three text views that are shown on the screen I get an error and the application exits. So, i think I have to somehow examine whether the textview is currently visible on the screen or not. This goes for all view objects.
Robotium loads all the views, but clicking views which are not currently visible causes error.

The Solo.getCurrentViews() will return all the views.
You can use: RobotiumUtils.removeInvisibleViews(solo.getCurrentViews()) for filtering the visible views.
OR you can filter the visible TextViews by yourself using the following code.
public ArrayList<TextView> getFilteredTextViews()
{
ArrayList<TextView> textViewList = solo.getCurrentViews(TextView.class);
ArrayList<TextView> filteredTextViewList = new ArrayList<TextView>();
for (TextView textview : textViewList ) {
if (textview != null && textview.isShown())
{
filteredTextViewList .add(view);
}
}
return filteredTextViewList;
}

You could cast every view to its class (or to android.view class!) and then check its "VISIBLE" property.
For TextView:
TextView tv = (TextView) solo.getCurrentViews().get(i);
int visible = tv.VISIBLE;
0 - Visible on screen; the default value.
1 - Not displayed, but taken into account during layout (space is left for it).
2 - Completely hidden, as if the view had not been added.
Do the same for all the controls.

just wanted to let you know, I solved the problem by using view.isShown() method check.

Related

RecyclerView is not returning all items

I'm making my first java android app and I'm having some issues with the RecyclerView.
I have a RecyclerView with a custom layout for each element.
I want to make that when I press the toolbar button, the Image Buttons inside EACH layout element inside the RecyclerView turn visible or invisible
This is the toolbar edit button code:
ArrayList<View> dest=new ArrayList<View>();
recView= findViewById(R.id.newListView);
recView.setItemViewCacheSize(0);
recView.findViewsWithText(dest,getString(R.string.onesingleuserlayout),View.FIND_VIEWS_WITH_CONTENT_DESCRIPTION);
for (View oneUserLayout:dest)
{
oneUserLayout.findViewById(R.id.btnDelete).setVisibility(newVisibility);
oneUserLayout.findViewById(R.id.btnEdit).setVisibility(newVisibility);
}
It hides almost all the elements, but not every one of them. The ones shown behave correctly, and SOMETIMES the ones not showing don't.
I think that it is related to the cached items.
Remove this line, in order to permit caching:
recView.setItemViewCacheSize(0);
Here it's explained how it works (which may also explain, why caching is required).
Try to change your approach and instead of calling all those findView methods from outside the RecyclerView, implement a method on the adapter to change a boolean variable representing the visibility of the buttons and then call notifyDataSetChanged to force the layout manager to redraw all the visible itens and since all items reference the boolean variable, when new items are redrawn they will have the new visibility.

ImageView flickers between its drawables

I have an android app with different graphical elements (ImageViews). Some ImageViews can be changed by pressing them, and then they will show another graphic. I have two systems for this, and my problem is the same for both.
In the first case I have layered two ImageViews on top of each other, and then I call each of them and set their visibility programmatically. In the second case I use the function "setImageResource" and change between different drawables.
In both cases I have the problem that the app quite often seems to "hickup" and for a split second show the wrong 'other' graphical element for each element that has a graphical alternative. It shows the wrong graphic for a split second and then jumps back to the correct graphic.
I can not find anything about this online, anyone here that recognizes this issue or have any clues as to what the problem might be?
relevant code:
public void setLight1(int bo) // changes a graphical element by drawable
{
ImageView vw = (ImageView) findViewById(R.id.light_1);
if (bo > 0)
vw.setImageResource(R.drawable.lampaljus);
else
vw.setImageResource(R.drawable.lampaslockn);
}
private void setStickMid(int stick) // changing between two layered imageViews
{
switch (stick)
{
case 1:
ImageView vw_1 = (ImageView) findViewById(R.id.stick_1_up);
vw_1.setVisibility(View.INVISIBLE);
ImageView vw_2 = (ImageView) findViewById(R.id.stick_1);
vw_2.setVisibility(View.VISIBLE);
break;
// the rest of the switch statement omitted, just more of the same
Of the top of my head, try these:
Move all the findViewById code to onCreate of your activity, to avoid calling it multiple times.
How big are the assets R.drawable.lampaljus, R.drawable.lampaslockn and others, dimensions wise. Because trying to load high resolution drawables, especially PNGs, will take a lot of memory.
But I can provide a better solution, if you can post the whole xml and Activity/Fragment code.

How to stack WebViews on top and load url into it without pushing views down

in our app, I'm loading an initial webview. Then in order to allow users to see chat history, I want to add new webviews on top on that initial one. The way I do that now is to have a linear layout wrapping the initial webview; this LinearLayout is called webview_wrapper and is in a ScrollView. Then, using a ScrollViewListener interface, when the user scrolls up past a set coordinate I create a new webview, call it newWebView, and call webview_wrapper.addView(newWebView, 0), the problem I'm having is that I want to do the loading and adding of the webview off the screen, then the user can continue to scroll up. This adding and scrolling happens inside of an onAnimationEnd method of an AnimationListener(while I make the post request for webview).
I feel like I've tried every way like calling scrollTo or scrollBy after adding the view but it's only scrolling partially. What is the best way to do this?
This problem was eventually solved by using a OnGlobalLayoutListener on the containing ScrollView, inside of which I call scrollTo(0, webViewHeight) and removeOnGlobalLayoutListener(this). Right before that, I make the WebView visible, set its height via setLayoutParams(view must be visible first).
Please correct me if I'm wrong but this probably works as seamlessly as it does because of the OnGlobalLayoutListener. When the view is made visible and the height set, and right after we set an OnGlobalLayoutListener which fires the scrollTo() to the exact height of the new view when the scrollView is being laid out, the net result becomes the appearance of the view inflating off screen.
final int newHeight = (int) ((height / 380.0) * webView.getWidth());
// Must set visible before setting layout params
currentOldView.setVisibility(View.VISIBLE);
// Without this line, view will bounce around as it attempts to self set the height based on HTML content
currentOldView.setLayoutParams(new LinearLayout.LayoutParams(webView.getWidth(), newHeight));
// Use viewTreeObserver to wait until scrollView completely laid out before attempting to scroll
ViewTreeObserver observer = scrollView.getViewTreeObserver();
observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
scrollView.scrollTo(0, newHeight); // Because spinner_wrapper still on view, will scroll to an overlap point.
canAddOldChat = true;
currentOldView.startAnimation(fadeInAnim);
if (isLastOldChat) spinner_wrapper.setAlpha(0.0f);
scrollView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});

Keyboard hides content in fragment, I need the frame layout to resize so bottom is just above the keyboard and now scrollable

I have a fragment in my app that has a scroll view for the signup and login pages. Right now there isn't enough content in the scroll view to actually make it scroll, however when the keyboard appears, it does cover up most of the content in the view. This causes a lot of issues especially on devices with smaller screens, it blocks a lot, and the view is NOT scrollable, so I have to close the keyboard to get to the rest of the inputs.
I need the bottom of the fragments frame layout to be pushed up to JUST above the top of the keyboard, so the keyboard won't actually hide any content, and still allow the scroll view to actually scroll to the rest of the content.
I have seen the usual fix to an issue similar to this, which would to change the AndroidManifest.xml to the following:
android:windowSoftInputMode="adjustResize"
but this will push up the entire page, which includes the footer view I have under and outside of the login and signup fragment layouts. It makes my scrollview smaller and allows for it to scroll, but I need the footer to stay hidden under the keyboard still.
I think a work around to this would be to have override onConfigurationChanged(); in MyActivity that will detect if the keyboard has appeared, and if it has, push the bottom of the framelayout to be JUST above the keyboard, thus making the scroll view smaller, and allowing us to actually scroll. I am not quite sure HOW to do this though.
Here is what it looks like with the keyboard up, blocking the content. This would be okay IF the scroll view was scrollable, allowing me to see the rest of the content, however it will not scroll and the only way to access the content under it is to close the keyboard first.
EDIT
I was able to use the answer below, editing the Android manifest for
android:windowSoftInputMode="adjustResize"
and the first method using the code below
final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight();
if (heightDiff > 100) { // if more than 100 pixels, its probably a keyboard...
... do something here
}
}
});
I had it adjust my views so the footer would be pushed way down below, then resize the layout holding the fragment to extend down allowing it to be scrollable still.
Okay, here's how I solved it.
The basic idea is that you have to:
Detect whether or not a soft-keyboard is showing,
React. Based on the detected information (is-soft-keyboard-showing), resize your layout accordingly.
There are two ways of achieving this:
to give your activity's root view a known ID, say '#+id/activityRoot', hook a GlobalLayoutListener into the ViewTreeObserver, and from there calculate the size diff between your activity's view root and the window size:
Customize your top-level layout class into one which overrides onMeasure()
And I would like to credit the above answer to this SO Post: how-to-check-visibility-of-software-keyboard-in-android, which I have found earlier on this particular problem.

Getting Currently Set Content View

We are creating an app with two main views: sView and sViewSettings. If the Android Back button is pressed we want an if statment to check if the current view is set to sView settings, if it is then call the sView.
Already have a listener setup for the back button just need it to call the if statement to check the current view.
Have already tried
if (this.findViewById(android.R.id.content) == sViewSettings)
Any ideas on this?
Thank you for Reading,
Travis
The view with id android.R.id.content is a FrameLayout holding your content view. Try this:
ViewGroup contentFrame = (ViewGroup) findViewById(android.R.id.content);
if (contentFrame.getChild(0) == sViewSettings) { ... }
However, I suggest a slightly different approach: use a ViewSwitcher (or any kind of ViewAnimator) to flip between the two main views and keep track in your code of which one is on display.
EDIT: If you want to keep your layouts loaded separately, you can assign an id (the same one) to the root view of each layout and then retrieve the content view directly using findViewById.

Categories

Resources