Button hides other elements behind it when clicked - android

I'm working on the UI of my project, specifically I'm in a compound view extending a FrameLayout. Inside it I have two buttons, one (the smaller one) on top of the other (the larger one). I managed to make the smaller button be always on top with the 'android:elevation' property. The problem is that when I run the app and I click on the larger button, it hides the smaller one behind it, despite having a lower elevation property. I want the smaller one to be always on top even if the user clicks on the other button, but I can't manage to make it work.
Here is the xml:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="80dp"
android:layout_height="80dp"
android:padding="0dp"
android:layout_margin="0dp">
<Button
android:layout_width="match_parent"
android:layout_height="match_parent"
android:insetTop="0dp"
android:insetBottom="0dp"/>
<Button
android:layout_width="20dp"
android:layout_height="30dp"
android:backgroundTint="#color/black"
android:layout_gravity="bottom|end"
android:insetTop="0dp"
android:insetBottom="0dp"
android:elevation="10dp"/>
</FrameLayout>

you may try to set up translationZ instead elevation (or next to it) - translationZ is intended to be "fixed" elevation and elevation is dynamic, can be animated. note that every Button has a stateListAnimator set up, which is overriding elevation parameter in default implementation. check out what it does in HERE
easy way to fix would be to set for both Buttons android:stateListAnimator="#null", but you will loose some anims when click occur
easiest way would be to have one FrameLayout, inside two additional FrameLayouts and inside each one Button - fastest, but unelegant and not so efficient (but still for two buttons it won't be noticeable)

Related

Android xml avoid overlap constraintLayout border radius by child constraintLayout

I have some issue with follow structure:
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/white_rectangle_radius10">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/first"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
/// many views here
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/second"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="#id/first"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
/// many views here
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/third"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="#id/second"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
/// many views here
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Programatically it can be 3 inner constraints or 4 or 2.
Root Constraint has round border radius.
Programatically when one of inner items clicked I set to this item background color, BUT when its first or last it overlap root border radius.
Note:
No need to suggest cardview as root element (not my option)
"Smart play" with margins/paddings also doesn't suit me because it should be changed programatically.
Is there some option to do it via XML?
When I added background color to first element it's top start/end corners not rounded.
First it is not recommended to nest layouts if you are going to use constraintLayout.
Second is how to design your view smoothly?
one of constraintlayout benefits is using the drag and drop option, therefore, start by doing that and ensure to place every item in its right place (but do not apply any constraint yet).
once all items are on the layout, click any item and look at the tool bar above the mobile screen, there is a magic wound, click on it, the constraint will be generated automatically based on the way you orgnized the view on the screen.
once that is done, now you might need to adjust the margins a bit according to the requirements.
also please assign id to each view before clicking the magic wound.
I hope I was helpful.

Android Uneven Design

I have an element that should remain centered in the layout and a button on the right size. The button width is variable.
The following design exemplify two scenarios.
Scenario 1: Long text button
Scenario 2: Small text button
The current solution is have an invisible duplicated button on the left. This is not ideal because the button look and feel may also vary for different locales. I have tried guidelines but that would require to define a percentage and I would prefer if it was dynamic. Barriers don't seem to work either because I would need them to be mirrored.
Any tips how to achieve this?
Try doing width with 0dp and give them weight and change this in runtime
may be they are in linear layout which is horizontal.
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)
button.getLayoutParams();
params.weight = 1.0f; // afterwards you can do the same with changing the weight
button.setLayoutParams(params);
Perhaps you can take advantage of the ConstraintLayoutStates:
https://riggaroo.co.za/constraintlayout-constraintlayoutstates/
And have two layouts one for each scenario.
I ended up using a different solution. I used two guidelines, one at 20% and another at 80%, to define the areas where the button could expand to.
When no button is available, I used the property app:layout_constrainedWidth="false" that ignores the constrainst and allow the title to expand to the available space.
I used this solution because I may need multiple buttons with different call to actions according to the selected language. It would be difficult to manage multiple hidden anchor buttons.
If I understand your pictures correctly, you want to have two elements on your screen:
A View that's centered on the screen, it can be any width size.
A Button that's positioned to the right of the View that can also be any width size. You want this button to be centered in the empty space between the View and the edge of the right screen.
You can try this:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<TextView
android:id="#+id/view"
android:layout_width="100dp"
android:layout_height="100dp"
android:gravity="center"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:text="1"
android:textColor="#FFFFFF"
android:background="#000000"
/>
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="#+id/view"
app:layout_constraintEnd_toEndOf="parent"
android:text="2"
/>
</androidx.constraintlayout.widget.ConstraintLayout>

