自定义ImageView的可绘制对象

5

我已经有一个具有以下参数的 'ImageView':

android:layout_width="wrap_content"
android:layout_height="wrap_content"

并设置自定义Drawable

public class HexDrawable extends Drawable {

    private Path hexagonPath;
    private float mWidth, mHeight;
    private int mBackgroundColor;
    private int mStrokeColor;
    private int mStrokeWidth;

    public HexDrawable(){
        init();
    }

    public void setBackgroundColor(int color) {
        mBackgroundColor = color;
    }

    public void setStrokeWidth(int width) {
        mStrokeWidth = width;
    }

    public void setStrokeColor(int color) {
        mStrokeColor = color;
    }

    @Override
    public int getIntrinsicHeight() {
        return 60;
    }

    @Override
    public int getIntrinsicWidth() {
        return 60;
    }

    private void init() {
        hexagonPath = new Path();
        mBackgroundColor = Color.BLUE;
        mStrokeColor = Color.GREEN;
        mStrokeWidth = 4;
    }

    private void calculatePath() {
        float p = mStrokeWidth / 2;
        float w = mWidth - 2 * p;
        float h = mHeight - 2 * p;
        float r = h / 2;
        float a = (float) (r / Math.sqrt(3));
        PointF X = new PointF(p + a + r / 2, p);
        PointF Y = new PointF(p + a + r , p);
        PointF A = new PointF(p + a, p + 0f);
        PointF B = new PointF(p + 0f, p + r);
        PointF C = new PointF(p + a, p + 2 * r);
        PointF D = new PointF(p + w - a, p + 2 * r);
        PointF E = new PointF(p + w, p + r);
        PointF F = new PointF(p + w - a, p + 0);
        hexagonPath.moveTo(Y.x, Y.y);
        hexagonPath.lineTo(A.x, A.y);
        hexagonPath.lineTo(B.x, B.y);
        hexagonPath.lineTo(C.x, C.y);
        hexagonPath.lineTo(D.x, D.y);
        hexagonPath.lineTo(E.x, E.y);
        hexagonPath.lineTo(F.x, F.y);
        hexagonPath.lineTo(X.x, X.y);
    }

    @Override
    protected void onBoundsChange(Rect bounds) {
        mWidth = bounds.width();
        mHeight = bounds.height();
        calculatePath();
    }

    @Override
    public void draw(Canvas canvas) {
        Paint paint = new Paint();
        paint.setColor(mStrokeColor);                    // set the color
        paint.setStrokeWidth(mStrokeWidth);               // set the size
        paint.setDither(true);                    // set the dither to true
        paint.setStyle(Paint.Style.STROKE);       // set to STOKE
        paint.setStrokeJoin(Paint.Join.ROUND);    // set the join to round you want
        paint.setStrokeCap(Paint.Cap.ROUND);      // set the paint cap to round too
        paint.setPathEffect(new CornerPathEffect(mStrokeWidth));   // set the path effect when they join.
        paint.setAntiAlias(true);
        canvas.drawPath(hexagonPath, paint);
        canvas.clipPath(hexagonPath, Region.Op.INTERSECT);
        canvas.drawColor(mBackgroundColor);
        canvas.drawPath(hexagonPath, paint);
        canvas.save();
    }

    @Override
    public void setAlpha(int alpha) {

    }

    @Override
    public void setColorFilter(ColorFilter colorFilter) {

    }

    @Override
    public int getOpacity() {
        return 0;
    }
}

在这种情况下,ImageView似乎使用了全部的宽度。

如何正确地实现Drawable以便与ImageView一起使用?


1
你能发布一下你自定义的可绘制代码吗? - RussHWolf
@Brucelet完成,已添加示例代码。 - Alex Klimashevsky
1
我看了你的代码,drawable 在 ImageView 中完美地呈现。ImageView 可能会占用额外的宽度(因为它可能采用矩形或正方形),但你只能看到六边形的 drawable。抱歉,但是... 实际问题是什么? - sha
2个回答

4
问题的根源是剪辑模式。
最好使用canvas.clipPath(hexagonPath, Region.Op.REPLACE); 此外,问题示例在ImageView中运行良好,但经过深入调查,我理解到,在Android 5.0及以上版本中,该可绘制对象用于TextView中的drawableLeft。 同时,不需要覆盖getIntrinsicHeight

1
您的代码是完全正确的:

enter image description here

这是我在活动的 onCreate() 方法中如何填充 ImageView

((ImageView)findViewById(R.id.hexImageView)).setImageDrawable(new HexDrawable());

截图中的Activity布局:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp">

    <ImageView
        android:id="@+id/hexImageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</FrameLayout>

如果我用一个值来替换wrap_content,六边形的大小会按预期发生变化。

在Android 6.0和4.3上测试过。

只有一个提示- 在getIntrinsicHeight()getIntrinsicWidth()中使用dimens可能更好,而不是硬编码的值。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接