I want to include the below layout in a main layout file, at multiple points, but at each usage, I want to change ONLY the "android:text" attribute of the text view inside the relative layout (as seen below). How can I achieve that?
P.S. I know how to include it in the main layout. This includes the relative layout (as seen below), but the main purpose of creating another layout file is because the code (of the textview) is being repeatedly used in the main layout, and the only attribute that differs is "android:text" between these repeated text views.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/order_id_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="test"
android:fontFamily="sans-serif-light"
android:padding="20dp"
android:textSize="20sp"
android:textStyle="bold" />
</RelativeLayout>
in your another Layout file you can use this .
<include layout="#layout/main_layout"/>
And From your activity class you can set text by this.
TextView tv = (TextView) findViewById(R.id.order_id_label)
tv.setText("New Text");
This is the only way you can do this .
If all TextView element arguments are the same you could define this component in a separate file using <merge> </merge> directive and then <include layout="" />
Check here how to reuse
But if any of the TextView argument is changing, i.e. android:text attribute, the best way is to separate all other TextView attributes to custom style and reuse this custom style in different xml layout files
Check here how to use styles
Related
I have a button I use a lot in one of my layouts. Or rather, I have like ten buttons all with the same text color, background color, text size, width, and height. I don't want to define all of these parameters for each button. So I want to be able to write something like...
<include view="#layout/standard_button"
android:id="#+id/button-id"
android:text="button-specific-text"/>
But of course, there is no include view="", there is only include layout, and include layout the xml file as a Layout, not a View, so setting the text is not possible and when I findViewById() in my activity, it would refer to a Layout and not a View.
Is there something like <include view="... ?
You can create a layout with your customized style button that you want to use multiple times, and wrap it in a <merge> tag like below sample.
And then you can reuse it over and over again using the include tag in any other layout.
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</merge>
Usage within any other layout, assuming the top layout named as my_button.xml
<include layout="#layout/my_button" />
I have a fragment defined by the following xml file:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment_example"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_example"/>
</RelativeLayout>
Now I would like to reuse the ImageButton (and other buttons I will add) in another fragment, ideally
without copying its definition
by keeping the definition in xml and not adding it programmatically
I.e. the goal is to overlay the same set of buttons in different fragments.
Is there a way to define all buttons in a separate xml file and load them programmatically on fragment creation?
Yes, You can.
Define all buttons in different xml say layout_buttons.xml
and add them in each fragment layout using
<include layout="#layout/layout_buttons" />
I've written an app and now want to design the UI. The problem is that I have the same data (well, not the same, but the same kind of data since it's an XML readout) and now I wanted to design it. But I don't think I can get the design how I want it programmatically. So I thought I design it once with XML and then copy the layout in the for loop for the other data as well. Is this possible?
If yes, how is it possible? I finished now my XML for one entry and now I want that all the other entries have the same style and layout as the others... Thanks!
There is simple way to achieve this.
There is include tag in xml file which you can use one layout in multiple screen design.
for eg. you had create header for application so no need to use same code in all file, just you can include that portion in each xml file.
here is simple example which may help you.
Create a Re-usable Layout
titlebar.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width=”match_parent”
android:layout_height="wrap_content"
android:background="#color/titlebar_bg">
<ImageView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/gafricalogo" />
</FrameLayout>
Use the Tag:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:background="#color/app_bg"
android:gravity="center_horizontal">
<include layout="#layout/titlebar"/>
<TextView android:layout_width=”match_parent”
android:layout_height="wrap_content"
android:text="#string/hello"
android:padding="10dp" />
...
</LinearLayout>
You should be using an Adapter to define your ListView elements. In which case, you will define a layout for that adapter (using XML) that will apply to every element in your ListView.
Bottom line, use an Adapter, which will set the same XML layout for every element in your List.
(Check item #3)
http://docs.xamarin.com/guides/android/user_interface/working_with_listviews_and_adapters
Here's the rub: I have a layout that uses the include tag. The layout is simple ->
<LinearLayout>
<TextView ...>
<LinearLayout>
<include ...>
</LinearLayout>
</LinearLayout>
Now the included file is nothing more than:
<LinearLayout>
<TextView ... android:id="#+id/inner_text">
</LinearLayout>
Now, if I try to access the TextView inner_text in either the create or onStart call, it throws a NPE. I have tried using LayoutInflater to infate the included xml file and then access inner_text but to no avail - it always fails.
So, the question is : does LayoutInflater work with included xml files of the parent xml file? What I would like to do is grab the contents of the included xml file - and set the whole thing to be either visible or not visible based on preferences.
Nothing seems to allow me to grab the TextView object.
Now, when I include the xml as just a nested element in the parent file (not using the include tag) - then it accesses that LinearLayout just fine - but that defeats my purpose of trying to make the layout of the view dynamic - that is, I can change the contents of the child included layout at will - and not have to do any changes to the parent layout.
Any help, pointers, suggestions -> greatly appreciated.
As suggestion I think you can have in the main xml some Layout component left empty, them in runtime, inflate the main xml, then the included xml and add the content of the included in the space you left in the main.
But I think you example have to work, internally the Android uses the inflater to inflate resources. Can you edit and tell a bit more? Code examples can be helpfully.
well, very strange, when you inflate a view from any xml resource (if xml resources have or have not nested resources with include) the view must hold all the parsed xml. So, yes, LayoutInflater work with included xml files of the parent xml file.
i copied here the way i'm doing now...
my generic layout (a header with text, progress bar and image)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingLeft="10dip">
<ImageView
android:id="#+id/genericHeaderLogoPin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:src="#drawable/logo_pin"/>
<TextView
android:id="#+id/genericHeaderTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="#id/genericHeaderLogoPin"
android:textSize="18dip"
android:textStyle="bold"
android:textColor="#FF0C9994"/>
<ProgressBar
android:id="#+id/genericHeaderProgressBar"
android:layout_width="25dip"
android:layout_height="25dip"
android:layout_centerVertical="true"
android:layout_toLeftOf="#id/genericHeaderLogoPin"
style="#android:style/Widget.ProgressBar.Inverse"
android:visibility="gone"/>
</RelativeLayout>
my parent layout... include the generic layout and a ListView
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="#drawable/background_new_search_activity_1">
<include layout="#layout/generic_header_layout" android:id="#+id/listaBusquedasHeader"/>
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:cacheColorHint="#00000000"/>
</LinearLayout>
my onCreate method that inflate the parent layout mentioned above:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
requestWindowFeature(Window.FEATURE_NO_TITLE);
LayoutInflater inflater = LayoutInflater.from(this);
View view = inflater.inflate(R.layout.lista_busquedas_activity, null);
setContentView(view);
listView = (ListView) findViewById(android.R.id.list);
listView.setOnItemClickListener(listItemClickListener);
((TextView)findViewById(R.id.genericHeaderTitle)).setText(R.string.messagesActivityTitle);
}
and that´s all, i hope this helps you.
Thanx for the help - I discovered what my problem was - I was trying to inflate the included file - not the parent container - so that's why it never found the elements. I wish the documentation would have mentioned that - logically I would think the parent xml file would load - but the included files may need inflating - guess not.
Works now thanks to your code examples you submitted.
Thanx.
In my layout xml file, I have included other layout xml file (each
with a different android id).
<include layout="#layout/view_contact_name" android:id="+id/test1"/>
<include layout="#layout/view_contact_name" android:id="+id/test2"/>
But when I run it in the emulator, and start Hierarchy Viewer, each of
the layout still shows 'NO_ID', and in my code, I have
findViewById(R.id.test1) and findViewById(R.id.test2) both returns null.
Can anyone please help me with my problem ?
Specify the ID in the <include>
<include layout="#layout/test" android:id="#+id/test1" />
Then use two findViewById to access fields in the layout
View test1View = findViewById(R.id.test1);
TextView test1TextView = (TextView) test1View.findViewById(R.id.text);
Using that approach, you can access any field in any include you have.
I found out, that if you are using <merge> tag in your include layout, then the ID of include transfers to the merge tag which is not real view.
So either remove merge, or replace it with some layout.
Tor Norbye wrote:
The <include> tag is not a real view, so findByView will not find it. The #id attribute (and any other attributes you've set on the include tag) gets applied on the root tag of the included layout instead. So your activity.getView(R.id.included1) should in fact be the <TextView> itself.
Romain Guy indicates that you can override the ID of an included layout by putting an android:id attribute inside the <include> tag.
<include android:id="#+id/cell1" layout="#layout/workspace_screen" />
I think the top answer misses the most important point and might mislead people into thinking the <include/> tag creates a View that holds the include contents.
The key point is that include's id is passed to the root view of the include's layout file.
Meaning that this:
// activity_main.xml
<include layout="#layout/somelayout" android:id="#+id/someid"/>
// somelayout.xml
<?xml version="1.0" encoding="utf-8"?>
<ImageView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
Becomes this:
// activity_main.xml
<ImageView
android:id="#+id/someid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
yes is like this, but careful when the layout inserted in include field is a custom one and you want to access that root layout. That layout in this case #layout/test test, is actually returned in first line.
test test1View = (test)findViewById(R.id.test1);
you must set id each include tag
included child element set a
new id. if you look how to generate new id, look at this entry:
https://stackoverflow.com/a/15442898/1136117
Problem is we try to use id which is not declared in current layout file.
Instead of declaring again, id can be simply referred using #+id/. If you refactor original id name through Android Studio it does refactor in included layout as well.
<include layout="#layout/toolbar"/>
<TextView
android:id="#+id/txt_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
**android:layout_below="#+id/toolbar"**
android:layout_marginTop="16dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"/>
In a case of using <RecyclerView> find the id of <include> by using an instance of inflated view or else it will return null.
public class ViewHolder extends RecyclerView.ViewHolder {
private mTextView;
public ViewHolder(View view) {
super(view);
View include_1 = view.findViewById(R.id.include_1);
mTextView = (TextView) include_1.findViewById(R.id.text_id);
}
}
If you have set id to either root tag of included layout then you can use that id
or you can set id to included layout.
But you can not set id to both it may throw exception.
<include layout="#layout/view_contact_name" android:id="+id/test1"/>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
....
</LinearLayout>
Or
<include layout="#layout/view_contact_name"/>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:id="#+id/llBottomMainView"
android:layout_width="match_parent"
android:layout_height="wrap_content">
....
</LinearLayout>
When talking about include you either have an id on the root view inside the included layout file or on the include line itself and not on both. For example:
<include layout="#layout/layout1" android:id="#+id/layout1"/>
Layout 1 file
<RelativeLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/layout2">
</RelativeLayout>
The above example is wrong because technically you have two id's declared for the same layout. So what you have to do is pick which element will have the id.
To specify the id when you are including a xml file is like setting it to any xml element
Example:
*list_layout.xml*
`<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rvNames"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>`
*activity_main.xml*
`<RelativeLayout
tools:context=".MainActivity">
<include
layout="#layout/list_layout"
android:id="#+id/myList" />
</RelativeLayout>`
Now if you want to get that to use in .kt file, just use normally findViewById
Exemplo
*MainActivity.kt*
`val myList: RecycleView = findViewById(R.id.myList)`
Wow, I can't believe this question doesn't have the right answer yet. It's simple tags suck. You can only change things that start with android:layout_ which android:id doesn't match. So the answer is you can't. Sorry. What you can do instead is create a class that will be a ViewGroup which will inflate the included views inside, then add that as a tag in your layout, but that's about it.