如何将阴影添加到矢量drawable?

时间:2017-02-02 12:38:49

标签: android vector shadow

我有一个矢量drawable(category_bg),我用它作为FrameLayout的背景

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="200dp"
    android:height="100dp"
    android:viewportWidth="600"
    android:viewportHeight="450">

    <path
        android:fillColor="#FFFFFF"
        android:fillType="evenOdd"
        android:pathData="M24.8,21.4c0,0,73.8-8.1,161.3-8.1c77.7,0,153.9,2,231.9,2c88.5,0,156.3,6,156.3,6c5.6,0,10.1,4.5,10.1,10.1
c0,0,2,41.2,2,134.1c0,68.5,4,77.9,4,139.1c0,65-6,114.9-6,114.9c0,5.6-4.5,10.1-10.1,10.1c0,0-32.1,7.1-80.6,7.1
c-47.5,0-99.6-7.1-164.7-7.1c-77.6,0-160.9,6-219.4,6c-52.8,0-84.7-6-84.7-6c-5.6,0-10.1-4.5-10.1-10.1c0,0-4-46.6-4-111.9
c0-85.8-1-102.9-1-183.5c0-55,5-92.7,5-92.7C14.7,25.9,19.2,21.4,24.8,21.4z" />
</vector>

我想在矢量drawable

中添加阴影

我的xml文件

<FrameLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/category_bg"
        android:padding="3dp">


        <com.shaker.materialComponents.view.MaskableFrameLayout
            android:id="@+id/category"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:mask="@drawable/pic_mask"
            app:porterduffxfermode="DST_IN">

            <com.shaker.materialComponents.view.AspectRatioImageView
                android:id="@+id/image"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:adjustViewBounds="true"
                android:scaleType="centerCrop"
                android:src="@drawable/meal"
                app:aspectRatio="0.75"
                app:aspectRatioEnabled="true"
                app:dominantMeasurement="width"/>


            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_gravity="bottom"
                android:background="@drawable/category_gradient_bg"
                android:gravity="center"
                android:orientation="horizontal"
                android:paddingBottom="16dp"
                android:paddingLeft="16dp"
                android:paddingRight="16dp"
                android:paddingTop="20dp">


                <com.shaker.materialComponents.view.MaterialTextView
                    android:id="@+id/name"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:ellipsize="end"
                    android:lines="1"
                    android:text="Salads"
                    android:textColor="#fff"
                    android:textSize="18dp"
                    android:textStyle="bold"
                    app:customFont="GothamRounded-Bold.ttf"/>

                <ImageView
                    android:id="@+id/expand_btn"
                    android:layout_width="20dp"
                    android:layout_height="20dp"
                    android:src="@drawable/expand_button"/>

            </LinearLayout>

        </com.shaker.materialComponents.view.MaskableFrameLayout>

当前结果

enter image description here

添加阴影之后应该是这样的

enter image description here

3 个答案:

答案 0 :(得分:1)

所有荣誉归于pskink,他在评论中将此代码与问题联系起来。不幸的是,这似乎仍然是唯一的解决方案

// test code
    View v = new View(this);
    setContentView(v);

    Drawable source = getResources().getDrawable(R.drawable.chrome);
    Drawable mask = getResources().getDrawable(R.drawable.chrome_mask);;
    int[] colors = {
            Color.RED, Color.BLACK
    };
    Drawable shadow = new GradientDrawable(GradientDrawable.Orientation.LEFT_RIGHT, colors);
    Shape s = new S(this, source, mask, shadow, 8);
    v.setBackground(new ShapeDrawable(s));

// end of test code

class S extends Shape {
    Context ctx;
    Drawable source;
    Drawable mask;
    Drawable shadow;
    float shadowRadius;
    Matrix matrix = new Matrix();
    Bitmap bitmap;

