I started using ConstraintLayout a few weeks ago and I am finding (I believe) that it has many bugs. One huge issue is that I cannot set view visibilities. The following code does not work:
<TextView
android:visibility="gone"
android:id="#+id/sampleView"
style="#style/RSTextView"
android:layout_width="0dp"
android:text="sample text"
android:textSize="20dp"
android:shadowColor="#00000000"
app:layout_constraintStart_toEndOf="#+id/privacyPolicyText"
app:layout_constraintTop_toBottomOf="#+id/enterAgreementText1" />
You can see I've marked it as "gone", but when I run and inspect the view using the layout inspector, visibility is STILL set to visible. I've had to come up with hacky solutions to this involving setting the alpha to 0 and isEnabled to false when I want a view to be gone and vice versa. When I try to set the visibility programmatically, I have the same issue:
sampleView.visibility = ConstraintLayout.GONE
This still results in a visible view. This is driving me nuts because I'm forced to make multi-line hacky solutions. Any help would be appreciated.
Be careful using Groups in Constraint Layout. Main things to note while using groups are
Group's visibility overrides normal view's visibility
If the group's visibility is unset, it defaults to visible and overrides your view's visibility.
While using Constraint Layout be careful in using Groups. I think almost all visibility issues in constraint layout are caused by groups.
I don't know if the below links I found are related to your problem:
https://issuetracker.google.com/issues/37151322
https://issuetracker.google.com/issues/37139335
https://issuetracker.google.com/issues/37138937
but they are all filed reports about problems/bugs concerning the visibility of views inside a ConstraintLayout.
Check them.
#Pavan Varma pointed out that Group visibility overrides the view's visibility. I thought that if the groups visibility was unset, it wouldn't override anything, but it still does. If you're having issues with visibility in ContraintLayouts, pay close attention to its group's visibility that overrides it. If the group's visibility is unset, it defaults to visible and overrides your view's visibility.
Related
i am getting "Set android:baselineAligned="false" on this element for better performance" while using LinearLayout, I know its regarding performance,but i dont know exactly why it is,please clarify me
If you are looking for a visual explanation like me, then you might find this useful.
When baselineAlign is enabled(i.e if it is set to true), then all the text in that line will be aligned to have the same baseline.
Note: By default, baselineAligned is set to true. (i.e. baselineAligned=true)
When you make baselineAligned=false, all it needs to do is to add new elements to the linear layout and be done with it. The app need not worry about where the baseline of other elements in the layout is.
See the image below for more clarity
android:baselineAligned/setBaselineAligned(boolean): When set to false,
prevents the layout from aligning its children's baselines.
So can take example with linear layout with horizontal child views having multiple TextView with different text size or different views like button there basealignment would be different and you cannot adjust it to have same basealignment if you set it to false
Reference
Update:
By setting android:baselineAligned="false" , you're preventing the extra work your app's layout has to do in order to Align its children's baselines; which can obviously increase the performance. (Less unnecessary operations on UI => Better performance) as mentioned here
I have a nested layout like the following:
<LinearLayout> <!----Parent layout--->
<LinearLayout> <!-----child 1--->
...
</LinearLayout> <!----child 1 ended--->
<LinearLayout> <!-----child 2--->
...
</LinearLayout> <!----child 2 ended--->
</LinearLayout> <!----Parent endded--->
The problem I am having now is that since all my data items are within child 1 or child 2 Linearlayout, if I add or delete a item the child linearlayout will animated with the effect of animateLayoutChanges but the parent layout will not do any animation. (I have android:animateLayoutChanges set to true for all linear layouts). Especially when I delete an item within child 1 the animation effect becomes weird (basically child 2 will jump up while child 1 is still doing its animation).
Does anybody have any idea how to solve this?
Thanks
UPDATE
Shortly after I posted this question, I found this on android developer's site in the LayoutTransition API.
Using LayoutTransition at multiple levels of a nested view hierarchy may not work due to the interrelationship of the various levels of layout.
So does anyone have any work around suggestions for this issue?
The animateLayoutChanges property makes use of LayoutTransitions, which animate both the layout's children and, from Android 4.0 onward, ancestors in the layout hierarchy all the way to the top of the tree. In Honeycomb, only the layout's children will be animated. See this Android Developers Blog post for details.
Unfortunately, it seems that there's currently no simple way to have the siblings of a layout react to its LayoutTransitions. You could try using a TransitionListener to get notified when the layout's bounds are being changed, and move the sibling views accordingly using Animators. See Chet Haase's second answer in this Google+ post.
EDIT - Turns out there is a way. In Android 4.1+ (API level 16+) you can use a layout transition type CHANGING, which is disabled by default. To enable it in code:
ViewGroup layout = (ViewGroup) findViewById(R.id.yourLayout);
LayoutTransition layoutTransition = layout.getLayoutTransition();
layoutTransition.enableTransitionType(LayoutTransition.CHANGING);
So, in your example, to have child 2 layout animated, you'd need to enable the CHANGING layout transformation for it. The transformation would then be applied when there is a change in the bounds of its parent.
See this DevBytes video for more details.
Ok, after digesting the first answer, I make it simple here, for those who don't get proper animation result when using android:animateLayoutChanges="true" in NESTED layout:
Make sure you add android:animateLayoutChanges="true" to the will-be-resized ViewGroup (LinearLayout/RelativeLayout/FrameLayout/CoordinatorLayout).
Use setVisibility() to control the visibility of your target View.
Listen carefully from here, add android:animateLayoutChanges="true" to the outer ViewGroup of your will-be-resized ViewGroup, this outer ViewGroup must be the one who wraps all the position-changing View affected by the animation.
Add following code in your Activity before the setVisibility(), here the rootLinearLayout is the outer ViewGroup I mentioned above:
LayoutTransition layoutTransition = rootLinearLayout.getLayoutTransition();
layoutTransition.enableTransitionType(LayoutTransition.CHANGING);
Before:
After:
Reminder: If you miss the 3rd step, you will get null pointer exception.
Good luck!
As a Kotlin Extension
fun ViewGroup.forceLayoutChanges() {
layoutTransition.enableTransitionType(LayoutTransition.CHANGING)
}
Usage
someContainer.forceLayoutChanges()
Notes:
In my experience, this happens when the container is a deep nested layout. For some reason android:animateLayoutChanges="true" just doesn't work, but using this function will force it to work.
We had added the android:animateLayoutChanges attribute to our LinearLayout but the change didn’t trigger an animation. To fix that, use this code:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
((ViewGroup) findViewById(R.id.llRoot)).getLayoutTransition()
.enableTransitionType(LayoutTransition.CHANGING);
}
More details.
It seems that a delayed transition on the parent also works for animating. At least for me the following code gives a proper expand/collapse animation.
expandTrigger.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
TransitionManager.beginDelayedTransition(parentLayout);
expanded = !expanded;
child1.setVisibility(expanded ? View.VISIBLE : View.GONE);
}
});
For deeply nested layouts you sometimes might need to use a parent higher up in the hierarchy in the call to the TransitionManager.
I had a similar issue:
I was using a animatelayoutchanges in one of my activity with a recycler view, I also added some custom layout transition because I wanted to increase speed of the animation while an item disappears in the list. It was working fine when it was not in a nested layout.
I had used the same adapter for another recyclerview which was in a nested layout. It was not working and I tried all the above solutions, None worked for me.
The real reason was, I forgot to set
mTicketsListAdapter.setHasStableIds(true);
in the nested layout activity. And after setting setHasStableIds to true, the animations was working perfectly in the nested layout.
I have an Autocompletetextview dropping down the suggestions list, up to the border of the soft-keyboard.
Then, when scrolling over the suggestions list:
- (in a gingerbread phone) the drop-down-menu automatically increases height covering the keyboard, which is nice since it shows more items.
- (in an ICS emulator) the drop-down-menu does not increase height over the keyboard.
Is this related to some system property?
Is there a way to force the first behavior also in ICS?
Just add android:dropDownHeight="100dp" to the AutoCompleteTextView tag in your layout file, it will work.
Let me explain my little trick to avoid that the "drop-down" displays behind the keyboard. The trick is with the dropDownAnchor property.
The solution is set the anchor with a view located on the top of the screen, so the menu will leave from that position, and therefore, will not be covered by the keyboard. For example:
android:dropDownAnchor="#+id/topview"
I know that is an ugly solution but this control is too limited.
You can also use android:dropDownAnchor="#id/ to anchor the dropdown to a view.
Just add getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); to your fragment or activity
A simple solution that works perfectly with all resolutions is to use the android:dropDownAnchor property with a resource ID that references your activity toolbar.
<my.app.ContactAutoCompleteTextView
android:id="#+id/autocomplete_textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="top"
android:dropDownAnchor="#id/appbar"
android:inputType="text|textMultiLine|textCapSentences|textAutoCorrect"
android:paddingBottom="12dp"
android:textColor="#color/text_primary"
android:textColorLink="#color/secondary"
android:textSize="#dimen/text_medium" />
You need to do two things.
First, adjust the soft input mode of that activity in the manifest.
android:windowSoftInputMode="stateHidden|adjustResize"
This ensures views are laid out again when the keyboard is shown. Then, set a global layout listener in your oncreate on the top level view to do the dropdown height calculation when the layout changes. Adjust the dropdown height to be the height of everything below the keyboard, minus some padding if you want.
v.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
autoCompleteView.setDropDownHeight(view2.getHeight());
}
Where view2 is the view/layout that includes everything below the autocompleteview.
If none of the above solutions worked. try this
android:dropDownHeight="match_parent"
or
android:dropDownHeight="500dp"
If we didn't mention the dropdown height, it would be considered wrap_content. Therefore the item will show behind the soft keyboard.
Setting two or more elements of a linear layout the same height seems to be a great problem.
I want to set four buttons in a row to the same height.
android:layout_height="wrap_content" does it for the moment but when the text on one of the buttons is longer than one line this button is increased and therefore bigger than the other ones. Due to different localisations I don't know, when and which button may have a second line.
So my idea is, to set the parent linearlayout to android:layout_height="wrap_content" and all (!) child heights to android:layout_height="fill_parent".
This works (all buttons have the same size), but I'm not sure if this causes any other problems? Because it the parent gets it's height from the childs and vice-versa.
In theory what you are describing should not work ("Because it the parent gets it's height from the childs and vice-versa".) However, we made it work in LinearLayout because it was a very common use case. I recently added similar support to FrameLayout (this feature should be part of Honeycomb.) What you are doing is therefore perfectly valid and will work just fine.
That doesn't make sense :(
Why don't you use android:singleLine="true" and some ellipsode?
When I use a RelativeLayout with either fill_parent or wrap_content as height and an element which specifies: android:layout_alignParentBottom="true" it is ignored and it is aligned at the top. Setting the height of the RelativeLayout to an explicit value makes it work. Any clues?
This seems to be a bug in Android itself, see http://code.google.com/p/android/issues/detail?id=1394.
I worked around it by wrapping my RelativeLayout in a FrameLayout and putting my bottom aligned view as a children of the FrameLayout with android:layout_gravity="bottom". This hinders you from referencing it from within the RelativeLayout so you'll have to work around that (for example using margins).
If anyone has a better workaround, please share.
When you inflate the layout, use inflate(R.layout.whatever, parent, false), where parent is the ListView. If you don't do that (e.g., you pass null for the parent), RelativeLayout gets strange in list rows.
My hack for this andriod bug:
ViewGroup.LayoutParams lp=(ViewGroup.LayoutParams)view.getLayoutParams();
lp.height=view.getContentHeight();//hack for android bug about ViewGroup.LayoutParams.WRAP_CONTENT and android:layout_alignParentBottom="true" on landscape orientation
view.requestLayout();
act.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
I was able to get the proper alignment by specifying the problematic TextView with:
android:id="#+id/must_be_bottom_left"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:layout_below="#id/xxx"
where xxx was the id of a TextView that has android:layout_below="#id/yyy"
and yyy is a TextView that is always above both xxx and must_be_bottom_left.
The contents of my list items can vary so that sometimes the "xxx" TextView is View.GONE, but even then the layout works as expected.
I don't know how fragile or merely seredipidous this work-around is. I am using Android 1.6 and I haven't tested it for forward compatability.