Android - How to get ripple effect on GridView items? - android

I have implemented image gallery using GridView. The layout for the grid item:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:descendantFocusability="blocksDescendants" >
<ImageView
android:id="#+id/media_item"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="#string/thumbnail_for_image"
android:scaleType="centerCrop" />
<View
android:id="#+id/overlay_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackground" />
</FrameLayout>
My goal is to get this nice material ripple effect upon touching the grid item.
Unfortunately, I couldn't manage to find pure solution for my problem.
So I came up with using this, as author says, work around - adding overlay View on top of main ImageView, and setting background to
?attr/selectableItemBackground
Putting it to ImageView's background or parent FrameLayout background didn't work.
I'm sure, there must be a better way to handle it.

android:drawSelectorOnTop="true" in GridView did the trick

If you want this ripple to be supported in pre-lollipop versions I suggest you to use ripple libraries like The ones here. I guess using ?attr/selectableItemBackground won't give you ripple on pre-L androids.

Related

Strange shadow behavior during `alpha` animation

Have recycler with CardView items. When screen open - I start alpha animation on recycler :
recyclerView.animate().alpha(1f).setStartDelay(300).start()
Recycler item:
<android.support.v7.widget.CardView
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="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="6dp"
android:layout_marginEnd="20dp"
android:layout_marginBottom="6dp"
app:cardCornerRadius="10dp"
app:cardElevation="4dp">
...
</android.support.v7.widget.CardView>
Problem that while this animation running the shadow of CardView directed to the up but when animation ends shadow change direction to the bottom (as normal)
Problem was found only on Android 9.
P.S. sorry for my english)
I have found a partial fix,
If you add android:layerType="hardware" to the parent view the shadow no longer flips direction.
The down side is the shadow permanently points in the wrong direction.
Found a workaround.
Make sure the alpha-animation targets on CardView itself instead of its parent and its parent's alpha must be 1F.
This work in my case.
Hope it can help you too.

selectableItemBackground and other Drawables disappear when there is an ImageView behind

My View hierarchy looks like this:
<RelativeLayout>
<ImageView
android:id="#+id/my_background_image"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
androd:id="#+id/my_image"
android:clickable="true"
android:foreground="?attr/selectableItemBackground" />
</LinearLayout>
</RelativeLayout>
If I set an image Drawable to my_background_image, the ripple drawable provided by ?attr/selectableItemBackground over my_image disappears. It doesn't matter what image I use, the ripple is completely gone. I've also found that the background (which includes the down arrow) of any "foreground" Spinner also disappears.
This is very strange behaviour. Does anyone know why this is happening?
Edit: I'd like to add that the ripple appears as long as src="..." is not included in the background ImageView or setImageDrawable() is not called on it.
Setting a transparent background to the LinearLayout solves the problem.
"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" from This Answer

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" />

Etsy's Android Staggered Gridview - drawSelectorOnTop

I'm trying to use Etsy's Staggered Gridview (https://github.com/maurycyw/StaggeredGridView), and I have it working mostly as expected, except I'm having an issue trying to get the selector to draw on top.
I've tried using mGridView.setDrawSelectorOnTop( true ); and android:drawSelectorOnTop="true" in the layout, but no success yet. Anyone happen to have solved this problem, or know if it's not possible with the library in its current state?
Etsy's StaggeredGrid frustratingly doesn't support item selector drawables. To work around this, set the selector on the GridView item, not the GridView itself.
In my current project, I wrap the GridView item in a FrameLayout, because a FrameLayout has an android:foreground attribute:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:foreground="?android:attr/selectableItemBackground">
<!-- Your item layout goes here. -->
</FrameLayout>
?android:attr/selectableItemBackground gives you the standard blue highlight. If you want, you can use your own state list drawable instead.

Overlapping Views in Android

Is it possible to have overlapping views in Android? I would like to have an ImageView with a transparent png in the front and another view in the background.
edit:
This is what I have at the moment, the problem is that the image in the imageView is not transparent, the parts that should be transparent are just black.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/gallerylayout"
>
<Gallery android:id="#+id/overview"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<ImageView android:id="#+id/navigmaske"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:src="#drawable/navigmask"
/>
</RelativeLayout>
edit:
I got it to work, it was a theme file from another programmer on the team.
Just changed this
<item name="android:background">#FF000000</item>
to this
<item name="android:background">#00000000</item>
Android handles transparency across views and drawables (including PNG images) natively, so the scenario you describe (a partially transparent ImageView in front of a Gallery) is certainly possible.
If you're having problems it may be related to either the layout or your image. I've replicated the layout you describe and successfully achieved the effect you're after. Here's the exact layout I used.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/gallerylayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Gallery
android:id="#+id/overview"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<ImageView
android:id="#+id/navigmaske"
android:background="#0000"
android:src="#drawable/navigmask"
android:scaleType="fitXY"
android:layout_alignTop="#id/overview"
android:layout_alignBottom="#id/overview"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</RelativeLayout>
Note that I've changed the parent RelativeLayout to a height and width of fill_parent as is generally what you want for a main Activity. Then I've aligned the top and bottom of the ImageView to the top and bottom of the Gallery to ensure it's centered in front of it.
I've also explicitly set the background of the ImageView to be transparent.
As for the image drawable itself, if you put the PNG file somewhere for me to look at I can use it in my project and see if it's responsible.
Also, take a look at FrameLayout, that's how the Camera's Gallery application implements the Zoom buttons overlay.
If you want to add your custom Overlay screen on Layout, you can create a Custom Linear Layout and get control of drawing and key events. You can my tutorial- Overlay on Android Layout-
http://prasanta-paul.blogspot.com/2010/08/overlay-on-android-layout.html
The simples way arround is to put -40dp margin at the buttom of the top imageview
A visible gallery changes visibility which is how you get the gallery over other view overlaps. the Home sample app has some good examples of this technique.
Now with Jetpack Compose in android, you should use Box for overlapping views.
Example.
Box(modifier = Modifier.fillMaxWidth().fillMaxHeight()){
RecipesList(viewModel.recipes.value)
Snackbar()
}
Here RecipesList and Snackbar are composabes positioned one on top of the other in the composition order
Check out this for Jetpack Compose samples - https://androidlearnersite.wordpress.com/2021/08/03/jetpack-compose-1-0-0-sample-codes/
Yes, that is possible. The challenge, however, is to do their layout properly. The easiest way to do it would be to have an AbsoluteLayout and then put the two images where you want them to be. You don't need to do anything special for the transparent png except having it added later to the layout.

Categories

Resources