How to use RippleDrawable programmatically in code (not xml) with Android 5.0 Lollipop?

前端 未结 3 447
我在风中等你
我在风中等你 2020-12-13 04:32

I have the following code for my ripple:




        
相关标签:
3条回答
  • 2020-12-13 04:40

    Basically, you need to create a new RippleDrawable object. For pre-Lollipop devices, you want a StateListDrawable (as others already suggested). I've written a somewhat resourceful GIST with a bunch of useful methods related to Drawables and coloring: https://gist.github.com/milosmns/6566ca9e3b756d922aa5

    Most likely you will want to use #getBackgroundDrawable() from that singleton.

    0 讨论(0)
  • 2020-12-13 04:47

    This is how I was able to achieve this.

    Note that this is Api 21+ only so you will have to fallback to a normal Drawable if you support lower versions.

    public static RippleDrawable getPressedColorRippleDrawable(int normalColor, int pressedColor)
    {
        return new RippleDrawable(getPressedColorSelector(normalColor, pressedColor), getColorDrawableFromColor(normalColor), null);
    }
    
    public static ColorStateList getPressedColorSelector(int normalColor, int pressedColor)
    {
        return new ColorStateList(
            new int[][]
                {
                    new int[]{android.R.attr.state_pressed},
                    new int[]{android.R.attr.state_focused},
                    new int[]{android.R.attr.state_activated},
                    new int[]{}
                },
            new int[]
                {
                    pressedColor,
                    pressedColor,
                    pressedColor,
                    normalColor
                }
        );
    }
    
    public static ColorDrawable getColorDrawableFromColor(int color)
    {
        return new ColorDrawable(color);
    }
    

    Edit: I tinkered with this some more and discovered that the ColorStateList doesn't need to be nearly as complex as the above solution. I have simplified it to the below snippet. (Everything else in the above code block is the same. I only changed the ColorStateList creation.) I will leave the above block as the original, in case this method doesn't work for someone.

    new ColorStateList(
        new int[][]
            {
                new int[]{}
            },
        new int[]
            {
                pressedColor
            }
    );
    
    0 讨论(0)
  • 2020-12-13 05:01
    public static Drawable getAdaptiveRippleDrawable(
        int normalColor, int pressedColor) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            return new RippleDrawable(ColorStateList.valueOf(pressedColor),
                    null, getRippleMask(normalColor));
        } else {
            return getStateListDrawable(normalColor, pressedColor);
        }
    }
    
    private static Drawable getRippleMask(int color) {
        float[] outerRadii = new float[8];
        // 3 is radius of final ripple, 
        // instead of 3 you can give required final radius
        Arrays.fill(outerRadii, 3);
    
        RoundRectShape r = new RoundRectShape(outerRadii, null, null);
        ShapeDrawable shapeDrawable = new ShapeDrawable(r);
        shapeDrawable.getPaint().setColor(color);
        return shapeDrawable;
    }
    
    public static StateListDrawable getStateListDrawable(
        int normalColor, int pressedColor) {
        StateListDrawable states = new StateListDrawable();
        states.addState(new int[]{android.R.attr.state_pressed}, 
            new ColorDrawable(pressedColor));
        states.addState(new int[]{android.R.attr.state_focused}, 
            new ColorDrawable(pressedColor));
        states.addState(new int[]{android.R.attr.state_activated}, 
            new ColorDrawable(pressedColor));
        states.addState(new int[]{}, 
            new ColorDrawable(normalColor));
        return states;
    }
    

    You can get the drawable and apply to any view using view.setDrawable.
    For Lollipop+ devices you will get ripple else it will change the color of view.

    0 讨论(0)
提交回复
热议问题