    public S(Context ctx, Drawable source, Drawable mask, Drawable shadow, float shadowRadius) {
        this.ctx = ctx;
        this.source = source;
        this.mask = mask;
        this.shadow = shadow;
        this.shadowRadius = shadowRadius;
    }

    @Override
    protected void onResize(float width, float height) {
        int intrinsicWidth = source.getIntrinsicWidth();
        int intrinsicHeight = source.getIntrinsicHeight();
        source.setBounds(0, 0, intrinsicWidth, intrinsicHeight);
        mask.setBounds(0, 0, intrinsicWidth, intrinsicHeight);
        shadow.setBounds(0, 0, intrinsicWidth, intrinsicHeight);

        RectF src = new RectF(0, 0, intrinsicWidth, intrinsicHeight);
        RectF dst = new RectF(0, 0, width, height);
        matrix.setRectToRect(src, dst, Matrix.ScaleToFit.CENTER);

        Paint p = new Paint();
        p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
        bitmap = Bitmap.createBitmap(intrinsicWidth, intrinsicHeight, Bitmap.Config.ARGB_8888);
        Canvas c = new Canvas(bitmap);

        shadow.draw(c);
        c.saveLayer(null, p, Canvas.ALL_SAVE_FLAG);
        mask.draw(c);
        c.restore();
        bitmap = blurRenderScript(bitmap);

        c = new Canvas(bitmap);
        int count = c.saveLayer(null, null, Canvas.ALL_SAVE_FLAG);
        source.draw(c);
        c.saveLayer(null, p, Canvas.ALL_SAVE_FLAG);
        mask.draw(c);
        c.restoreToCount(count);
    }

    @Override
    public void draw(Canvas canvas, Paint paint) {
        canvas.drawColor(0xffdddddd);
        canvas.drawBitmap(bitmap, matrix, null);
    }

    Bitmap blurRenderScript(Bitmap input) {
        Bitmap output = Bitmap.createBitmap(input.getWidth(), input.getHeight(), input.getConfig());
        RenderScript rs = RenderScript.create(ctx);
        ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
        Allocation inAlloc = Allocation.createFromBitmap(rs, input, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_GRAPHICS_TEXTURE);
        Allocation outAlloc = Allocation.createFromBitmap(rs, output);
        script.setRadius(shadowRadius);
        script.setInput(inAlloc);
        script.forEach(outAlloc);
        outAlloc.copyTo(output);
        rs.destroy();
        return output;
    }
}

答案 1 :(得分:0)

使用上面的解决方案,我对一个圆形可绘制对象进行了此操作:

val source: Drawable = ContextCompat.getDrawable(context,R.drawable.my_drawable)!!
val colors = intArrayOf(
                Color.GRAY, Color.TRANSPARENT
        )
val shadow: Drawable = GradientDrawable(GradientDrawable.Orientation.BOTTOM_TOP, colors)
val s: Shape = DrawableShadow(context, source, source, shadow, 10f)
imageView.background = ShapeDrawable(s)
imageView.setImageResource(R.drawable.my_drawable)

和我更改的DrawableShadow

class DrawableShadow(
    private val context: Context,
    private val source: Drawable,
    private val mask: Drawable,
    private val shadow: Drawable,
    private val shadowRadius: Float
) : Shape() {
...
override fun draw(canvas: Canvas, paint: Paint?) {
    canvas.drawColor(Color.TRANSPARENT)
...

为他的解决方案提供@@ pskink

答案 2 :(得分:-3)

最简单的方法是对布局容器进行更改。 尝试使用CardView作为布局的容器。

试试这个例子:

<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/cardView"
android:layout_marginTop="20dp"
android:layout_marginRight="20dp"
android:layout_marginLeft="20dp"
app:cardCornerRadius="12dp"
app:cardElevation="20dp"
android:layout_width="match_parent"
android:layout_height="60dp"> <!--Change to wrap_content-->

<!--Add layout views-->
</android.support.v7.widget.CardView>