I am trying to use VIEWSTUB inside the merge tag.and its working well.I'm able to catch onclicklistenr of ViewStub's parent button.But i want to access the button that is inside the viewstub.
1.Main xml:
<merge>
<LinearLayout>
<Button></Button>
<ViewStub></ViewStub>
</LinearLayout>
</merge>
2.view stub layout
<Button android:id="#+id/button_cancel" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:minWidth="100dip"
android:text="Next" />
<ImageView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/imageView"
android:background="#drawable/golden_gate"
/>
</LinearLayout>
I am inflating view stub in an activity...here i want to fire click event on button cancel.How it will be possible
Let's suppose your ViewStub ID is view_stub. You need to do the following in the activity:
ViewStub viewStub = (ViewStub) findViewById(R.id.view_stub);
View inflatedView = viewStub.inflate();
Button button = (Button) inflatedView.findViewById(R.id.button_cancel);
Now you can do whatever you want with the button :) That is, the inflate method returns the stub layout which contains the actual elements from the XML file.
Of course, you can always have the onClick XML attribute...
As for removing the ViewStub - the question is two-fold (check http://developer.android.com/resources/articles/layout-tricks-stubs.html):
before inflation of the ViewStub - you cannot actually remove it. There's no need, though, since ViewStub "has no dimension, it does not draw anything and does not participate in the layout in any way".
after inflation - you just take the View returned by the ViewStub.inflate() method and do whatever you want with it - for example, hide it.
Related
Is it possible to inflate a ViewStub with a native android widget?
For example:
<LinearLayout...>
<TextView...>
<TextView...>
<ViewStub...>
</LinearLayout>
I want to replace/inflate the ViewStub with a Switch or a Checkbox. Is that possible?
To set the layout to inflate into the ViewStub either:
Set the layout via XML:
<ViewStub
android:id="#+id/stub"
android:inflatedId="#+id/myLayout"
android:layout="#layout/myLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
Or, set the layout at runtime:
viewStub.setLayoutResource(R.layout.myLayout);
Then, you can inflate the ViewStub.
View inflatedView = viewStub.inflate();
You could call this inflate() method from where you want, such as a Switch or Checkbox being clicked (as you asked).
Currently there is no way to replace the StubView with a View object. You must create a layout representing the view you want to replace. So for example, if you want to switch it with a single CheckBox, you need to create a layout like this
<?xml version="1.0" encoding="utf-8"?>
<CheckBox xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/my_checkbox"
android:text="Click me"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
Then calling
viewStub.setLayoutResource(R.layout.my_checkbox);
viewStub.inflate();
If you need a reference to the inflated view you can use this instead
CheckBox checkInflated = (CheckBox)viewStub.inflate();
I have a GridLayout-based View to which I am dynamically adding several ImageButtons. I'm trying to understand why the ImageButtons are styled correctly when I inflate them from a layout xml file, but not when I create them using the ImageButton constructor directly.
The GridLayout and ImageButtons were previously both defined in the same layout .xml file (and rendered as expected):
<ScrollView
style="#style/my_list_style"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="12dp">
<GridLayout
android:id="#+id/my_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center">
<!-- These ImageButtons are being converted to dynamic. -->
<ImageButton
style="#style/my_button_style"
android:src="#drawable/image1" />
<ImageButton
style="#style/my_button_style"
android:src="#drawable/image2" />
</GridLayout>
</LinearLayout>
</ScrollView>
To convert the ImageButtons to dynamic, I first removed them from the layout file and used code like the following to add them at runtime:
ImageButton imageButton = new ImageButton(context, null, R.style.my_button_style);
imageButton.setImageResource(R.drawable.image1);
parent.addView(imageButton);
But the buttons failed to render properly; they are not centered, and their sizes do not appear to be correct/uniform.
I then tried creating a new layout file, containing nothing but the ImageButton and its style:
<ImageButton
style="#style/my_button_style"/>
When I inflate this layout into the GridView at runtime, everything looks as expected:
LayoutInflater inflater = LayoutInflater.from(context);
ImageButton imageButton = (ImageButton) inflater.inflate(
R.layout.my_button_layout, parent, false);
imageButton.setImageResource(R.drawable.image1);
parent.addView(imageButton);
Why does inflating the view with LayoutInflator give different results than creating the button directly from its constructor?
Because when you create ImageButton manually, you do not specify its parent, hence it doesn't know the layout params of its parent and can't be laid out as you expect.
On the other hand, when you inflate it via LayoutInflater, you are specifying the parent. Then correct layout params are being passed to children. That's why you see difference.
Have a look at detailed article by Dave Smith.
I want to know how the LayoutParams will work on LayoutInflator. And what is difference between:
LinearLayout childLayout=(LinearLayout)inflater.inflate(R.layout.childitemlayout, null); //FIRST WAY
LinearLayout childLayout=(LinearLayout)inflater.inflate(R.layout.childitemlayout, container,false); //SECOND WAY
Because, both methods gives me different result.
Actually second inflate method are gives me correct result for both child layout change, but First method will gives me different result.
Here is my code:
MainActivity.Java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
LinearLayout mainLayout=(LinearLayout)findViewById(R.id.mainLayout);
LayoutInflater inflater=LayoutInflater.from(getApplicationContext());
for(int i=0;i<10;i++){
LinearLayout childLayout=(LinearLayout)inflater.inflate(R.layout.childitemlayout, null); //First WAY
// LinearLayout childLayout=(LinearLayout)inflater.inflate(R.layout.childitemlayout, mainLayout,false); //SECOND WAY
mainLayout.addView(childLayout);
}
}
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mainLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
</LinearLayout>
childitemlayout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="80dp"
android:layout_height="80dp"
android:orientation="vertical"
android:background="#525f67">
<TextView android:id="#+id/btn"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Button"
android:gravity="center"
/>
</LinearLayout> <!-- Both ways gives different result -->
<!--
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="#525f67">
<TextView android:id="#+id/btn"
android:layout_width="80dp"
android:layout_height="80dp"
android:text="Button"
android:gravity="center"
/>
</LinearLayout> Both method gives SAME result -->
The main difference between the two inflate() methods is the second parameter(the ViewGroup parameter) and its use in setting the proper LayoutParams for the root view of the inflated layout file. This is important because the LayoutParams keep various layout attributes of the view(like width, height, positioning rules etc) and are required so the parent of that view can properly show the view.
The first method basically says: build the hierarchy view from this layout file but don't assign LayoutParams to the root of the inflated hierarchy(maybe because the parent isn't know yet), also don't attach the inflated view to a parent.
The second inflate method says: build the hierarchy view from this layout file and also assign the proper LayoutParams(based on the second parameter given to the inflate method) to the root of the inflated hierarchy, also don't attach the inflated view to a parent.
In the first case, the root of the inflated layout file(R.layout.childitemlayout) will not have any LayoutParams set on it(the inflate method didn't assign any because the second parameter is null and it doesn't know which type of LayoutParams to generate), so your fixed width/height values are lost. Later when you'll do mainLayout.addView(childLayout); the mainLayout will check the LayoutParams of the childLayout, see that those are null and will automatically set an instance of the LayoutParams(using its generateDefaultLayoutParams() method). This method, in the particular case of a horizontal LinearLayout, will return an instance of LayoutParams where the width/height will be set to WRAP_CONTENT. So your childLayout will end up with WRAP_CONTENT as its size instead of the fixed values you set on them.
In the second case, the inflate method sees that you suggested the LinearLayout mainLayout as the ViewGroup used for generating the LayoutParams. This means that the fixed values(that you used for the width/height) retrieved from the layout file can be stored in a proper instance of the LayoutParams. When you'll do mainLayout.addView(childLayout);, mainLayout will see that childLayout has the proper LayoutParams instance(which has the values used in the layout file) and doesn't call its generateDefaultLayoutParams().
This question already has an answer here:
Custom Layout in android
(1 answer)
Closed 2 years ago.
I'm looking to a simple way to do layout templating in android.
I already check include and merge techniques without success.
(I think that it's possible creating custom Layouts and defining by code this behavior, but i wondered if that could be done by xml)
I want to define something like this:
[globalLayout]
<linearLayout params=xxx>
<linearLayout params=yyy>
<?yied ?>
</linearLayout>
</linearLayout>
[customView1]
<Linearlayout>
<ImageView />
<Button/>
</LinearLayout>
[customView2]
<Linearlayout>
<Button/>
<Button/>
<Button/>
</LinearLayout>
(these 3 xml should be reusable)
[HomeLayout]
<?include globalLayout >
<?include customView1 />
</include>
[ParamsLayout]
<?include globalLayout >
<?include customView2 />
</include>
The thing is that i want to have a reusable layout, if a perform a small change, it will affect all dependent views. somethink linked to "partial views or templating" in other languages.
Could anyone help me?
I have done something like this before by using view stub.
You can inflate any view you like inside that view.
<GlobalLayout>
<ViewStub>
<GlobalLayout>
Use LayoutInflater to do something like this:
On the Activity's onCreate:
super.onCreate(savedInstanceState);
setContentView(new TemplateInflater(this).apply(R.layout.products)
.onViewGroup(R.id.replace_here).ofTemplate(R.layout.template));
An implementation snippet:
public View ofTemplate(int templateId) {
LayoutInflater inflater = LayoutInflater.from(context);
View root = inflater.inflate(templateId, null);
View content = inflater.inflate(contentId, null);
((ViewGroup)root.findViewById(viewGroupId)).addView(content);
return root;
}
An example of a working code is in my git: https://github.com/erichegt/AndroidTemplating
I think this code will solve your problem, but you should use Fragments instead. You can have one Activity associated with a template and a Fragment to inflate it.
ViewStub is pretty straightforward and can cover basic layout templating needs.
It serves as a placeholder for some other layout which you can specify and inflate at runtime and then:
The inflated View is added to the ViewStub's parent with the ViewStub's layout parameters.
Here is example from one of my projects. In my layout template I have:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout ... >
...
<ViewStub
android:layout_width="0dp"
android:layout_height="0dp"
android:id="#+id/button_1_stub"
app:layout_constraintDimensionRatio="H,1:1"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="#id/split_guideline"
app:layout_constraintLeft_toRightOf="#+id/primary_left_guideline"
app:layout_constraintRight_toLeftOf="#+id/primary_right_guideline">
</ViewStub>
....
</android.support.constraint.ConstraintLayout>
... then, when I inflate it I am setting actual button layout that I need and inflate stub:
View contentView = inflater.inflate(R.layout.activity_main_template, null);
ViewStub button1Stub = contentView.findViewById(R.id.button_1_stub);
button1Stub.setLayoutResource(R.layout.work_button);
button1Stub.inflate();
... which inserts layout from R.layout.work_button instead of stub, imposing layout constraints I defined on the R.id.button_1_stub.
I have a custom navigation class where there are common views therefore i was thinking to put them into one layout which is to be inflated by the custom class and on the main layout ill put some navigation item on it.
Currently when i extends linearlayout, the views in the xml replaces all the views in the inflated view (i put this code on constructor)
((Activity) context).getLayoutInflater().inflate(R.layout.navigation_group, this ,true);
Is there a way where i could inflate a layout and get the child of the xml implementation and put it on one view? like
layout to be inflated
<com.mycompany.NavigationGroup>
<Text android:text="title" ... />
<Button android:text="collapse" ... />
<LinearLayout android:id="#+id/navigationItemHolder ... />
<Text android:text="descriptions" ... />
</com.mycompany.NavigationGroup>
used in main layout
<com.mycompany.NavigationGroup>
<Button android:text="menu 1" />
<Button android:text="menu 2" />
</com.mycompany.NavigationGroup>
My question is how could i put menu 1 & menu 2 inside navigationItemHolder? Thanks
You can do this programmatically after you inflate your layout. I believe you can do something like this:
YourLayout layout = (YourLayout)((Activity) context).getLayoutInflater().inflate(R.layout.navigation_group, this ,true);
layout.((LinearLayout)getChildAt (3)).addView (yourNavigationGroup);