Check If a view is completely hidden by other views (not window) - android

I have two views A and B. View B is completely covered view A which means the bounding rect of view B is more than bounding rect of view A.
The best example I can give is, I have a fixed bottom tabs layout and a RecyclerView with multiple linear layouts. When I scroll, one of the linear layout will be behind the bottom tabs layout.
So, How can I programatically check If view A is completely covered by other views (other views might not be known upfront)?
Is there any possible way to identify this?
Update:
I have tried the solution mentioned here. But it didn't solve my problem. In my case, the view bounds are exactly matching and I want which view is on top.

After lot of struggle, I have found a way to identify if view is overlapped by other views in the following way.
AccessibilityNodeInfo nodeInfo = AccessibilityNodeInfo.obtain();
viewA.onInitializeAccessibilityNodeInfo(nodeInfo);
if (!nodeInfo.isVisibleToUser()) {
// View is not visible to user. This also validates if viewA is overlapped by other views
}
nodeInfo.recycle();

Use the following method it will help you to find view overlapping:-
private boolean isYourViewOverlapping(View firstView, View secondView) {
int[] firstPosition = new int[2];
int[] secondPosition = new int[2];
firstView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
firstView.getLocationOnScreen(firstPosition);
secondView.getLocationOnScreen(secondPosition);
int r = firstView.getMeasuredWidth() + firstPosition[0];
int l = secondPosition[0];
return r >= l && (r != 0 && l != 0);
}

Related

How to check if layout is covered by another layout?

On top of the screen I have a Grid Recycler layout and it has height wrap content. So on start it has 1 row of items. In the middle of the screen I have a button. So I am starting adding items in recycler and number of rows increases 1 then 2 then 3 etc... So I want to know the point when my recycler view will be visually "UNDER" button because number of rows in grid is too much.
So is there a way to check if the view is covered by another view?
Assuming your item layout_height is wrap_content along recyclerview, there is a possibility recyclerview takes one item to fill up the screen or more than 100. However, you can check the accepted answer and explore other answers.
private boolean isViewOverlapping(View firstView, View secondView) {
int[] firstPosition = new int[2];
int[] secondPosition = new int[2];
firstView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
firstView.getLocationOnScreen(firstPosition);
secondView.getLocationOnScreen(secondPosition);
int r = firstView.getMeasuredWidth() + firstPosition[0];
int l = secondPosition[0];
return r >= l && (r != 0 && l != 0);
}

Android getting the view tree

I want to get all views inside of an activity. like;
ArrayList<View> views = new Arraylist<>();
views.addAll(getAllViewsFromActivity());
what I want is "getAllViewsFromActivity()" function. I clearly want to get all the views even a single button. But I couldn't find any clear answer.
For the progress, it must be like this:
MainView : getWindow().getDecorView()
- -
RelativeLayout
- -
Button LinearLayout
-
TextView
How can I get this tree in Android programmatically? and also lets assume that I got this tree, Can I also identify the types of them like: view instanceof Button ?
the view you want to get is clear. so you can use the parent view(such as LinerarLayout) to get the children. so you can try this:
int count = parent.getChildCount();
for(int i =0; i< count;i++){
View child = parent.getChildAt(i);
//here you can to chage the view some proper.
//if you only want to change the background color, it belongs to view, don't
// need to cast.
}

android scrollview scroll to top direction when new view added

In scrollview, if I add any view in middle, normally all the views below the added view scrolls downside. But I want to scroll the top views of added view to upside without disturbing the bottom views. Is it possible in scrollview , please help me ?
In the figure , If view 4 was added , then view 1 has to be scrolled upwards , without changing the positions of view 2 and view 3.
You can probably get the height of the view you are adding with and then scroll the scrollview manually that many pixels
scrollView.scrollBy(0, viewAdded.getHeight())
I've been wanting to try this question for quite some time, I finally got the chance today. The method is pretty simple (in fact, #dweebo already mentioned it earlier) - we move the ScrollView up as we add the view. For getting precise (and valid) dimensions when adding, we use a ViewTreeObserver. Here's the code you can get hints from:
// Getting reference to ScrollView
final ScrollView scrollView = (ScrollView) findViewById(R.id.scrollView);
// Assuming a LinearLayout container within ScrollView
final LinearLayout parent = (LinearLayout) findViewById(R.id.parent);
// The child we are adding
final View view = new View(ScaleActivity.this);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 100);
view.setLayoutParams(params);
// Finally, adding the child
parent.addView(view, 2); // at index 2
// This is what we need for the dimensions when adding
ViewTreeObserver viewTreeObserver = parent.getViewTreeObserver();
viewTreeObserver.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
#Override
public boolean onPreDraw() {
parent.getViewTreeObserver().removeOnPreDrawListener(this);
scrollView.scrollBy(0, view.getHeight());
// For smooth scrolling, run below line instead
// scrollView.smoothScrollBy(0, view.getHeight())
return false;
}
});

