View.getRoot() returns View, so we can easily figure out which is the root view by using getResourceName(View.getId()).
View.getParent()..., while I expect it also returns View that is the parent, actually only returns an instance of ViewParent that seems to have very very few useful method/fields. It sucks.
So, is there any way to know the ID of the parent? I believe a View's parent is also View, thus it should has mID field.
I really wonder why Google didn't let View.getParent() just returns View. It makes sense, only when something else other than View could be the parent, and as far as I know, it's limited to View and its subclasses.
ViewParent is just an interface that any View that can have children implements. Most of the times the class you get back will be an instance of a ViewGroup, like LinearLayout or RelativeLayout. I'm not exactly sure what you mean by "name" but if you want to get the class name you can do so like always: view.getParent().getClass().getName().
The docs state that the parent is not necessarily a View:
public final ViewParent getParent ()
Added in API level 1 Gets the parent of this view. Note that the
parent is a ViewParent and not necessarily a View.
Returns Parent of this view.
However all implementations of ViewParent inherit from View. This should be a design decision to decouple the parent from a View using the ViewParent interface, although all implementations in the SDK are views.
Try casting it first. For example, if the parent of the View that you're trying to get id of is a TableRow, then do
((TableRow)View.getParent()).getID()
Related
As far as I understand we can put any view, such as child view of our root layout when initializing Snackbar.
Quoted from the document:
Snackbar will try and find a parent view to hold Snackbar's view from the value given to view.
However, this statement makes me think of putting the root view might be the best approach. Since traversing the nodes can be taxing especially a layout with a complex hierarchy.
Do I understand this correctly?
What is the difference between removing a view from it's parent and setting it's visibility as GONE?
If you remove a view from the parent, its no longer in its list of children. You can then add it to any other ViewGroup. If you loop through the old paren't children it won't come up, and it won't be called when the ViewGroup does things like resize itself.
If you make it GONE, its still a child of the ViewGroup. It can't be added to another, because it can have only 1 parent. It will still be called for things like resizing of the view group.
If you set a View's visibility GONE, it will look like it doesn't exist anymore, but it actually exists inside its parent, it is there, you can still manipulate it at your will, however, if you remove that view from its parent it will be actually out of it with all the consequences.
For instance: If you remove a view from a LinearLayout, it won't be inside of that linearLayout, and therefore it won't be affected by its parent gravity, but if you just set your view visibility GONE, it'll be still affected by its parent gravity, even if you can't see it because your view is invisible.
I'm sorry if it sounds a little bit unclear, but it is kind of hard to explain for me.
I have a ViewGroup that can have many LinearLayouts. And each LinearLayout can have many nested child views. What I want is that, if any view(even deep nested) inside a LinearLayout gets focus, it should call a custom method of its main parent LinearLayout.
The last thing I want to do is, set OnFocusChangeListener on every single deep nested child views of LinearLayout and that listener will call its parent's custom method. But that is really bad way to go for.
Is there any method I can override of parent LinearLayout that gets called every time its any nested child view's focus changes ?
You could use contentView.getViewTreeObserver().addOnGlobalFocusChangeListener() or override ViewGroup.requestChildFocus() of the root ViewGroup (requestChildFocus() is passed along the view parent chain).
For example When we write the code
View view = inflater.inflate(R.layout.main_activity, null);
What does the Android system do?
Check out the source for the LayoutInflater. It's an abstract class, a concrete instance of which is obtained through getLayoutInflater().
In essence, the inflater creates a root view object (the root view group of the inflated XML), then does two passes through the XML tree to attach each child view. This is done recursively to handle 'include' and to fix up references between child views, for example in RelativeLayout, and is done top to bottom.
The first pass constructs the tree by instantiating each of the child views, top down recursively, and passes the XML attributes to the view constructor telling the view how big it should be. It then calls measure() for each child passing in restrictions determined by the parent (e.g. RelativeLayout with 2 child views each requesting match_parent) using a measure specifications object and asks the view how big it wants to be. If the view is itself a view group, it will use the same algorithm to measure it's children.
The second pass is the layout pass when layout() is called on each child to position itself within the view. The parent positions the view using the measurements calculated in the measure pass. onDraw() is called and is passed a Canvas created from the DecorView backing bitmap.
The finalised tree is then ready to pass to the window manager which is done by setContentView() or addContentView().
http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.1.1_r1/android/view/LayoutInflater.java#LayoutInflater
Inflating an XML layout in simple language means you are converting the XML in View. Then you can fetch each view declared in the XML using the parent/inflated View.
For eg -
View view = inflater.inflate(R.layout.main_activity, null);
Now, here view is the reference of the XML from which you can fetch all the views as,
TextView tv = (TextView)view.findViewById(R.id.tv);
I have a container, usually a common LinearLayout, where I want to add views. After the user clicks on a view, the view should be removed from the container. Obviously, I can implement the functionality in an OnClickListener, and attach it to the view.
But, if another programmer forgets, to remove the view, after doing his stuff in his OnClickListener, the view will remain in the container.
Is there a way, that the container can enforce the removal? I haven't seen a View#getOnClickListener.
Why don't you create your own container and when addView is called you can modify the view's onClickListener.
EDIT:
This is not possible since there is no getOnClickListener and also the variable that holds the listener has the {#hide}.
I guess the only way out if extending each View and overriding the setOnClickListener method.