【问题标题】:Design a Path for cropping an ImageView设计用于裁剪 ImageView 的路径
【发布时间】:2014-09-26 09:53:39
【问题描述】:

好的,我需要裁剪一个特定形状的 ImageView,我不能通过添加 png 来做到这一点,因为背景可以是可变的(例如图案)。所以,我需要形状外的区域是透明的。

形状必须是这样的:

我想用 Path() 来绘制这个形状并用它来遮罩 ImageView,但是我完全不知道如何用 Path() 来绘制这样一个复杂的形状。

非常感谢。

【问题讨论】:

    标签: java android path shape


    【解决方案1】:

    所以我很无聊,这看起来很有趣,所以我整理了一个简单的 Drawable,你可以用它来做这件事。您可以变得更漂亮并添加笔触和诸如此类的东西,但这适用于您建议的基本情况,并允许您将箭头设置为指向任何角落,并且还将缩放您的图像以适应边界可绘制的。结果如下:

    您可以通过以下方式使用它:

    BubbleDrawable bubbleDrawable = new BubbleDrawable(
            this, R.drawable.your_image, BubbleDrawable.Corner.TOP_RIGHT);
    myImageView.setImageDrawable(bubbleDrawable);
    

    这是 BubbleDrawable 的代码:

    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.BitmapShader;
    import android.graphics.Canvas;
    import android.graphics.ColorFilter;
    import android.graphics.Matrix;
    import android.graphics.Paint;
    import android.graphics.Path;
    import android.graphics.Rect;
    import android.graphics.RectF;
    import android.graphics.Shader;
    import android.graphics.drawable.Drawable;
    
    import static android.graphics.Matrix.ScaleToFit.FILL;
    import static android.graphics.Paint.ANTI_ALIAS_FLAG;
    import static android.graphics.Path.Direction.CW;
    import static android.graphics.PixelFormat.TRANSPARENT;
    import static android.graphics.Shader.TileMode.CLAMP;
    import static test.com.testrotationanimation.BubbleDrawable.Corner.TOP_LEFT;
    
    public final class BubbleDrawable extends Drawable {
        private final Matrix mMatrix = new Matrix();
        private final Paint mPaint = new Paint(ANTI_ALIAS_FLAG);
        private final Path mPath = new Path();
        private final RectF mSrcRect = new RectF();
        private final RectF mDstRect = new RectF();
        private final Shader mShader;
    
        private Corner mArrowCorner = TOP_LEFT;
    
        public BubbleDrawable(Bitmap bitmap, Corner arrowCorner) {
            // Initialize a BitmapShader with the image you wish to draw
            // (you can use other TileModes like REPEAT or MIRROR if you prefer)
            mShader = new BitmapShader(bitmap, CLAMP, CLAMP);
            mPaint.setShader(mShader);
    
            // Save the bounds of the bitmap as the src rectangle -- will
            // be used later to update the matrix when the bounds change
            // so that the image fits within the bounds of this drawable
            mSrcRect.set(0, 0, bitmap.getWidth(), bitmap.getHeight());
    
            // Set the corner in which the arrow will be drawn
            mArrowCorner = arrowCorner;
        }
    
        public BubbleDrawable(Context ctx, int drawableResource, Corner arrowCorner) {
            this(BitmapFactory.decodeResource(ctx.getResources(), drawableResource), arrowCorner);
        }
    
        public Corner getArrowCorner() {
            return mArrowCorner;
        }
    
        public void setArrowCorner(Corner corner) {
            mArrowCorner = corner;
            updatePath();
            invalidateSelf();
        }
    
        @Override
        protected void onBoundsChange(Rect bounds) {
            super.onBoundsChange(bounds);
            updateMatrix(bounds);
            updatePath();
        }
    
        private void updateMatrix(Rect bounds) {
            // Set the destination rectangle for the bitmap to be the
            // new drawable bounds
            mDstRect.set(bounds);
    
            // Scale the bitmap's rectangle to the bounds of this drawable
            mMatrix.setRectToRect(mSrcRect, mDstRect, FILL);
    
            // Update the shader's matrix (to draw the bitmap at the right size)
            mShader.setLocalMatrix(mMatrix);
        }
    
        private void updatePath() {
            final Rect bounds = getBounds();
            final float x = bounds.exactCenterX();
            final float y = bounds.exactCenterY();
    
            // Draw the initial circle (same for all corners)
            mPath.reset();
            mPath.addCircle(x, y, Math.min(x, y), CW);
    
            // Add the rectangle which intersects with the center,
            // based on the corner in which the arrow should draw
            switch (mArrowCorner) {
                case TOP_LEFT:
                    mPath.addRect(bounds.left, bounds.top, x, y, CW);
                    break;
                case TOP_RIGHT:
                    mPath.addRect(x, bounds.top, bounds.right, y, CW);
                    break;
                case BOTTOM_LEFT:
                    mPath.addRect(bounds.left, y, x, bounds.bottom, CW);
                    break;
                case BOTTOM_RIGHT:
                    mPath.addRect(x, y, bounds.right, bounds.bottom, CW);
                    break;
            }
        }
    
        @Override
        public void draw(Canvas canvas) {
            // Easy enough, just draw the path using the paint.
            // It already has the BitmapShader applied which
            // will do the work for you.
            canvas.drawPath(mPath, mPaint);
        }
    
        @Override
        public int getOpacity() {
            // Indicate that this Drawable has fully-transparent pixel values
            return TRANSPARENT;
        }
    
        @Override
        public void setColorFilter(ColorFilter colorFilter) {
            // Yay, you can even support color filters for your drawable
            mPaint.setColorFilter(colorFilter);
        }
    
        @Override
        public void setAlpha(int i) {
            // You could do this by doing some canvas magic but I'm 
            // lazy and don't feel like it. Exercise for the reader. :)
            throw new UnsupportedOperationException("Not implemented.");
        }
    
        public enum Corner {
            TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT
        }
    }
    

    【讨论】:

    • 我希望你以后再无聊...... :D 只是,谢谢你,非常详细的解决方案!
    猜你喜欢
    • 1970-01-01
    • 2013-10-07
    • 1970-01-01
    • 1970-01-01
    • 2016-08-01
    • 2015-07-08
    • 2014-12-08
    • 2011-03-18
    • 1970-01-01
    相关资源
    最近更新 更多