Material ripple effect hidden by other view in layout

I added a ripple effect on a ImageButton, however it is hidden by an ImageView used as a background for the parent view RelativeLayout.
Here's the layout file:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="172dp"
android:orientation="vertical"
android:theme="#style/ThemeOverlay.AppCompat.Dark">
<ImageView
android:id="#+id/drawerBackgroundImageView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="#drawable/drawer_background"/>
[...]
<ImageButton
android:id="#+id/drawerLogoutButton"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_alignBottom="#id/drawerEmailTextView"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_marginEnd="#dimen/activity_horizontal_margin"
android:layout_marginRight="#dimen/activity_horizontal_margin"
style="#style/FlatButtonStyle"
android:scaleType="centerInside"
android:src="#drawable/ic_logout_white_24dp"/>
</RelativeLayout>
(there's a bunch of other views but they're irrelevant here)
I'm using an ImageView as the background for the RelativeLayout as I need to set a specific scaleType for the image, so I can't use the basic android:background property.
The ripple effect is hidden as it doesn't have a mask layer (I want it to extend out of the button's bounds) and thus uses the ImageButton's parent view to be displayed. The effect is perfectly visible if I remove the ImageView.
Is there a way to get the ripple effect to be shown above the problematic ImageView?
I had exactly the same issue and solved it using this thread: https://code.google.com/p/android/issues/detail?id=155880
Issue preview:
Before solved:
After solved:
Explanation:
"Borderless buttons draw their content on the closest background. Your button might not be having background between itself and the ImageView, so it draws underneath the ImageView."
Solution:
"Use a transparent background (android:background="#android:color/transparent") on some layout containing the button (beneath the ImageView). This will dictate what the maximum bounds of the ripple effect is."
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
...>
<!-- Your background ImageView -->
<ImageView
android:id="#+id/drawerBackgroundImageView"
android:src="#drawable/drawer_background"
... />
<!-- ... -->
<!-- HERE, you need a container for the button with the transparent
background. Let's say you'll use a FrameLayout -->
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#android:color/transparent">
<!-- Maybe more items -->
<!-- Button with borderless ripple effect -->
<ImageButton
android:id="#+id/drawerLogoutButton"
android:background="?selectableItemBackgroundBorderless"
... />
</FrameLayout>
</FrameLayout>
Hope it helps.
I am experiencing same issue. Only solution I have found so far is not 100% okay since ripple is masked by view (its not borderless).
The solution (workaround):
surround your ImageButton with other view and set ripple to the foreground instead of the background in your layout like this:
<ImageView ... />
<FrameLayout
...
android:clickable="true"
android:focusable="true"
android:foreground="?attr/selectableItemBackgroundBorderless" >
<ImageButton />
</FrameLayout>
I would be really glad if someone explain why the ripple is drawn behind the image. Also if you look at Google Photos app, in image detail they have transparent icons over image view with ripple. I would like to replicate this, but I am not able to make the ripple to be in foreground. Does anybody know how to put transparent imagebuttons over everything but still have the ripple?
EDIT final solution
here you can find exactly same question link
with great explanation what is happening. the solution is the same but on top of that it solves rectangular mask by adding
android:clipChildren="false"
android:clipToPadding="false"
to your layout. now your ripple should be borderless (it worked for me).
The layout xml could be something like this:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
...
android:clipChildren="false"
android:clipToPadding="false">
<ImageView ... />
<FrameLayout
...
android:clickable="true"
android:foreground="?attr/selectableItemBackgroundBorderless">
<ImageView ... />
</FrameLayout>
</FrameLayout>
I'm aware this is an old post but I did struggle with this quite a bit today hence I'm posting what I was finally able to figure out and maybe someone else might benefit from it. One key emphasis beforehand, please do always RTFM!
1) The story
I aimed to use the unbounded ripple effect on Tab Items and consequently have it spread all over the AppBarLayout area. I had applied #android:color/transparent to TabLayout as the first wrapping parent and gave AppBarLayout a background color, nevertheless the ripple was still being cut off right at the borders of TabLayout's height.
2) The moral of the story (RTFM)
So I run to the nest of Android knowledge: The Documentation, and spotted this:
?android:attr/selectableItemBackgroundBorderless for a ripple that extends beyond the view. It will be drawn upon, and bounded by, the nearest parent of the view with a non-null background.
3) The course of action
Using Layout Inspector, I realized that #android:color/transparent although transparent (duh!) it actually assigns 0 as the value of the bg attribute of a View, but zero is not null hence the ripple gets bounded at the nearest parent.
4) The conclusion
With that in hand, I went and set the android:background property of my TabLayout to #null rather than transparent, and now I have a fancy little ripple spread onto the area of the AppBarLayout.
5) Outro: **ANDROID & SO FTW!
Props to everyone in this post who shed light on the matter in word. Cheers!
After wrapping ImageButton inside FrameLayout, I was getting rectangular shape on touch. Applied background with oval shape on FrameLayout and got the circular shape on touch.
Had the same issue. Used the solutions described above and worked. Managed to avoid the wrapping FrameLayout by setting foreground as ?attr/actionBarItemBackground and background as #null.
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center|end"
android:background="#null"
android:contentDescription="#string/app_name"
android:foreground="?attr/actionBarItemBackground"
android:padding="#dimen/small_margin"
android:src="#drawable/ic_clear_text_icon" />

