Haven't found something to understand how to use it correctly.
I need to measure 2 views.
For first view i use this:
viewPager.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
//my measure code
viewPager.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
});
So what should i do for second view: i should use another same block of code, but for second view or can i put second measurement inside viewpager's measurements?
Added: logically it can be different cases:
One view inside another view.
Two views near each other in same parent (viewObserver on first view).
Two views near each other in same parent (viewObserver on parent).
Related
On my activity's creation I have set an AlphaAnimation in order to perform some visual effects. Now I have set a LayoutAnimationListener and overriden the onAnimationEnd() method. The Animation is executed correctly and the callback to onAnimationEnd() is working as well. Within the onAnimationEnd() method I want to perform another animation on two child objects of the Activity's layout. These are two EditTexts that are defined in XML with the property android:visibility="gone". For starters, what I want to do is to have them set as VISIBLE.
I've tried getting a reference from their parent, change their setVisibility(View.VISIBLE); and in the end invalidate the parent view.
This attempt does not seem to work. You will find the code attached below:
#Override
public void onAnimationEnd(Animation animation) {
Log.d(TAG, "onAnimationEnd()");
// TODO move icon up, make edittext's appear.
RelativeLayout layout = (RelativeLayout) View.inflate(
getApplicationContext(), R.layout.splash_dialog_layout,
null);
LinearLayout linear = (LinearLayout) layout.getChildAt(0);
Log.d(TAG, "Children" + linear.getChildCount());
email = (EditText) linear.findViewById(R.id.splash_Email);
email.setVisibility(View.VISIBLE);
pass = (EditText) linear.findViewById(R.id.splash_password);
pass.setVisibility(View.VISIBLE);
linear.invalidate();
layout.invalidate();
Splash_Activity.layout.invalidate();
}
};
I've tried to removeAllViews from a parent and add them one by one and invalidate again but that doesn't seem to work either.
There is probably a misunderstanding on my behalf as to how view inflation operates, shouldn't this work?
Thanks for your time.
Inflating a layout creates a new view hierarchy, which means the views you're obtaining are actually different from the ones displayed on screen even though they have the same IDs.
You can obtain on-screen views in several ways, but the easiest would probably be to query the containing Activity.
Activity.this.findViewById(R.id.splash_Email);
I would like to know how the child views in my custom RelativeLayout is drawn so that I can use getChildAt() (the childviews are defined in xml).
In particular, my layout contains 5 of these custom layout each containing a number of child views. Most solution I seen seem to be using findViewById() and indexOfChild(), however, since each child view with the same id would appear 5 times I am unsure if this method can be implemented. As a side note I would also like to know if how the index is determined so that when I make modification to the custom layout I would know how to adjust the index. Thanks!
RelativeLayout does not override getChildAt, so the order is the one defined in ViewGroup. The code of getChildAt is
2914 public View getChildAt(int index) {
2915 try {
2916 return mChildren[index];
2917 } catch (IndexOutOfBoundsException ex) {
2918 return null;
2919 }
2920 }
For an important reason, i'm required to keep only a single instance of a View in the entire application.
Within the application there will be multiple parent views, (each displayed only once at at time). And I need to move the child view around - to the currently active parent.
I tried doing the following:
if (view_to_move_around != null) {
ViewGroup oldParent = (ViewGroup) view_to_move_around.getParent();
if (oldParent != null) {
oldParent.removeView(view_to_move_around);
}
} else {
// Initialise the View
}
newParent.addView(view_to_move_around)
However, that method didn't seem to work? Completely stuck at this point.
I guess my question will be "What do you mean it's not working?" Are you getting an exception? It is not being displayed properly? Does it execute without issue, but is not displaying? Does it display, but it's always initializing?
Are you manipulating the child view within each parent view, before you pass it on to the next view?
Few things to make sure right off the bat:
Layout Params. Are they all set correctly? For both the parent and the child?
Parent View. The code doesn't appear to be faulty from what I can see. So is the parent view being displayed correctly?
Visibility. Are both the parent and child View.VISIBLE?
EDIT
Sweet. Ok, when I'm debugging these things, I like to keep it simple at first. I would take the child view, set it's background color to purple (or a contrasting color from the parent). Then, for simplicity's sake, set it's layout params to match parent. Assuming the ParentView is a FrameLayout:
mChildView.setBackgroundColor(Color.CYAN);
mNewParentView.addView(mChildView,
new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT, Gravity.CENTER));
Does it fill up and take over the parent?
In the intermediate steps, does it no longer have a parent when it's been removed?
Log.d("LOGTAG", mChildView.getParent().toString());
Does the new parent show that the child has been added?
Log.d("LOGTAG", mNewParentView.getChildCount()): // before and after
Is it being shown 'behind' the other views within the Parent?
mParentView.bringChildToFront(mChildView);
What may be the problem is that you are using getParent() to store oldParent. Compare for example:
if (view_to_move_around != null) {
ViewGroup oldParent = (ViewGroup) findViewById(R.id.old_parent);
if (view_to_move_around.getParent() == oldParent) {
oldParent.removeView(view_to_move_around);
}
} else {
// Initialise the View
}
newParent.addView(view_to_move_around)
Does this sound like what you're looking for? Let me know if this works.
I have seen some widgets using addView and sometimes addViewInLayout.
What is the difference between them?
What will happen if I replace one with the other?
Should I keep a flag during layout and use "addViewInLayout" or "addView" accordingly?
Thanks.
BR,
Henry
ps. add more tags: removeview, removeviewinlayout
Its generally a bad idea to call addView inside onLayout because addView internally triggers a requestLayout which eventually will call onLayout. So you end up triggering a layout while you are in the middle of a layout.
addViewInLayout is a "safer" version of the addView in the case you really have to add a new view in onLayout. It basically doesn't trigger a layout pass (doesn't call requestLayout internally).
See this video (by android engineer) for more detail: http://www.youtube.com/watch?v=HbAeTGoKG6k
addViewInLayout
Adds a view during layout. This is useful if in your onLayout() method, you need to add more views (as does the list view for example). If index is negative, it means put it at the end of the list.
addView
Assign the passed LayoutParams to the passed View and add the view to the window.
*Note that addView is implemented by ViewManager, an Interface to let you add and remove child views to an Activity, so you will be able to add views to ViewGroup at run time (DYNAMICALLY). Also note that addViewInLayout is a protected method of ViewGroup so if you are doing to create a custom view group you can call addViewInLayout() in onLayout() method.
For more see this
for example: we have a Layout (mLayout) and you want to add 2 views (view1, view2) into this layout.so there are 2 ways (the same)
case1: simply you use following command
mLayout.addView(view1); //onLayout() will be called first time
mLayout.addView(view2); //onLayout() will be called second time after the first time.
in this case, you don't care function onLayout(). it is simple source code.
case2: complicate but better performance
//do something to <global variable>
bCheck = true; //check it in fuction onLayout()
requestLayout(); //use this function to call onLayout() function for only one time
//in onLayout() function of mLayout, you use addViewInLayout()
//addViewInLayout() dont call onLayout() function, so you can add 2 views with only one time to call onLayout()
//onLayout() is abstract function, so mLayout is a instant of subclass of ViewGroup (ex: RelativeLayout, LinearLayout....)
#Override
onLayout(boolean changed, int l, int t, int r, int b)
if(bCheck == true){
v.addViewInLayout(view1); //add view1 to mLayout
v.addViewInLayout(view1); //add view2 to mLayout
bCheck = false;
}
}
});
I have no time to test it. anyone can help me make it more clear.
I have created linearlayout with layout:height="fill_parent" I have set 3 buttons and one TextView. I am able to see all. But when I want to get get the height of linearlayout. I used the following code in onCreate method. I am getting linear layout height as zero. But My linearlayout height is fill parent. and also i am able to see elements that i have added. Why I am not getting the actual height of my linearlayout.
LinearLayout mainLayout = (LinearLayout) findViewById(R.id.main_linearlayout);
System.out.println("...Height..."+mainLayout.getMeasuredHeight());
Thanks
Deepak
Refer to this question
Can't get height of Widgets
When an Activity receives focus, it will be requested to draw its layout. The Android framework will handle the procedure for drawing, but the Activity must provide the root node of its layout hierarchy.
See this link view drawing and layout padding and margis
Till onCreate, OnResume, onStart view is not yet created.
So if you want to get height or width of view do following and get it
observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener()
{
#Override
public void onGlobalLayout()
{
SearchResultActivity.this.sideIndexHeight = SearchResultActivity.this.sideIndex.getHeight();
ViewTreeObserver obs = sideIndex.getViewTreeObserver();
obs.removeGlobalOnLayoutListener(this);
}
});
Please get new TreeObserver to remove, otherwise you will get an exception, TreeObserver is not alive
overriding onWindowFocusChanged method, you get the height or width of view. But if your activity is started as child activity then onWindowFocusChanged method will not get called. So in that case use the above one.