Сенсорный экран предварительного просмотра Ripple Android L

Я пытаюсь создать эффект «пульсации» предварительного просмотра Android L для сенсорного события в представлении. Если я использую этот код для работы кнопки:

public class MyButton extends Button {

    private float mDownX;
    private float mDownY;

    private float mRadius;

    private Paint mPaint;

    public MyButton(final Context context) {
        super(context);
        init();
    }

    public MyButton(final Context context, final AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public MyButton(final Context context, final AttributeSet attrs, final int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {
        mPaint = new Paint();
        mPaint.setAlpha(100);
    }

    @Override
    public boolean onTouchEvent(@NonNull final MotionEvent event) {
        if (event.getActionMasked() == MotionEvent.ACTION_UP) {
            mDownX = event.getX();
            mDownY = event.getY();

            ObjectAnimator animator = ObjectAnimator.ofFloat(this, "radius", 0, getWidth() * 3.0f);
            animator.setInterpolator(new AccelerateInterpolator());
            animator.setDuration(400);
            animator.start();
        }
        return super.onTouchEvent(event);
    }

    public void setRadius(final float radius) {
        mRadius = radius;
        if (mRadius > 0) {
            RadialGradient radialGradient = new RadialGradient(
                    mDownX,
                    mDownY,
                    mRadius * 3,
                    Color.TRANSPARENT,
                    Color.BLACK,
                    Shader.TileMode.MIRROR
            );
            mPaint.setShader(radialGradient);
        }
        invalidate();
    }

    private Path mPath = new Path();
    private Path mPath2 = new Path();

    @Override
    protected void onDraw(@NonNull final Canvas canvas) {
        super.onDraw(canvas);

        mPath2.reset();
        mPath2.addCircle(mDownX, mDownY, mRadius, Path.Direction.CW);

        canvas.clipPath(mPath2);

        mPath.reset();
        mPath.addCircle(mDownX, mDownY, mRadius / 3, Path.Direction.CW);

        canvas.clipPath(mPath, Region.Op.DIFFERENCE);

        canvas.drawCircle(mDownX, mDownY, mRadius, mPaint);
    }
}

Даже если это не совсем так, как в предварительном просмотре Android L, но это работает ... Однако ... если я изменю Button и попытаюсь использовать класс View, это не сработает ... это что-то, чтобы создать этот эффект во всем представлении, а не только в кнопке?


person Atlas91    schedule 21.07.2014    source источник


Ответы (3)


Мой ответ несколько запоздал, и я также поделился этим решением ">тоже по этому исходному вопросу, но я также хочу поделиться им здесь. Я создал еще один класс под названием TouchEffectAnimator по идее Ника Хаармана. Кстати, благодаря мистеру Хаарману.

Вы можете увидеть класс и пример его использования здесь. И объясню это просто.

Класс содержит в себе все необходимые методы и переменные и создает ту же анимацию, что и Android L (preview) на данный момент. Для использования этого класса:

  • Создайте собственное представление. (в основном примере я создал LinearLayout)
  • Инициализируйте объект TouchEffectAnimator.
  • Определите некоторые его атрибуты, такие как цвет, тип эффекта, продолжительность и размер углов обрезки.
  • Вызовите метод onTouchEvent TouchEffectAnimator внутри представления onTouchEvent.
  • Вызовите метод onDraw TouchEffectAnimator внутри представления onDraw.

вот и все. Но есть две вещи, которые необходимо сделать, чтобы этот класс работал правильно.

  • В представлении должен быть какой-то OnClickListener, чтобы получить событие касания UP.
  • Для представления должен быть установлен настраиваемый или прозрачный фон. Если в качестве фона ничего не установлено, анимация не отображается.

Я надеюсь, что это сработает и для вас.

P.S. Я создал этот класс для своего библиотечного проекта Android FlatUI Kit. Вы также можете увидеть использование этого класса в классе FlatButton.

person eluleci    schedule 25.09.2014

Вам нужно вернуть true из onTouchEvent(), чтобы продолжать получать события. Кнопка делает это, потому что она предназначена для обработки событий кликов, а представление по умолчанию — нет.

Если вы настроите свое представление как кликабельное, вы получите ожидаемое поведение. Если вы посмотрите на рябь в L-предварительном просмотре, вы заметите, что она возникает только во включенных и кликабельных представлениях.

private void init() {
    mPaint = new Paint();
    mPaint.setAlpha(100);
    setClickable(true);
    setFocusable(true);
}

В качестве альтернативы вы всегда можете просто вызвать super, а затем вернуть true:

@Override
public boolean onTouchEvent(@NonNull final MotionEvent event) {
    ...
    super.onTouchEvent(event);
    return true;
}
person alanv    schedule 22.07.2014
comment
Просто вопрос, что такое @NonNull? что значит? - person Atlas91; 23.07.2014
comment
Это было в вашем коде, поэтому я оставил его в примере. Это аннотация, которая в этом конкретном месте означает, что аргумент никогда не должен быть нулевым. - person alanv; 23.07.2014
comment
Да, я знаю, что это было в моем коде, но, честно говоря, я никогда не понимал, что это значит. Спасибо :) однако я нашел способ сделать то, что хотел, и вот результат plus.google.com/u/0/+DavideDellai/posts/TqzsypnzudS :) Я также собираюсь создать библиотеку, чтобы упростить создание этого эффекта для каждого разработчика. - person Atlas91; 23.07.2014

Вы можете использовать эту библиотеку, чтобы получить «эффект ряби», поддерживает более старые устройства, версии API> = 14, с некоторыми хаками может также поддерживать версии API ‹ 14.

Ссылка: material-ripple

Вот пример использования:

  1. Оберните заинтересованное представление:

    <com.balysv.materialripple.MaterialRippleLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        style="@style/MyStyleViewContainer">
    
        <android.support.v7.widget.CardView
            xmlns:card_view="http://schemas.android.com/apk/res-auto"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <!-- content -->
        </android.support.v7.widget.CardView>
    </com.balysv.materialripple.MaterialRippleLayout>
    
  2. Определить стиль

    <style name="base_ripple_style" parent="AppTheme">
        <item name="mrl_rippleAlpha">0.3</item>
        <item name="mrl_rippleDelayClick">true</item>
        <item name="mrl_rippleDuration">300</item>
        <item name="mrl_rippleFadeDuration">50</item>
        <item name="mrl_rippleOverlay">true</item>
        <item name="mrl_rippleRoundedCorners">5dp</item>
    </style>
    
    <style name="MyStyleViewContainer" parent="base_ripple_style">
        <item name="mrl_rippleColor">@android:color/white</item>
    </style>
    
person Kreshnik    schedule 14.07.2016