I have to include one layout in my application. So that I have used
<include
android:id="#+id/support_layout"
android:width="match_parent"
android:height="match_parent"
layout="#layout/support"/>
I have referenced this include tag in my java file using View.
View v = (View) findViewById(R.id.support_layout);
But at some point of my code I have to Hide this layout.
so that I used v.GONE
But it's not Hiding.
I want to reference those text and button attributes located in XML programatically.
How can I do that?
There is my support.xml:
<LinearLayout
android:id="#+id/support_layout"
android:width="match_parent"
android:height="match_parent">
<TextView
android:id="#+id/txt"
android:width="match_parent"
android:height="wrap_content"/>
<Button
android:id="#+id/btn"
android:width="match_parent"
android:height="wrap_content"
android:text="Button"/>
</LinearLayout>
Since <include/> is not a View type in android and visibility is the property of View, we can not access the visibility from included layout's reference.
However if you are using kotlin with view binding, we can get the reference of root of the included layout like binding.supportLayout.root which probably will be one of the View (ConstraintLayout, RelativeLayout, LinearLayout etc.)
Now we have reference of view means we can play with their visibility like below code.
binding.supportLayout.root.visibility = View.GONE
Hope you got the idea.
We need to see your actual implementation of hiding that View you mentioned.
But, straight from reading of your question, I presume that you've might do it the wrong way.
To hide or make a view invisible, use this:
yourView.setVisibility(View.INVISIBLE);
Bear in mind that this does not remove the view compeletly; it would still remain in your layout and you could get a reference to it or even try to manipulate it.
To remove it compeletly, use this instead:
yourView.setVisibility(View.GONE);
Now if you call this, yourView would be compeletly removed from the layout. You will no longer able to get a reference to it.
Put that view into a linearlayout and hide the linearlayout. It will work.
<LinearLayout
android:id="#+id/support_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<include
layout="#layout/support"
android:height="match_parent"
android:width="match_parent" /> </LinearLayout>
And don't forget writing Linearlayout instead of View.
Briefly, instead of
View v = (View) findViewById(R.id.support_layout);
Do this
LinearLayout v = (LinearLayout) findViewById(R.id.support_layout);
You can hide this "included" layout with calling setVisibility() :
v.setVisibility(View.GONE)
and show it later with calling :
v.setVisibility(View.VISIBLE)
To reference button and textview from support layout you can use findViewById method on your included View (I'm not sure but I think it's even not mandatory, you can call it directly on your activity's view) :
View supportLayout = (View) findViewById(R.id.support_layout);
Textview txv = (TextView) findViewById(R.id.txt);
Button btn = (Button) findViewById(R.id.btn);
(if it's not working try with : Button btn = (Button) supportLayout.findViewById(R.id.btn);)
-- FYI --
When you give attributs to include tags it override ones of the included layout (there support_layout LinearLayout) so you don't need to do that
you must use like this includedLayoutId.viewId.visibility = View.GONE in this case you can access to included view, now for example:
loading.xml
<com.airbnb.lottie.LottieAnimationView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:lottie_autoPlay="true"
app:lottie_fileName="loading.json"
app:lottie_loop="true" />
in fragment_a.xml :
<include layout="#layout/loading"
android:id="#+id/anim_loading"
android:layout_width="match_parent"
android:layout_height="#dimen/_80sdp"/>
and finally use it animLoading.loading.visibility = View.GONE
Thanks to the new ConstraintLayout.
This is how I do it with widget.Group
<include
android:id="#+id/bottom_bar_action"
layout="#layout/bottom_bar_back_action"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<androidx.constraintlayout.widget.Group
android:id="#+id/bottom_bar_group"
android:layout_width="0dp"
android:layout_height="0dp"
app:constraint_referenced_ids="bottom_bar_action" />
Then you can hide the include layout by doing binding.bottomBarGroup.visibility = View.GONE. Cheers
// 1 - copy this
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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"
android:orientation="vertical"
tools:context=".Add">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="gone"
android:onClick="onclick_gone_include"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="visible"
android:onClick="onclick_visible_include"/>
<LinearLayout
android:id="#+id/support_layout"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="100dp"
>
<include
layout="#layout/support"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
//code
//2 copy this to Add cliass
//this methods on click in Add class
public void onclick_gone_include(View view) {
View v = (View) findViewById(R.id.support_layout);//view is the v
v.setVisibility(View.GONE);
}
public void onclick_visible_include(View view) {
View v = (View) findViewById(R.id.support_layout);
v.setVisibility(View.VISIBLE);
}
//3 activity that included 'support activity'
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
tools:context=".Add"
android:gravity="center"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="textview1"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="textview2"
/>
</LinearLayout>
Related
I'm having some weird affects when trying to animate view from gone to visible. See attached gif.
I have a simple Switch, that toggles visibility of TextView. When TextView changes to visible, there is an undesired animation-like affect on the Button.
I've figured this is something to do with R.id.group layout height. See layout below.
When I remove ScrollView, and change R.id.group layout height to match_parent, it works correctly. But that is not the solution, since I ultimately need a ScrollView.
How to avoid button animation effect?
Source code:
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Switch sw = view.findViewById(R.id.toggle);
TextView tv = view.findViewById(R.id.text);
sw.setOnCheckedChangeListener((button, isChecked) -> {
int visibility = isChecked ? View.VISIBLE : View.GONE;
tv.setVisibility(visibility);
});
}
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/white"
android:padding="10dp"
>
<LinearLayout
android:id="#+id/group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true"
android:orientation="vertical"
>
<Switch
android:id="#+id/toggle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="toggle"
/>
<TextView
android:id="#+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Blabla\nblabla\nblabla\nblabla"
/>
</LinearLayout>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Self destruct"
/>
</LinearLayout>
</ScrollView>
Managed to find out workaround on the world wide web after all. Props to Sam Chen's anwser.
Basically, I needed to set LayoutTransition (aka animateLayoutChanges="true") for R.id.group layout, where Button resides, and enable CHANGING transition:
LayoutTransition transition = new LayoutTransition();
transition.enableTransitionType(LayoutTransition.CHANGING);
groupLayout.setLayoutTransition(transition);
I got The specified child already has a parent. You must call removeView() on the child's parent first. ERROR.
But I do not want to remove the parent view.
If you click a button, a message must be added at the end of LinearLayout's childViews.
This is my Java code:
Button addBTN = findViewById(R.id.addButton);
LinearLayout messageListLL = findViewById(R.id.messageList_LinearLayout);
addBTN.setOnClickListener((v) -> {
MessageItem messageItem = new MessageItem();
View messageView = View.inflate(this, R.layout.item_message, messageListLL);
messageListLL.addView(messageView, messageListLL.getChildCount());
});
This is the part of activity's xml:
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#id/adView"
android:layout_below="#id/userContainer"
android:background="#CCC"
android:padding="15dp">
<LinearLayout
android:id="#+id/messageList_LinearLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<Button
android:id="#+id/addButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:backgroundTint="#color/design_default_color_primary"
android:text="ADD"
android:textColor="#android:color/white" />
</LinearLayout>
</ScrollView>
This is item_message.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left" />
<EditText
android:layout_width="300dp"
android:layout_height="wrap_content" />
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_gravity="right"
android:background="#FFD9D9" />
</LinearLayout>
So, I'd like to make a view with item_message and put it into LinearLayout in the activity's xml, which has messageList_LinearLayout for the id attribute.
The button is also in the LinearLayout. The button must be placed at the end of the LinearLayout.
And whenever, I click the button, a message view must be created and added at the end of the messageList and also before the button.
You can just change the third parameter into null.
View messageView = getLayoutInflater().inflate(this, R.layout.item_message, null);
messageListLL.addView(messageView, messageListLL.getChildCount() - 1)
The third parameter specifies its root view. You can inflate the messageView without any roots.
Using Xamarin.Android native in Visual Studio 2017.
Here is an example of my layout. Let's call it 'headache.axml'.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/topLinearLayoutId"
android:paddingLeft="20dp"
android:paddingTop="0dp"
android:paddingRight="20dp"
android:paddingBottom="15dp"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_width="match_parent"
android:onClick="showPasswordDialog"
android:orientation="horizontal" >
<TextView android:id="#+id/sampleId_0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView android:id="#+id/sampleId_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
. . . more views . . .
</LinearLayout>
And here is the code where I inflate this layout.
View view = inflater.Inflate(Resource.Layout.fragment_selection, container, false);
ViewStub stub = (ViewStub) view.FindViewById(stubIds[i]);
stub.LayoutResource = Resource.Layout.headache;
View inflatedView = stub.Inflate();
Then I can use inflatedView.FindViewById() to get any view from my layout except the top LinearLayout.
For example, these lines work perfect:
var txtView0 = (TextView) inflatedView.FindViewById(Resource.Id.sampleId_0);
var txtView1 = (TextView) inflatedView.FindViewById(Resource.Id.sampleId_1);
Both txtView0 and txtView1 are initialized.
And here is my problem, when I try to get the top View from my layout I get null:
var top = (LinearLayout) inflatedView.FindViewById(Resource.Id.topLinearLayoutId); // returns null
As a workaround,
I've added a pre-top LinearLayout to my 'headache.axml'. It's become like this:
<?xml version="1.0" encoding="utf-8"?>
<!-- workaround: pre-top LinearLayout (still inaccessible) -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/glitchyLinearLayout"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="horizontal">
<!-- workaround: accessible LinearLayout -->
<LinearLayout
android:id="#+id/topLinearLayoutId"
android:paddingLeft="20dp"
android:paddingTop="0dp"
android:paddingRight="20dp"
android:paddingBottom="15dp"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_width="match_parent"
android:orientation="vertical">
<TextView android:id="#+id/sampleId_0"
... all the same ... />
<TextView android:id="#+id/sampleId_1"
... all the same ... />
. . . more views . . .
</LinearLayout>
Now I can get my topLinearLayoutId.
var top = (LinearLayout) inflatedView.FindViewById(Resource.Id.topLinearLayoutId);
In this case, the top is initialized and my application works well.
But I'd like to understand why the hell I've got this problem.
I have a common layout (common.xml) which I want to include many times in another layout (layout_a.xml). But it only shows me just one time. Why?
common.xml
<merge xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#android:drawable/alert_light_frame">
<ImageView
android:layout_width="match_parent"
android:layout_height="150dp"
android:id="#+id/imageView"
android:src="#drawable/test"
android:scaleType="centerCrop" />
<TextView
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_below="#+id/imageView"
android:id="#+id/textView"
android:text="test"
android:layout_marginTop="10dp"
android:layout_marginRight="10dp"
android:layout_marginLeft="10dp" />
</RelativeLayout>
</merge>
layout_a.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="#layout/common" />
<include layout="#layout/common" />
</LinearLayout>
The ids when defined in XML must be unique. You are including two layouts that have views that contain the same id.
Here is how you would go about fixing it.
p.s. Unless there is more code that you are not including in your first layout file, that merge tag is useless.
As btse said, the ids in the XML must be unique.
It can be achieved in this way:
<include android:id="#+id/common1"
layout="#layout/common" />
<include android:id="#+id/common2"
layout="#layout/common" />
For information about how to access the elements inside those two included views, you can check out this blog post.
That's what I had done in my Project with Inflater.
test1is just a Layout made with a LinearLayout(Vertical) with text and a button and mainofferslayout in that case, the main layout with an image.
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_offers_display, container, false);
View inflatedLayout = inflater.inflate(R.layout.test1, (ViewGroup) view, false);
LinearLayout ll = (LinearLayout) view.findViewById(R.id.mainofferslayout);
ll.addView(inflater.inflate(R.layout.test1, (ViewGroup) view, false));
ll.addView(inflater.inflate(R.layout.test1, (ViewGroup) view, false));
ll.addView(inflater.inflate(R.layout.test1, (ViewGroup) view, false));
I fixed by setting the layout_height of the RelativeLayout to 250dp since they are overlapped.
I have the following layout.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="#style/list_item_bottom">
<TextView android:id="#+id/list_item_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<ViewStub android:id="#+id/stub_for_alt_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/list_item_name"
android:layout="#layout/text_view_alt_name"/>
<ImageView android:id="#+id/list_item_dopinfo1_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/stub_for_alt_name"
android:src="#drawable/ic_released"/>
</RelativeLayout>
I want ViewStub to be below TextView and ImageView to be below ViewStub.
Elements with ViewStub inflated are shown as I expect.
But elements without ViewStub have TextView overlapped with ImageView.
What's wrong with my layout?
UPDATE:
The only solution I've found is to give ViewStub and related TextView the same android:id value.
I know it's a bit of an old question but the trick in there is to set the inflatedId parameter to the same as the actual viewStub itself, like this:
<ViewStub android:id="#+id/stub_for_alt_name"
android:inflatedId="#id/stub_for_alt_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/list_item_name"
android:layout="#layout/text_view_alt_name"/>
The only solution I've found is to give ViewStub and related TextView the same android:id value.
It's an old question, but I've got a useful addition
1) Yes, like others have posted - use same id and inflatedId:
<ViewStub
android:id="#+id/view_stub_id"
android:inflatedId="#id/view_stub_id"
...
/>
2) When you need to inflate view or refresh its content it's convenient to act like this:
View v = parentView.findViewById(R.id.view_stub_id);
if (v instanceof ViewStub)
v = ((ViewStub) v).inflate();
// here v is always the inflated view
// ...
Hi you can try this one.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="#style/list_item_bottom">
//you can add another relative layout containing your textview and imageview
<RelativeLayout
android:id="#+id/layout_content"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView android:id="#+id/list_item_name"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<ImageView android:id="#+id/list_item_dopinfo1_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/stub_for_alt_name"
android:src="#drawable/ic_released"
android:layout_below="#+id/list_item_name" />
</RelativeLayout>
<ViewStub android:id="#+id/stub_for_alt_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/list_item_name"
android:layout="#layout/text_view_alt_name"
android:layout_below="#+id/layout_content" />
</RelativeLayout>