Extend UI of an View

I would like to extend the UI of AutoCompleteTextView. The Functionality is fine, all I need is to add an button to the right that looks like a drop-down button. Sadly AutoCompleteTextView has a 'natural' margin that I can't reduce to 0.
What can I do now?
Dose I have to overwrite onDraw() & onMeasure() to archive my goal (is there an easier way)?
You could put both AutoCompleteTextView and button onto FrameLayout, add some extra margin right to AutoCompleteTextView to make FrameLayout slightly bigger, and align button to parent right. In fact, these 2 views will interfere, but for user they will appear one next to the other w/o any margin.
Another option could be to set custom background to AutoCompleteTextView (probably modified original one taken from Android source with removed margin).
Just remembered that you can supply negative margin. You can put both views onto LinearLayout and set left margin of button to -5dp for example. However, you will still have to supply custom marginless background for button.
you can use RelativeLayout to put Button to the right of AutoCompleteTextView
Sample
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/btn_close_pressed"
android:layout_alignParentRight="true"
android:id="#+id/myBtn"
></Button>
<AutoCompleteTextView android:id="#+id/myautocomplete"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:completionThreshold="1"
android:layout_toLeftOf="#+id/myBtn"
/>
</RelativeLayout>

Android Linear Layout gives me headache

I've got the following xml file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/linearLayout1"
android:background="#android:color/transparent"
android:layout_marginTop="0px"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:weightSum="1"
android:orientation="horizontal">
<Button android:id="#+id/info" android:text="Info" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom"></Button>
<Button android:id="#+id/town" android:text="Town" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom"></Button>
<Button android:id="#+id/unit" android:text="Unit" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom"></Button>
<Button android:layout_height="wrap_content" android:text="EndTurn" android:id="#+id/endturn" android:layout_width="wrap_content" android:layout_gravity="bottom"></Button>
</LinearLayout>
which provides the following result: http://i42.tinypic.com/otdkb4.png
Now I've got some questions about this:
The top and bottom padding, how to get rid of it?
I tried RelativeLayout, multiple layouts within each other, padding, margin, changing height nothing seem to affect it in any way.
Is there a way to get the layout transparent? android:background seems to be the wrong one.
Between the third and the fifth button is a bit more space (where the fourth button should be). I catch it the in the program and set it to invisible.
unitButton.setVisibility(INVISIBLE);
unitButton.setWidth(0);
Now the space between the two buttons is more than double of the normal range (between 1 and 2) Any idea on this? - Altough this is a minor problem
Thanks in advance.
1: Is the layout presented in a Dialog? If so, that'll give you some headaches. To get more control you should either create your own custom Dialog extension (as some dialog layout values are hardcoded), or display your layout in another way (a new activity on top, or using a framelayout perhaps)?
2: To get a layout transparent, simply don't give it a background-attribute. (Though, if you really are using a dialog, the dialog box is not transparent, and it is that which you see. You can also set it to be transparent by setting background to "#00000000" (which is what you do).
3: A View with visibility as "invisible" is still measured, that means both its width/height as well as its margins and padding is displayed as empty space in your layout. Setting the visibility to "gone" instead will not measure it, and you won't need the setWidth(0) either. (You can still display it later by setting it back to "visible")
Edit: removing the unused "weightSum" attribute might also be a good idea, as the view is now expecting its children to have a total weight of something other than 0.

Categories

Resources