Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b0ee18f3 authored by Selim Cinek's avatar Selim Cinek
Browse files

Clipping to the top roundness when scrolling

We are now clipping properly to the top roundness,
such that the scrolling works properly and you never
see a hard edge on the top.

Test: add notifications, scroll, observe nice clipping
Bug: 69168591
Change-Id: I991eb33337eee8f0e1cee56e01e4e457146cb145
parent b95fd185
Loading
Loading
Loading
Loading
+35 −2
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ public abstract class ExpandableOutlineView extends ExpandableView {
    private static final Path EMPTY_PATH = new Path();

    private final Rect mOutlineRect = new Rect();
    private final Path mClipPath = new Path();
    private boolean mCustomOutline;
    private float mOutlineAlpha = -1f;
    private float mOutlineRadius;
@@ -75,6 +76,8 @@ public abstract class ExpandableOutlineView extends ExpandableView {
     * it is moved. Otherwise, the translation is set on the {@code ExpandableOutlineView} itself.
     */
    protected boolean mShouldTranslateContents;
    private boolean mClipRoundedToClipTopAmount;
    private float mDistanceToTopRoundness = -1;

    private final ViewOutlineProvider mProvider = new ViewOutlineProvider() {
        @Override
@@ -159,8 +162,8 @@ public abstract class ExpandableOutlineView extends ExpandableView {
        return roundedRectPath;
    }

    private void getRoundedRectPath(int left, int top, int right, int bottom, float topRoundness,
            float bottomRoundness, Path outPath) {
    public static void getRoundedRectPath(int left, int top, int right, int bottom,
            float topRoundness, float bottomRoundness, Path outPath) {
        outPath.reset();
        int width = right - left;
        float topRoundnessX = topRoundness;
@@ -197,20 +200,50 @@ public abstract class ExpandableOutlineView extends ExpandableView {
    @Override
    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
        canvas.save();
        Path intersectPath = null;
        if (mClipRoundedToClipTopAmount) {
            int left = 0;
            int top = (int) (mClipTopAmount - mDistanceToTopRoundness);
            int right = getWidth();
            int bottom = (int) Math.max(getActualHeight() - mClipBottomAmount,
                    top + mOutlineRadius);
            ExpandableOutlineView.getRoundedRectPath(left, top, right, bottom, mOutlineRadius,
                    0.0f,
                    mClipPath);
            intersectPath = mClipPath;
        }
        boolean clipped = false;
        if (childNeedsClipping(child)) {
            Path clipPath = getCustomClipPath(child);
            if (clipPath == null) {
                clipPath = getClipPath();
            }
            if (clipPath != null) {
                if (intersectPath != null) {
                    clipPath.op(intersectPath, Path.Op.INTERSECT);
                }
                canvas.clipPath(clipPath);
                clipped = true;
            }
        }
        if (!clipped && intersectPath != null) {
            canvas.clipPath(intersectPath);
        }
        boolean result = super.drawChild(canvas, child, drawingTime);
        canvas.restore();
        return result;
    }

    @Override
    public void setDistanceToTopRoundness(float distanceToTopRoundness) {
        super.setDistanceToTopRoundness(distanceToTopRoundness);
        if (distanceToTopRoundness != mDistanceToTopRoundness) {
            mClipRoundedToClipTopAmount = distanceToTopRoundness >= 0;
            mDistanceToTopRoundness = distanceToTopRoundness;
            invalidate();
        }
    }

    protected boolean childNeedsClipping(View child) {
        return false;
    }
+8 −0
Original line number Diff line number Diff line
@@ -130,6 +130,14 @@ public abstract class ExpandableView extends FrameLayout {
        }
    }

    /**
     * Set the distance to the top roundness, from where we should start clipping a value above
     * or equal to 0 is the effective distance, and if a value below 0 is received, there should
     * be no clipping.
     */
    public void setDistanceToTopRoundness(float distanceToTopRoundness) {
    }

    public void setActualHeight(int actualHeight) {
        setActualHeight(actualHeight, true /* notifyListeners */);
    }
+23 −0
Original line number Diff line number Diff line
@@ -657,11 +657,32 @@ public class NotificationStackScrollLayout extends ViewGroup

    private void onPreDrawDuringAnimation() {
        mShelf.updateAppearance();
        updateClippingToTopRoundedCorner();
        if (!mNeedsAnimation && !mChildrenUpdateRequested) {
            updateBackground();
        }
    }

    private void updateClippingToTopRoundedCorner() {
        Float clipStart = (float) mTopPadding;
        Float clipEnd = clipStart + mCornerRadius;
        boolean first = true;
        for (int i = 0; i < getChildCount(); i++) {
            ExpandableView child = (ExpandableView) getChildAt(i);
            if (child.getVisibility() == GONE) {
                continue;
            }
            float start = child.getTranslationY();
            float end = start + Math.max(child.getActualHeight() - child.getClipBottomAmount(),
                    0);
            boolean clip = clipStart > start && clipStart < end
                    || clipEnd >= start && clipEnd <= end;
            clip &= !(first && mOwnScrollY == 0);
            child.setDistanceToTopRoundness(clip ? Math.max(start - clipStart, 0) : -1);
            first = false;
        }
    }

    private void updateScrollStateForAddedChildren() {
        if (mChildrenToAddAnimated.isEmpty()) {
            return;
@@ -2981,6 +3002,7 @@ public class NotificationStackScrollLayout extends ViewGroup
            mAnimationEvents.clear();
            updateBackground();
            updateViewShadows();
            updateClippingToTopRoundedCorner();
        } else {
            applyCurrentState();
        }
@@ -3674,6 +3696,7 @@ public class NotificationStackScrollLayout extends ViewGroup
        setAnimationRunning(false);
        updateBackground();
        updateViewShadows();
        updateClippingToTopRoundedCorner();
    }

    private void updateViewShadows() {