What should I pass for root when inflating a layout to use for a MenuItem's ActionView?
Solution 1
I would simply do it like this:
menuItem.setActionView(R.layout.action_view_layout);
Let Android inflate the view for you.
If you need to do some extra changes on this ImageView call
ImageView imageView = (ImageView) menuItem.getActionView();
Update
In order to cater to your curiosity. That is what folks from Google do under the hood:
public MenuItem setActionView(int resId) {
final Context context = mMenu.getContext();
final LayoutInflater inflater = LayoutInflater.from(context);
setActionView(inflater.inflate(resId, new LinearLayout(context), false));
return this;
}
Solution 2
You have look on this. it nicely explains the Layout Inflator as well.
There are two usable versions of the inflate()
method for a standard application:
inflate(int resource, ViewGroup root)
inflate(int resource, ViewGroup root, boolean attachToRoot)
The first parameter points to the layout resource you want to inflate. The second parameter is the root view of the hierarchy you are inflating the resource to attach to. When the third parameter is present, it governs whether or not the inflated view is attached to the supplied root after inflation.
It is these last two parameters that can cause a bit of confusion. With the two parameter version of this method, LayoutInflater will automatically attempt to attach the inflated view to the supplied root. However, the framework has a check in place that if you pass null for the root it bypasses this attempt to avoid an application crash.
Many developers take this behavior to mean that the proper way to disable attachment on inflation is by passing null as root; in many cases not even realizing that the three parameter version of inflate() exists.
Solution 3
You generally want to pass whatever (ViewGroup sub-class) you're going to be adding actionView to in to inflate. in order to get actionView back from the inflate call and not the parent you'll want to add a 3rd parameter, false, so that it won't add the inflated view to the parent.
ImageView actionView =
(ImageView)layoutInflater.inflate(R.layout.action_view_layout, parent, false);
// .. do whatever you like with actionView and then add it to it's parent
menuItem.addActionView(actionView)
There's a pretty good tutorial here that goes about things a little differently. It's specifying action_view_layout
as part of menu.xml
with something like:
android:actionLayout="@layout/action_view_layout"
That may also work for you provided you're always using the same layout. if you go that route you'd be able to get the ActionView
by doing
ImageView actionView = menu.findItem(R.id.whatever).getActionView();
dlf
I write C++ and C# professionally, and other stuff recreationally. I can be contacted through my gmail account: username dlfsdev.
Updated on July 11, 2022Comments
-
dlf almost 2 years
I have an
ImageView
that I attach to aMenuItem
as itsActionView
(the item appears in theActionBar
). The layout for this view comes from XML. I'm inflating it like so:ImageView actionView = (ImageView) layoutInflater.inflate( R.layout.action_view_layout, null);
This appears to work fine. However; passing null for
root
in the call toinflate()
makes Lint yell at me:Avoid passing null as the view root (need to resolve layout parameters on the inflated layout's root element)
I can seemingly manage without a root in my specific case, but I'd rather have the code be as correct as possible. The problem is, I'm not sure which
View
should be used as the root here. This answer says it should be "the widget that is surrounding the view objects that you want to inflate." But what does that mean here? The one for the action bar? The activity? Something else entirely?
Update: Reading the answers has made me suspect me the right thing to do is:
- Get the
ActionBar
View
corresponding to theMenuItem
- Get its root
- Cast the root to a
ViewGroup
- Pass the result to the inflater
This seems to work. Can anyone confirm or deny whether this is what should be done?
- Get the
-
dlf about 10 yearsWell geez; I didn't even know that overload existed. Using it means I can't cache the result of the inflation and reuse it later (I detach and reattach the ActionView multiple times), but maybe I shouldn't be doing that anyway. And thanks for showing what that function actually does; guess I was making it more complicated than it needed to be.
-
Damian Petla about 10 yearsI don't think you need to cache it but if you have doupts ask another question and paste link here so I can track it and give you an answer. Don't forget to post your code. Thumbs up!
-
dlf about 10 yearsI definitely don't need to; I just thought I'd save the cost of inflating the layout each time. But it's a premature optimization for sure.
-
avalancha almost 10 years-1 this answer simply copies from the article and thereby explains what (good) inflation is. The OP presumably knows this and is asking about a special case to which this answer does not add anything