Android DataBinding Dynamic addView - android

I have two layout xml A and B
A linearlayout in A xml with id 'layout'
Now I want to add B in layout using layout.addView()
How can i do this by using databinding

I don't think this is the best practice, but here's how I dynamically added views with databinding.
In layout A, I have a FrameLayout like below:
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
bind:createView="#{viewModel.dynamicViews}">
In my viewModel class, I have a static method with BindingAdapter annotation,
#BindingAdapter("bind:createView")
public static void createImproveView(FrameLayout layout, LinearLayout replacement) {
layout.removeAllViews();
layout.addView(replacement);
}
and I have my replacement layout here:
public LinearLayout getDynamicViews() {
LinearLayout layout = new LinearLayout(mContext);
// dynamically add views here. This could be your layout B.
return layout;
}
I couldn't find any other solutions, and this was working fine for me. Please give me any comments, I'm open to learn better solutions!

addView(databinding.getRoot())
you can see the getRoot() return a View instance, so you can addView by this method.
This databinding is the databinding instance of the view you want to add.

If you want to do the same using the layout xml . Use the include control like this:
<include layout="#layout/header_logo_lyt" //Name of xml you want to include/>

Related

Newbie questtion : Inflating xml files with and without using the actually layout

This always confused me. Let's say I have these two scenarios :
First scenario :
my_layout.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout ..>
<CardView id="#+id/myCardView" ../> // or any other view
</RelativeLayout>
In code :
.. onCreate() {
View view = inflater.inflate(R.layout.my_layout, container, false);
myCardView = (CardView) view.findViewById(R.id.myCardView);
}
Second scenario :
my_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<CardView ../>
In code :
.. onCreate() {
myCardView = (CardView) inflater.inflate(R.layout.my_layout, container, false);
}
To inflate and get a CardView object, when should one use first scenario and when the second ?
Note that in first scenario, I never do anything with the RelativeLayout object. It's merely used to get the CardView object.
The reason I ask is I see the first scenario in so many tutorials but it is never explained why the extra encapsulating Layout is actually there.
Is there any scenario where the first example above does make more sense than the second ?
Post Edit: Could you please evaluate my question with RecyclerView.ViewHolder pattern in mind ?
Post Edit 2:
I use the first scenario in ViewHolder pattern.
public class EntryViewHolder extends RecyclerView.ViewHolder {
public CardView cv;
public EntryViewHolder(View itemView) {
super(itemView);
cv = (CardView) itemView.findViewById(R.id.entries_card_view);
}
}
Still, even in this scenario I never make use of the encapsulating RelativeLayout. I only use it to call findViewById(..) to get the CardView object.
The first scenario would be used whenever you have an XML layout with multiple child views inside of them. A couple TextViews, EditTexts, Spinners, etc, the things you would need to put together a presentable page for the user. The <RelativeLayout and the other layout tags help organize the child views inside of them, in this case "Relative" to each other. I would stick to this practice instead of your second scenario.
I'm not sure I have ever seen anything like your second scenario before. Inflating the layout and then casting the entire layout to a CardView seems odd. The closest thing I can relate it to is when you make an XML for a custom adapter view, where you might be making a list of card objects.
Here is a helpful link on Layouts.

Show custom view in all activities

I want to show a view that should be shown in all activities. I don't know how to inherit views in android. What i did is below, its showing the view in first activity but not in all activities. This pease of code is form my BaseActivity, please help
LayoutInflater inflater = getLayoutInflater();
View child = inflater.inflate(R.layout.custom_error, null);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams( LayoutParams.WRAP_CONTENT , LayoutParams.WRAP_CONTENT );
params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
addContentView(child, params);
You could get an Android specific View in the Activity. For example the following code below will add a TextView to the Activity's content area.
TextView tvSample = new TextView(this);
tvSample.setText("Hello!");
((ViewGroup) hostActivity.findViewById(android.R.id.content)).addView(this);
Whereby hostActivity is your current Activity and android.R.id.content is a specific element (the content area, not including the ActionBar).
Alternatively, as already stated, make use of <merge> and <include> tags in your layout XMLs.
you can do this with two solution
for programmatically
1)After adding child view to you parent View need to call setContentView(parentView) and pass you parent layout to it.
and With XMl
2) You can use include tag. follow this link will help you.
http://developer.android.com/training/improving-layouts/reusing-layouts.html
Have you tried 'include' tag of xml? It will do the job.
<include
android:id="#+id/container_header_lyt"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_above=...
android:layout_toLeftOf=...
layout="#layout/header_logo_lyt" //Name of the xml layout file you want to include
/>
In the layout/xxxx use the name of your layout file that should be repeated.
After use the above code in your xml file like any other widget.
When you want to show it:
FrameLayout rootLayout = (FrameLayout)findViewById(android.R.id.content);
View.inflate(this, R.layout.overlay_layout, rootLayout);
Then when you want to remove it:
FrameLayout rootLayout = (FrameLayout)findViewById(android.R.id.content);
rootLayout.removeViewAt(rootLayout.getChildCount()-1);
That's a concise solution, you should remove the View by giving the RelativeLayout an id in the XML file, then remove by: rootLayout.removeView(findViewById(R.id.the_id_of_the_relative_layout));.
Answer by nmw

Android including an xml layout to activity

