Android Nougat clipPath не работает во время анимации

#android #animation #clip #android-7.0-nougat

#Android #Анимация #клип #android-7.0-nougat

Вопрос:

Я создал круговой контур клипа на своем холсте, и у меня есть столбец чисел, который анимируется на холсте, поэтому я вижу, что числа анимируются в обрезанном разделе и анимируются. Вот код для обрезки:

 mClipPath.addCircle((w / 2f), (h / 2f), radius, Path.Direction.CW); 
canvas.clipPath(mClipPath, Region.Op.INTERSECT);
  

Как вы можете видеть, 0 анимируется, а 1 анимируется (цифры справа).
введите описание изображения здесь

Но в некоторых случаях отсечение не происходит должным образом во время анимации (3 и 4 слева).

введите описание изображения здесь

Это происходит только на Nougat.

Комментарии:

1. Можете ли вы поделиться снимками экрана других версий API? Кроме того, было бы полезно добавить больше кода

2. Другие версии api аналогичны первому скриншоту, без неправильного отсечения для любого из чисел во время анимации.

Ответ №1:

Я вижу ту же проблему. При прокрутке RecyclerView, содержащего CircleCropDrawable ниже, я вижу, что отображаемая вспышка между обрезанной и не обрезанной в зависимости от положения прокрутки.

Однако методом проб и ошибок я увидел, что это происходит только тогда, когда путь пересекает край рисуемого объекта. Уменьшение радиуса на 1dp устраняет проблему (меньше 1dp не работает)

CircleCropDrawable.java

 package com.someone.android.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.util.TypedValue;

public class CircleCropDrawable extends Drawable {

    private final Context mContext;
    private final Drawable mDrawable;

    public CircleCropDrawable(Context context, Drawable drawable) {
        mContext = context;
        this.mDrawable = drawable;
    }

    @Override
    public void draw(@NonNull Canvas canvas) {
        final float width = getBounds().width();
        final float height = getBounds().height();
        final Path path = new Path();
        // There seems to be a bug in N where the clip path doesn't work when animating
        // without a 1dp reduction in radius, the drawable unclips when scrolling in a RecyclerView
        float inset = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2, mContext.getResources().getDisplayMetrics());
        path.addCircle(width / 2, height / 2, Math.min(width / 2, height / 2) - inset, Path.Direction.CW);
        canvas.clipPath(path);
        mDrawable.draw(canvas);
    }

    @Override
    protected void onBoundsChange(Rect bounds) {
        mDrawable.setBounds(bounds);
    }

    @Override
    public int getIntrinsicWidth() {
        return mDrawable.getIntrinsicWidth();
    }

    @Override
    public int getIntrinsicHeight() {
        return mDrawable.getIntrinsicHeight();
    }


    @Override
    public void setAlpha(int i) {
        mDrawable.setAlpha(i);
    }

    @Override
    public void setColorFilter(ColorFilter colorFilter) {
        mDrawable.setColorFilter(colorFilter);
    }

    @Override
    public int getOpacity() {
        return mDrawable.getOpacity();
    }
}  

Комментарии:

1. Удивительно! Я потратил много времени на ту же проблему. Я никак не мог это понять! 🙂 Спасибо.

Ответ №2:

Я отправил сообщение об ошибке в Google по этому поводу, и, похоже, оно было устранено. Вот ссылка на ошибку:

https://code.google.com/p/android/issues/detail?id=225016

Ответ №3:

Мы исправили проблему, отключив аппаратное ускорение для этого представления, например:

 myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);