I'm doind this on my activity:
<include
android:id="#+id/withGyroLayout"
layout="#layout/with_gyro_layout"/>
Where with_gyro_layout.xml is
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.util.FixedTransformerViewPager
android:id="#+id/viewPagerTop"
android:layout_width="0dp"
android:layout_height="143dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.example.util.FixedTransformerViewPager
android:id="#+id/viewPagerBottom"
android:layout_width="0dp"
android:layout_height="143dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/viewPagerTop" />
</androidx.constraintlayout.widget.ConstraintLayout>
However, I can't access the elements viewPagerBottom or viewPagerTop from the binding for my activity:
binding.viewPagerBottom.setVisibility(View.VISIBLE);
binding.viewPagerTop.setVisibility(View.VISIBLE);
I tried putting with_gyro_layout.xml around <merge>...</merge> but it also didn't solve.
I want to be able to change programatically between with_gyro_layout.xml and without_gyro_layout.xml and also access its inner elements by the binding. How can I do that?
Two things are required in order to use ViewBinding with an included layout.
<merge> is not supported
The documentation only covers Data Binding, and not View Binding, but it does appear to be applicable to both. See https://developer.android.com/topic/libraries/data-binding/expressions#includes
Data binding doesn't support include as a direct child of a merge element.
In other words, the layout must have a real, concrete view as its root element. The following is supported:
<LinearLayout ...>
<TextView ... />
<TextView ... />
</LinearLayout>
But a layout with a <merge> root is not supported:
<merge ...>
<TextView ... />
<TextView ... />
</merge>
The <include> tag must specify an ID
It is, in general, possible to include a layout without explicitly specifying an ID. View Binding does not support this:
<include layout="#layout/included_layout"/>
Even if the included layout has an ID on its root element, it is still not supported. Instead, you must explicitly specify the ID on the <include> tag:
<include
android:id="#+id/some_id"
layout="#layout/included_layout"/>
Once both of these conditions are satisfied, your generated binding for the outer layout will include a reference to the binding of the included layout. Let's say our two files are outer_layout.xml and included_layout.xml. Then these two files would be generated:
OuterLayoutBinding.java
IncludedLayoutBinding.java
And you could reference the included views like this:
val outerBinding = OuterLayoutBinding.inflate(layoutInflater)
val innerBinding = binding.someId // uses the id specified on the include tag
val innerView = innerBinding.viewPagerTop
Or, for short:
val binding = OuterLayoutBinding.inflate(layoutInflater)
val innerView = binding.someId.viewPagerTop
I am using a bottomSheetBehavior in my android project. See codes below:
onlineGame.java:
// get the bottom sheet view
ConstraintLayout llBottomSheet = findViewById(R.id.end_of_online_game_bottom_sheet_behavior_cl);
// init the bottom sheet behavior
end_of_online_game_popup = BottomSheetBehavior.from(llBottomSheet);
avtivity_online_game.xml:
.
.
.
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.androidsample.BottomSheetActivity">
<!-- include bottom sheet -->
<include
android:id="#+id/includeBottomSheetBehavior"
layout="#layout/test_end_of_online_game_popup" />
</android.support.design.widget.CoordinatorLayout>
.
.
.
test_end_of_online_game_popup.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/end_of_online_game_bottom_sheet_behavior_cl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/cardview_light_background"
android:visibility="gone"
app:behavior_hideable="false"
app:behavior_peekHeight="120dp"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior">
.
.
.
The problem is this line:
ConstraintLayout llBottomSheet = findViewById(R.id.end_of_online_game_bottom_sheet_behavior_cl);
is returning null. I even changed the code place to onResume, but it did not work. When I get another element in test_end_of_online_game_popup, it works well and not null.
What is the problem?
tnx
Two choices:
ConstraintLayout llBottomSheet = findViewById(R.id. includeBottomSheetBehavior);
<include layout="#layout/test_end_of_online_game_popup" />
Try this:
View view = findViewById(R.id.includeBottomSheetBehavior);//firstly get the root view ID
ConstraintLayout llBottomSheet = view.findViewById(R.id.end_of_online_game_bottom_sheet_behavior_cl);
As you are using included layouts :
Use the find view on the id you have given to the include tag
findViewById(R.id.includeBottomSheetBehavior)
Or you can omit the id in the layout tag so that its not overridden.
In the < include > tag, only the layout attribute is required. This attribute, is a reference to the layout file you wish to include. This tag also lets you override a few attributes of the included layout.
The above example shows that you can use android:id to specify the id of the root view of the included layout; it will also override the id of the included layout if one is defined. Similarly, you can override all the layout parameters.
Source : http://www.curious-creature.com/2009/02/25/android-layout-trick-2-include-to-reuse/
I am using a RecylerView inside a layout l1.xml. I am including this l1.xml inside l2.xml using include tag.
I update this RecyclerView after an api call but l2.xml is not showing the updated RecyclerView.
Is there a way to forcibly ask the parent to refresh?
invalidate(), refreshDrawableState(); on the parent layout didn't help?
Is there a smarter way to use a rendered layout in multiple places?
l1.xml
...
...
<LinearLayout
android:id="#+id/feed"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="4"
android:background="#color/light_primary_background">
<include layout="#layout/events_list"/>
</LinearLayout>
...
...
events_list.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/events_recycler_view"
android:layout_width="wrap_content"
android:layout_height="match_parent" />
I update the events_recycler_view after an API call and the events_list.xml is updated but the include in l1.xml is not updated
Yes you can always use LayoutInflater to inflate a view, but the view must have the ids and type matching the id and type defined in your java code.
Check out this link for how to use layout inflater
http://www.programcreek.com/java-api-examples/android.view.LayoutInflater
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
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.