9

I am trying to add touch feedback to a LinearLayout that is similar to a regular Button's feedback in API level 21, much like in this example, and have been so far unsuccessful.

I have defined a standard ripple drawable like this:

<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:colorControlHighlight">

<item android:id="@android:id/mask">
    <shape android:shape="rectangle">
        <solid android:color="?android:colorAccent" />
    </shape>
</item>

and used the StateListAnimator that Google provides here:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true" android:state_pressed="true">
    <objectAnimator
        android:duration="@android:integer/config_shortAnimTime"
        android:propertyName="translationZ"
        android:valueTo="@dimen/touch_raise"
        android:valueType="floatType" />
</item>
<item>
    <objectAnimator
        android:duration="@android:integer/config_shortAnimTime"
        android:propertyName="translationZ"
        android:valueTo="0dp"
        android:valueType="floatType" />
</item>

After defining the animator and ripple drawable, i've added them to my LinearLayout like so:

<LinearLayout
    android:id="@+id/linearLayout"        
    android:clickable="true"
    android:focusable="true"
    android:orientation="horizontal"
    android:background="@drawable/ripple"
    android:stateListAnimator="@anim/touch_elevation">

The idea is to use this LinearLayout as a button, as it is much simpler for me to insert various types of text and handle ImageView positioning inside it (as opposed to button drawables).

Adding the ripple effect or the animation separately works, so long as the background of the view has no transparency as per this question.

I am not sure if this is an issue related to the above mentioned question, but seeing as the standard button manages to employ both ripple and elevation animation feedback, I figure that achieving this effect is possible on other views as well.

Any insight into this problem would be greatly appreciated.

Community
  • 1
  • 1
Rakatan
  • 451
  • 4
  • 17
  • If you are expecting the ripple effect to be applied when the user taps on your `LinearLayout`, you need to use an appropriate `StateListDrawable`, not directly referencing your ``. – CommonsWare Jan 28 '15 at 12:34
  • Your existing background says "show a ripple immediately". That seems like a curious choice. The background of a `Button` is a `StateListDrawable`, to use different images for normal, pressed, disabled, focused, etc. You would need to do the same thing. – CommonsWare Jan 28 '15 at 12:41
  • I think i get you but oddly enough, as I mentioned in my question, if I only specify the ripple as the background, it works as intended. – Rakatan Jan 28 '15 at 12:47
  • What effect happens with both? – GPack Jan 28 '15 at 17:43
  • No effect whatsoever – Rakatan Jan 29 '15 at 10:29
  • RippleDrawable handles both pressed and focus state. You don't need to use a StateListDrawable. What do you mean by, "the background of the view has no transparency"? Aren't you using the ripple as the background? – alanv Jan 29 '15 at 23:01
  • Also, the mask is just used as an alpha channel. You can use rather than a shape drawable. – alanv Jan 29 '15 at 23:03

2 Answers2

3

Use ForegroundLinearLayout. It allows to put ripple or any another drawable in foreground of view. The same way you can create ForegroundRelativeLayout etc. (just make this class extend from RelativeLayout).

Here is example with your stateListAnimator and ripple drawable:

<your.package.ForegroundLinearLayout
    android:layout_width="300dp"
    android:layout_height="300dp"
    android:layout_centerInParent="true"
    android:gravity="center"
    android:foreground="@drawable/bg_ripple"
    android:background="#fff"
    android:clickable="true"
    android:stateListAnimator="@animator/animator_elevation">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello world!"/>

</your.package.ForegroundLinearLayout>

Result:

enter image description here

EDIT: ForegroundLinearLayout exists in support design library. So you can just use android.support.design.internal.ForegroundLinearLayout

Community
  • 1
  • 1
ashakirov
  • 12,112
  • 6
  • 40
  • 40
1

Both effects work togheter without android:id="@android:id/mask"attribute in the ripple's item element (maybe this attribute adds some transparency ).

GPack
  • 2,494
  • 4
  • 19
  • 50
  • Indeed both the effects work together without the mask. It is clearly that same transparency issue then. I am sorry but i can't use your solution, since i was looking to apply both effects on any item. Using this solution on a CardView for example (where the ripple must be the foreground), renders the entire content of the view invisible. – Rakatan Jan 29 '15 at 16:19
  • I never thought android:id/mask could be the cause of elevation not showing for my drawables!!! – reavcn Dec 03 '19 at 12:01