如何制作透明(alpha)渐变蒙版以使一层在Android中淡入透明度?

时间:2018-05-27 20:49:59

标签: android android-layout android-canvas gradient linear-gradients

我希望根据渐变使一层淡入下层(或透明度取决于您的看法)。一种所谓的透明(alpha)渐变掩模。我正在寻找一个解决方案similar to this但是在android而不是ios:

enter image description here

我已尝试this solution,但正如评论中所述,叠加层不会使图层透明,只会使其淡化为指定的颜色。

有什么建议吗?

1 个答案:

答案 0 :(得分:1)

您可以使用Android-FadingEdgeLayout库。 或者这是基于上述lib的子类化framelayout:

public class AlphaGradientLayout extends FrameLayout {

    private static final int DEFAULT_GRADIENT_SIZE_DP = 80;

    public static final int FADE_EDGE_TOP = 1;
    private static final int DIRTY_FLAG_TOP = 1;

    private static final int[] FADE_COLORS = new int[]{Color.TRANSPARENT, Color.BLACK};

    private boolean fadeTop;
    private int gradientSizeTop;
    private Paint gradientPaintTop;
    private Rect gradientRectTop;
    private int gradientDirtyFlags;

    public AlphaGradientLayout(Context context) {
        super(context);
        init(null, 0);
    }

    public AlphaGradientLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(attrs, 0);
    }

    public AlphaGradientLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(attrs, 0);
    }

    private void init(AttributeSet attrs, int defStyleAttr) {
        int defaultSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, DEFAULT_GRADIENT_SIZE_DP,
                getResources().getDisplayMetrics());

        if (attrs != null) {
            TypedArray arr = getContext().obtainStyledAttributes(attrs, R.styleable.AlphaGradientLayout, defStyleAttr, 0);
            int flags = arr.getInt(R.styleable.FadingEdgeLayout_fel_edge, 0);

            fadeTop = (flags & FADE_EDGE_TOP) == FADE_EDGE_TOP;

            gradientSizeTop = arr.getDimensionPixelSize(R.styleable.FadingEdgeLayout_fel_size_top, defaultSize);

            if (fadeTop && gradientSizeTop > 0) {
                gradientDirtyFlags |= DIRTY_FLAG_TOP;
            }

            arr.recycle();
        } else {
            gradientSizeTop = defaultSize;
        }

        PorterDuffXfermode mode = new PorterDuffXfermode(PorterDuff.Mode.DST_IN);
        gradientPaintTop = new Paint(Paint.ANTI_ALIAS_FLAG);
        gradientPaintTop.setXfermode(mode);

        gradientRectTop = new Rect();
    }

    @Override
    public void setPadding(int left, int top, int right, int bottom) {
        if (getPaddingTop() != top) {
            gradientDirtyFlags |= DIRTY_FLAG_TOP;
        }
        super.setPadding(left, top, right, bottom);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        if (h != oldh) {
            gradientDirtyFlags |= DIRTY_FLAG_TOP;
        }
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        int newWidth = getWidth(), newHeight = getHeight();
        boolean fadeAnyEdge = fadeTop;
        if (getVisibility() == GONE || newWidth == 0 || newHeight == 0 || !fadeAnyEdge) {
            super.dispatchDraw(canvas);
            return;
        }

        if ((gradientDirtyFlags & DIRTY_FLAG_TOP) == DIRTY_FLAG_TOP) {
            gradientDirtyFlags &= ~DIRTY_FLAG_TOP;

            int actualHeight = getHeight() - getPaddingTop() - getPaddingBottom();
            int size = Math.min(gradientSizeTop, actualHeight);
            int l = getPaddingLeft();
            int t = getPaddingTop();
            int r = getWidth() - getPaddingRight();
            int b = t + size;
            gradientRectTop.set(l, t, r, b);
            LinearGradient gradient = new LinearGradient(l, t, l, b, FADE_COLORS, null, Shader.TileMode.CLAMP);
            gradientPaintTop.setShader(gradient);
        }

        int count = canvas.saveLayer(0.0f, 0.0f, (float) getWidth(), (float) getHeight(), null, Canvas.ALL_SAVE_FLAG);
        super.dispatchDraw(canvas);
        if (fadeTop && gradientSizeTop > 0) {
            canvas.drawRect(gradientRectTop, gradientPaintTop);
        }
        canvas.restoreToCount(count);
    }
} 

然后将要褪色的项目移动到此布局中

And here's what you should get