Let's say I have a view object:
View elem = getLayoutInflater().inflate(R.layout.element_activity, null);
I do some editing to this view dynamically and need to pass it as an argument to a function that takes a resource (ex. R.layout.element_activity). Is it possible to pass this edited view into that function?
Thanks in advance.
Is it possible to pass this edited view into that function?
No, there is no overloaded version of inflate method in LayoutInflater class, which accepts the View as parameter.
View inflateinflate(int resource, ViewGroup root)
View inflate(XmlPullParser parser, ViewGroup root)
View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot)
View inflate(int resource, ViewGroup root, boolean attachToRoot)
Note: if you have the view instance then simply use it, no need to inflate new view from resources or anything
Related
I'm following this tutorial to implement Expandable ListView: https://www.youtube.com/watch?v=GD_U0-N3zUI&t=404s
I did everything same as in it, But:
#Override
public View getGroupView(int i, boolean b, View view, ViewGroup viewGroup) {
String title=(String)this.getGroup(i);
if(convertView==null){
LayoutInflater layoutInflater=(LayoutInflater)this.ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView=layoutInflater.inflate(R.layout.parent);
}
return null;
}
I'm getting this error: "Cannot resolve symbol convertView"
Tried:
I did everything same as in it
No you didn't. If you watch the video closely you will notice the parameter names are different in the video.
I'm getting this error: "Cannot resolve symbol convertView"
That is because convertView is not defined in your code. (in the video it is).
You can fix it by either changing the parameter names:
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent)
The key here (for your problem) is the third parameter View convertView.
The other option is to use the your variable name view everywhere convertView is used.
Update: the inflate function expects a layout resource id (e.g. R.layout.parent an a corresponding XML file should exist in the rea/layout folder) as the first parameter. You are passing an ID resource.
Simply replace your code with below:
#Override public View getGroupView(int i, boolean b, View convertView, ViewGroup viewGroup)
{ String title=(String)this.getGroup(i);
if(convertView==null){ LayoutInflater layoutInflater=(LayoutInflater)this.ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView=layoutInflater.inflate(R.layout.parent, null); } return convertView; }
Model One :
private Context mContext;
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate("layout name",parent, false);
}
Model Two:
private Context mContext;
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate("layout name", null);
}
Difference between the two snippets:
convertView = inflater.inflate("layout name" , null);
and
convertView = inflater.inflate("layout name", parent, false);
inflate with 2 prams:
inflate(int resource, ViewGroup root)
inflate with 3 prams:
inflate(int resource, ViewGroup root, boolean attachToRoot)
resource: int: ID for an XML layout resource to load (e.g., R.layout.main_page)
root: ViewGroup: Optional view to be the parent of the generated hierarchy (if attachToRoot is true), or else simply an object that provides a set of LayoutParams values for root of the returned hierarchy (if attachToRoot is false.)
attachToRoot: boolean: Whether the inflated hierarchy should be attached to the root parameter? If false, root is only used to create the correct subclass of LayoutParams for the root view in the XML.
See Android Docs.
The difference is that you can specify a parent element for the inflated layout and can control whether or not the inflated layout should be attached to the parent. You can find the documentation of LayoutInflaters here.
Btw. You can use a more readable syntax like this one:
final View viewToAdd = LayoutInflater.from(this).inflate(layoutId, null);
I read the answer on Why does LayoutInflater ignore the layout_width and layout_height layout parameters I've specified? and wanted to make sure i understood what attach to root does.
Basically if you do
inflater.inflate(int idOfLayoutFile, ViewGroup parent, boolean AttachToRoot)
and lets say parent is not null
From what I got out of that answer was that attach to root just affects what the return type is of the inflate method. That is if attachToRoot is true, method will return parent, and if it is false, the method will return the root view of the XML file as specified by the resource id. Do I have the right idea here or am I missing something?
No, something is missed!
When you pass true as 'attach to root', inflater will inflate specified layout (represented by its ID) and then attach it to root of parent and finally return the parent
But when you left 'attach to root' to false. the parent hierarchy won't changed and only inflated layout will be returned.
Yes you are correct :: In short terms
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = LayoutInflater.from(getActivity()).inflate(
R.layout.your_layout, null);
return view;
}
Now as per above code view reference will hold the root element for
the layout your_layout
You can use this view reference to find all the child views of this
parent layout
You can refer the child views here even though the activity is not
created yet
If you read this you'll find that you should NOT pass null as value of root ViewGroup if you do not want to attach it but rather should use the 3-parameter version of inflater.inflate with 3rd parameter (attach to root) set to false. I.e., do this:
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState)
{
View view = LayoutInflater.from(getActivity()).inflate
(
R.layout.your_layout,
container,
false
);
return view;
}
And from the docs:
root Optional view to be the parent of the generated hierarchy (if attachToRoot is true), or else simply an object that provides a set of LayoutParams values for root of the returned hierarchy (if attachToRoot is false.)
And this is really good.
I have a ListView whose rows display data held within a Message Class. The view for each row is built when the Message Class is initialized and stored as a ViewGroup. I chose to do this as building the ViewGroup within the ListView adapters getView method was slow and caused the ListView to stutter when scrolled.
Ideally, in the ListView adapter I want to get a reference to the rows root view (which is a FrameLayout) and add this ViewGroup to it I.e. rootView.addView(message.getBody()) where getBody() returns the ViewGroup stored in the message class.
However if I do this I get this exception when I scroll up and down the list a few times:
IllegalStateException: The specified child already has a parent
If I attempt to call removeAllViews() on the rows root view the outcome is the same.
Is there a way to build a view once, store it within an object and simply add this to a row over and over?
Thanks
ListView is caching Views, so when you do this:
rootView.addView(message.getBody());
you may be trying to add a view that is already added to another of the ListViews cached Views. You should be able to fix this by explicitly removing the View from its parent ViewGroup before you add it to the root view:
ViewGroup vg = message.getBody();
ViewParent parent = vg.getParent();
if (parent != null && parent instanceOf ViewGroup) {
// if this ViewGroup already has a parent, unlink it from that parent
// before adding it to the new one
((ViewGroup)parent).removeView(vg);
}
rootView.addView(vg);
In your Adapter class you can check for convertView being null in getView(...). For example:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null)
convertView = _inflater.inflate(R.layout.my_row_layout, null);
//Your other work here
return convertView;
}
The convertView allows for re-use of the cell which is what you are looking for.
Using Fragments in android
I am trying to learn fragments
public class FirstFragment extends Fragment implements OnClickListener {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.first_fragment,
container, false);
Button nextButton = (Button) view.findViewById(R.id.button_first);
nextButton.setOnClickListener(this);
return view;
}
}
In the line ::
View view = inflater.inflate(R.layout.first_fragment,container, false);
why are we giving false
what is this about container
Can someone explain in laymen terms, in simplest terms
Please go easy on answers ... i am a newbie
You can check it all in the documentation: Android Developer Reference
public View inflate (XmlPullParser parser, ViewGroup root, boolean attachToRoot)
And the parameters you're asking about are:
root Optional view to be the parent of the generated hierarchy (if attachToRoot is true), or else simply an object that provides a set of LayoutParams values for root of the returned hierarchy (if attachToRoot is false.)
attachToRoot Whether the inflated hierarchy should be attached to the root parameter? If false, root is only used to create the correct subclass of LayoutParams for the root view in the XML.
Also, mind the return value as it depends on those parameters:
Returns
The root View of the inflated hierarchy. If root was supplied and attachToRoot is true, this is root; otherwise it is the root of the inflated XML file.