I've an activity.java file in which my setContentView(R.layout.x); Now,I've an y.xml in which I've an Linear Layout,I've to attach an onclick() method to my view.
Attaching onclick() has to be in my activity.java file, How do I include y.xml.
I tried this,
1. layout = (LinearLayout) findViewById(R.layout.y);
eView = (EditText)layout. findViewById(R.id.editview);
2. eView = (EditText)findViewById(R.id.editview);
but both gives my null pointer exception, How do I include my editText
Update
final LayoutInflater lyInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
showLinearLayout = (LinearLayout) lyInflater.inflate(R.layout.y, null);
showView = (EditView) showLinearLayout.findViewById(R.id.edittext);
You can use inflation as shown below:
final LayoutInflater lyInflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LinearLayout yLayout = (LinearLayout) lyInflater .inflate(
R.layout.y, null);
eView = (EditText)yLayout.findViewById(R.id.editview);
So you won't get exception anymore. Hope it helps.
LayoutInflater is used to instantiate layout XML file into its corresponding View objects.in other words, it takes as input a XML file and builds the View objects from it.
in your scenario, you have to use LayoutInflater. read this article.
Ram.
If you want to include y xml file into your x xml file then follw this steps.
I am assuming that you want to include Linear Layout into your Activity on click of onclick() method of the button or whatever, then add the Linear Layout into your x xml file and add the android:visibility="gone" so at begin you can not show the linearlayout.
<LinearLayout
android:id="#+id/history_value_body"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:visibility="gone" > <<<<<<<<<<< HERE
----------------------------
-----------------------------
</LinearLayout>
Now, From the java class make it visible when needed, in your case into onclick method.
Like...
linear.setVisibility(View.VISIBLE); // linear is the object of your Linearlayout
If any prob then ask me.
Good Luck.
If I understand the question correctly, your Activity uses x.xml, and you also want to include another layout that is defined in y.xml.
You can do so using the <merge> or <include> tags, as described in the documentation.
Alternately, you can use a ViewStub to conditionally inflate another layout in a given place in a layout. For example, you can include a ViewStub tag in x.xml, and inflate y.xml in the same spot in the view hierarchy. Then, you may attach any click listeners you need (by using findViewById()).
You can use addView method of ViewGroup.
addView(layout, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));

Newbie: set content view which consists of two parts

I am developing an Android 2.1 app.
I have defined a LinearLayout class:
public class MyTopBar extends LinearLayout {
...
}
Then, I have a layout xml file (content.xml):
<LinearLayout>
...
</LienarLayout>
I have a RootActivity.java , I would like to set MyTopBar as content in this RootActivity.
Then I have MyActivity which extends RootActivity:
public class MyActivity extends RootActivity{
//set xml layout as content here
}
I would like to set the content.xml as content of MyActivity.
As a whole, I would like to use the above way to achieve the layout that MyTopBar should be located on top of the screen always. The other Activities which extend RootActivity will have its content below MyTopBar. How to achieve this??
1 You could add your custom LinearLayout directly to the xml layout of the MyActivity class like this:
<LinearLayout>
<com.full.package.MyTopBar
attributes here like on any other xml views
/>
...
</LinearLayout>
or you could use the include tag to include the layout with the custom view:
<LinearLayout>
<include layout="#layout/xml_file_containing_mytopbar"
/>
...
</LinearLayout>
2 Use :
setContentView(R.layout.other_content);
Have a Layout vacant for the TopBar and add Your Topbar in it by using layout.addView(topbarObject);
Regarding your second question the setContentView can be called only once, as far as I know. You can however have those two xml files inflated using View.inflate(other_content.xml) and added in the parent xml layout whenever you need it. You can removeView() on parent layout and addView() with the new layout file.
Edit:
For the solution of both the question, you can have a parent Layout for eg. like the following:
//Omitting the obvious tags
//parent.xml
<RelativeLayout
android:id="#+id/parentLayout">
<RelativeLayout
android:id="#+id/topLayout">
</RelativeLayout>
<RelativeLayout
android:id="#+id/contentLayout">
</RelativeLayout>
</RelativeLayout>
Now in your code set the parent layout as content view,make an object of your TopBar layout and add it to the topLayout.
setContentView(R.layout.parent);
MyTopBar topBar=new MyTopBar(this);
RelativeLayout toplayout=(RelativeLayout)findViewByid(R.id.topLayout);
topLayout.addView(topBar); //or you can directly add it to the parentLayout, but it won't work for the first question. So better stick to it.
Now inflate the required xml layout. and add it to contentLayout.
RelativeLayout layout=(RelativeLayout)View.inflate(R.layout.content,null);
contentLayout.addView(layout);//Assuming you've done the findViewById on this.
and when you need to show the other content xml, just call the following code.
contentLayout.removeAllView();
RelativeLayout layout2=(RelativeLayout)View.inflate(R.layout.other_content,null);
contentLayout.addView(layout2);

Wrapping a LinearLayout from xml

I'm trying to make some Android view classes (which are just wrappers around layouts defined in an XML file). Is this correct:
public class MyViewWrapper extends LinearLayout {
private TextView mTextView;
public MyViewWrapper(Context context) {
super(context);
}
public constructUI() {
LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.myview, this);
mTextView = (TextView)findViewById(R.id.myview_textview);
}
}
so the idea is just that I can construct my views like that, and they have logic inside for modifying their child views etc. The layout looks like:
<LinearLayout>
<TextView />
</LinearLayout>
It just looks like I'm going to get an extra unnecessary LinearLayout. The wrapper class is itself a LinearLayout, and then it will attach the inner LinearLayout from the xml file.
Is that ok?
Thanks
You can try replacing the <LinearLayout> in your layout file with <merge>. I have not tried that recently, and I think I ran into problems when I last tried it, but in theory it should serve the purpose. <merge> basically means "take all my children and put them directly into whatever container I'm being inflated into".

Categories

Resources