Reparent a view in Android - move from one layout to another

I'm coming from iOS where I can simply reparent a view under another view. I'm trying to figure out the equiv in Android. I want to move an imageview up a couple of spots in the view hierarchy when clicked. Something like:
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
//Tile touchBegan
if(action == MotionEvent.ACTION_DOWN) {
RelativeLayout rl = (RelativeLayout)(getParent().getParent());
rl.addView(this);
}
}
This is a simplified example of course.. but just trying to figure out how to re-parent a view under another layout. I found this example searching around which seems incredibly complicated..
http://blahti.wordpress.com/2011/02/10/moving-views-part-3/
If I remember my old iOS experience right it removes the view from it's old parent automatically if you add it to another one (I might be wrong ;-).
Here's how you would do the same on android:
ViewGroup parent = (ViewGroup) yourChildView.getParent();
if (parent != null) {
// detach the child from parent or you get an exception if you try
// to add it to another one
parent.removeView(yourChildView);
}
// you might have to update the layout parameters on your child
// for example if your child was attached to a RelativeLayout before
// and you add it to a LinearLayout now
// this seems very odd coming from iOS but iOS doesn't support layout
// management, so...
LinearLayout.LayoutParams params = new LinearLayout.LayoutP...
yourChildView.setLayoutParams(params);
yourNewParent.addView(yourChildView);
((ViewGroup)view.getParent()).removeView(view);
newContainer.addView(view)

Android ViewFlipper + homescreen animation

I am trying to use a ViewFlipper and make it act like the home screen(The layout will move with your finger). Check out this for an example. I want to do this with a ViewFlipper that only contains two children so the opposite view should be shown on either side of the current view depending on which way the user moves their finger. This code works but only for 1 direction at a time. This is in onTouchEvent.
case MotionEvent.ACTION_MOVE:
leftView.setVisibility(View.VISIBLE);
rightView.setVisibility(View.VISIBLE);
// move the current view to the left or right.
currentView.layout((int) (touchEvent.getX() - oldTouchValue),
currentView.getTop(),
(int) (touchEvent.getX() - oldTouchValue) + 320,
currentView.getBottom());
// place this view just left of the currentView
leftView.layout(currentView.getLeft() - 320, leftView.getTop(),
currentView.getLeft(), leftView.getBottom());
// place this view just right of the currentView
rightView.layout(currentView.getRight(), rightView.getTop(),
currentView.getRight() + 320, rightView.getBottom());
Which ever of the bottom two lines I put last that direction will work correctly but the other will not.
Here is how I set the leftView and rightView:
final View currentView = myFlipper.getCurrentView();
final View leftView, rightView;
if (currentView == meView) {
Log.d("current layout: ", "me");
leftView = youView;
rightView = youView;
} else if (currentView == youView) {
Log.d("current layout: ", "you");
leftView = meView;
rightView = meView;
} else {
leftView = null;
rightView = null;
}
Is it going to be possible to set it up so that the same view is shown on both sides of the current view?
Thanks stealthcopter
That worked here is the new code if anyone is interested.
if (touchEvent.getX() < oldTouchValue){
// place this view just right of the currentView
rightView.layout(currentView.getRight(), rightView.getTop(),
currentView.getRight() + 320, rightView.getBottom());
}else if (touchEvent.getX() > oldTouchValue) {
// place this view just left of the currentView
leftView.layout(currentView.getLeft() - 320, leftView.getTop(),
currentView.getLeft(), leftView.getBottom());
}
I also moved the setVisibility() calls to the MotionEvent.ACTION_DOWN in an attempt to get rid of some flickering of the views. This helped but I still get a bit.
I have possibly not very constructive suggestion, but if you want it to behave like a home screen, why you don't want to look at the src of that, and modify it to your needs ?
To get rid of the flickering, set setVisibility(View.INVISIBLE) in MotionEvent.ACTION_DOWN. The default value is "GONE" on a view. That means that you can not set Layout() on a view until it's either "VISIBLE" or "INVISIBLE". So in three steps:
Set Visibility to INVISIBLE on the View
Set Layout() on the View
Set Visibility to Visible on the View
If I understand your request, this effect should now be implemented using a View Pager
Looks like this:

Categories

Resources