【问题标题】:Android Hexagon ImageViewAndroid Hexagon ImageView
【发布时间】:2014-11-24 13:12:31
【问题描述】:

我怎样才能实现如下所示的六边形图像视图。

http://imgur.com/1PEGuQu

请注意,我尝试了针对此问题的解决方案: How to give hexagon shape to ImageView

我也尝试了这个解决方案: Masking(crop) image in frame

但我不想在六边形之外填充颜色。我希望它是透明的,所以可以看到后面的视图和图像。

顺便说一下,BitmapShader、PorterDuffXFermode 等都试过了,但都无法得到我想要的结果。

提前致谢。

【问题讨论】:

    标签: android imageview mask


    【解决方案1】:

    我终于解决了我的问题。我找到了一个非常有用的库,它专门完成了我想要的技巧。它用 svg 类型的矢量图像掩盖了 imageview。

    图书馆:

    CustomShapeImageView

    结果:

    Screenshot

    编辑:我还想与您分享六角形 svg,以备不时之需。

    <svg width="205" height="237" xmlns="http://www.w3.org/2000/svg">
    <title>hexagon</title>
    <metadata id="metadata3064">image/svg+xml</metadata>
    <g>
    <title>Layer 1</title>
    <polygon points="0,59.27092742919922 0,177.8127899169922 102.66026306152344,237.08370971679688 205.3205108642578,177.8127899169922 205.3205108642578,59.27092742919922 102.66026306152344,0 " id="svg_1" fill="#000000"/>
    </g>
    </svg>
    

    【讨论】:

    • 嗨。 SafaOrhan,svg 必须保存在哪个文件夹和哪个扩展名中?
    • @Jack 你可以把它放到 /res/raw 文件夹中,不用任何扩展名。
    【解决方案2】:

    这是我的代码,它支持阴影:

    import android.annotation.SuppressLint;
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.BitmapShader;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Path;
    import android.graphics.PorterDuff;
    import android.graphics.Shader;
    import android.graphics.drawable.BitmapDrawable;
    import android.util.AttributeSet;
    import android.widget.ImageView;
    
    public class HexagonImageView extends ImageView {
    
        private Path hexagonPath;
        private Path hexagonBorderPath;
        private float radius;
        private Bitmap image;
        private int viewWidth;
        private int viewHeight;
        private Paint paint;
        private BitmapShader shader;
        private Paint paintBorder;
        private int borderWidth = 4;
    
        public HexagonImageView(Context context) {
            super(context);
            setup();
        }
    
        public HexagonImageView(Context context, AttributeSet attrs) {
            super(context, attrs);
            setup();
        }
    
        public HexagonImageView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            setup();
        }
    
        private void setup() {
            paint = new Paint();
            paint.setAntiAlias(true);
    
            paintBorder = new Paint();
            setBorderColor(Color.WHITE);
            paintBorder.setAntiAlias(true);
            this.setLayerType(LAYER_TYPE_SOFTWARE, paintBorder);
            paintBorder.setShadowLayer(4.0f, 1.0f, 1.0f, Color.BLACK);
    
            hexagonPath = new Path();
            hexagonBorderPath = new Path();
        }
    
        public void setRadius(float r) {
            this.radius = r;
            calculatePath();
        }
    
        public void setBorderWidth(int borderWidth)  {
            this.borderWidth = borderWidth;
            this.invalidate();
        }
    
        public void setBorderColor(int borderColor)  {
            if (paintBorder != null)
                paintBorder.setColor(borderColor);
    
            this.invalidate();
        }
    
        private void calculatePath() {
    
            float triangleHeight = (float) (Math.sqrt(3) * radius / 2);
            float centerX = viewWidth/2;
            float centerY = viewHeight/2;
    
            hexagonBorderPath.moveTo(centerX, centerY + radius);
            hexagonBorderPath.lineTo(centerX - triangleHeight, centerY + radius/2);
            hexagonBorderPath.lineTo(centerX - triangleHeight, centerY - radius/2);
            hexagonBorderPath.lineTo(centerX, centerY - radius);
            hexagonBorderPath.lineTo(centerX + triangleHeight, centerY - radius/2);
            hexagonBorderPath.lineTo(centerX + triangleHeight, centerY + radius/2);
            hexagonBorderPath.moveTo(centerX, centerY + radius);
    
            float radiusBorder = radius - borderWidth;    
            float triangleBorderHeight = (float) (Math.sqrt(3) * radiusBorder / 2);
    
            hexagonPath.moveTo(centerX, centerY + radiusBorder);
            hexagonPath.lineTo(centerX - triangleBorderHeight, centerY + radiusBorder/2);
            hexagonPath.lineTo(centerX - triangleBorderHeight, centerY - radiusBorder/2);
            hexagonPath.lineTo(centerX, centerY - radiusBorder);
            hexagonPath.lineTo(centerX + triangleBorderHeight, centerY - radiusBorder/2);
            hexagonPath.lineTo(centerX + triangleBorderHeight, centerY + radiusBorder/2);
            hexagonPath.moveTo(centerX, centerY + radiusBorder);
    
            invalidate();
        }
    
        private void loadBitmap()  {
            BitmapDrawable bitmapDrawable = (BitmapDrawable) this.getDrawable();
    
            if (bitmapDrawable != null)
                image = bitmapDrawable.getBitmap();
        }
    
        @SuppressLint("DrawAllocation")
        @Override
        public void onDraw(Canvas canvas){
            super.onDraw(canvas);
    
            loadBitmap();
    
            // init shader
            if (image != null) {
    
                canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
    
                shader = new BitmapShader(Bitmap.createScaledBitmap(image, canvas.getWidth(), canvas.getHeight(), false), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
                paint.setShader(shader);
    
                canvas.drawPath(hexagonBorderPath, paintBorder);
                canvas.drawPath(hexagonPath, paint);
            }
    
        }
    
        @Override
        public void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    
            int width = measureWidth(widthMeasureSpec);
            int height = measureHeight(heightMeasureSpec, widthMeasureSpec);
    
            viewWidth = width - (borderWidth * 2);
            viewHeight = height - (borderWidth * 2);
    
            radius = height / 2 - borderWidth;
    
            calculatePath();
    
            setMeasuredDimension(width, height);
        }
    
        private int measureWidth(int measureSpec)   {
            int result = 0;
            int specMode = MeasureSpec.getMode(measureSpec);
            int specSize = MeasureSpec.getSize(measureSpec);
    
            if (specMode == MeasureSpec.EXACTLY)  {
                result = specSize;
            }
            else {
                result = viewWidth;
            }
    
            return result;
        }
    
        private int measureHeight(int measureSpecHeight, int measureSpecWidth)  {
            int result = 0;
            int specMode = MeasureSpec.getMode(measureSpecHeight);
            int specSize = MeasureSpec.getSize(measureSpecHeight);
    
            if (specMode == MeasureSpec.EXACTLY) {
                result = specSize;
            }
            else {
                result = viewHeight;
            }
    
            return (result + 2);
        }
    
    
    }
    

    【讨论】:

      【解决方案3】:

      我已阅读此内容并且看起来有效。他们甚至有一个视频教程:http://www.41post.com/4794/programming/android-rendering-a-path-with-a-bitmap-fill 关于如何用纹理填充形状

      【讨论】:

      • 我不想填充颜色。我想掩盖它,以便可以看到它背后的视图。
      • 使用他们的 tut,您可以创建具有纹理形状的透明图像。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-05-04
      • 1970-01-01
      • 2021-11-04
      • 2016-02-03
      • 1970-01-01
      • 1970-01-01
      • 2011-12-17
      相关资源
      最近更新 更多