美文网首页Android 自定义view
Android 自定义气泡TextView

Android 自定义气泡TextView

作者: 挂机的坑坑 | 来源:发表于2019-11-12 11:49 被阅读0次

效果如下:

可以设置颜色、描边、三角形高度和方向,以向上居中和向下居中为例


气泡.png

实现思路:

使用Canvas绘制气泡形状,因为气泡中间只显示文字,所以我直接继承TextView,重写onDraw方法。

关键代码:

1、在attrs.xml文件中自定义属性,我定义了气泡颜色、描边颜色、描边宽度、三角形高度、三角形方向代码如下:

    <!--气泡-->
    <declare-styleable name="BubbleView">
        <attr name="bubbleColor" format="reference|color" />
        <attr name="bubbleStrokeColor" format="reference|color" />
        <attr name="bubbleStrokeWidth" format="dimension" />
        <attr name="triangleHeight" format="dimension" />
        <attr name="triangleDirection">
            <flag name="top" value="1" />
            <flag name="bottom" value="2" />
        </attr>
    </declare-styleable>

2、Canvas绘制矩形,提供了两种重载方式:
drawRoundRect(@NonNull RectF rect, float rx, float ry, @NonNull Paint paint)
drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, @NonNull Paint paint)
rx表示圆心
ry表示半径
left, top可以理解为为矩形左上角点的坐标
right, bottom可以理解为矩形右下角点的坐标

如图所示:

矩形.jpg

3、Path绘制三角形,先moveTo移动到任意一点,然后lineTo画线:


描点.jpg

完整代码:

BubbleView.java

/**
 * 类描述: 气泡
 * 创建人: liufei
 * 创建时间: 2019/10/25 15:14
 */
public class BubbleView extends AppCompatTextView {

    private Paint mPaint;
    private Paint mStrokePaint;

    //背景颜色
    private int bgColor;
    //描边颜色
    private int strokeColor;
    //描边宽
    private int strokeWidth;
    //view总高
    private int height;
    //view总宽
    private int width;
    //矩形高
    private int labelHeight;
    //圆角半径
    private int mRadius;
    //三角形高
    private int triangleHeight;
    //三角形方向
    private int triangleDirection;

    public BubbleView(Context context) {
        this(context, null);
    }

    public BubbleView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public BubbleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs, defStyleAttr);
    }

    public void init(Context context, AttributeSet attrs, int defStyleAttr) {
        if (attrs != null) {
            TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.BubbleView);
            bgColor = a.getColor(R.styleable.BubbleView_bubbleColor, 0);
            strokeColor = a.getColor(R.styleable.BubbleView_bubbleStrokeColor, 0);
            strokeWidth = a.getDimensionPixelOffset(R.styleable.BubbleView_bubbleStrokeWidth, 0);
            triangleHeight = a.getDimensionPixelOffset(R.styleable.BubbleView_triangleHeight, 30);
            triangleDirection = a.getInt(R.styleable.BubbleView_triangleDirection, 0);
            a.recycle();
        }
        setGravity(Gravity.CENTER);
        initPaint();
        labelHeight = getFontHeight() + getPaddingTop() + getPaddingBottom();
        height = labelHeight + triangleHeight * 2 + strokeWidth * 2;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        width = getPaddingStart() + getFontWidth() + getPaddingEnd() + strokeWidth * 2;
        setMeasuredDimension(width, height);
    }

    //初始化画笔
    public void initPaint() {
        mPaint = new Paint();
        //设置抗锯齿
        mPaint.setAntiAlias(true);
        //设置填充
        mPaint.setStyle(Paint.Style.FILL);
        //设置防抖动
        mPaint.setDither(true);
        //字体大小
        mPaint.setTextSize(getTextSize());
    }

    //初始化描边画笔
    public void initStrokePaint() {
        mStrokePaint = new Paint();
        mStrokePaint.setAntiAlias(true);
        mStrokePaint.setStyle(Paint.Style.FILL);
        mStrokePaint.setDither(true);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        drawView(canvas);
        super.onDraw(canvas);
    }

    //绘制气泡
    private void drawView(Canvas canvas) {
        if (strokeColor != 0 && strokeWidth != 0) {
            initStrokePaint();
            mStrokePaint.setColor(strokeColor);
            mRadius = labelHeight / 2 + strokeWidth;
            drawRound(canvas, mStrokePaint, 0);
            drawTriangle(canvas, mStrokePaint, 0);
        }
        if (bgColor != 0) {
            mPaint.setColor(bgColor);
            mRadius = labelHeight / 2;
            drawRound(canvas, mPaint, strokeWidth);
            drawTriangle(canvas, mPaint, strokeWidth);
        }
    }

    //绘制矩形
    private void drawRound(Canvas canvas, Paint paint, int stroke) {
        canvas.drawRoundRect(stroke, triangleHeight + stroke,
                width - stroke, height - triangleHeight - stroke,
                mRadius, mRadius, paint);
    }

    //绘制三角形
    private void drawTriangle(Canvas canvas, Paint paint, int stroke) {
        Path path = new Path();
        switch (triangleDirection) {
            //上
            case 1:
                path.moveTo(width / 2 - triangleHeight + stroke / 2, triangleHeight + stroke);
                path.lineTo(width / 2, stroke + stroke / 2);
                path.lineTo(width / 2 + triangleHeight - stroke / 2, triangleHeight + stroke);
                break;
            //下
            case 2:
                path.moveTo(width / 2 - triangleHeight + stroke / 2, height - triangleHeight - stroke);
                path.lineTo(width / 2, height - stroke - stroke / 2);
                path.lineTo(width / 2 + triangleHeight - stroke / 2, height - triangleHeight - stroke);
                break;
            default:
                return;
        }
        canvas.drawPath(path, paint);
    }

    //根据字号求字体高度
    private int getFontHeight() {
        Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
        return Math.round(fontMetrics.descent - fontMetrics.ascent);
    }

    //根据字号求字体宽度
    private int getFontWidth() {
        return (int) mPaint.measureText(getText().toString());
    }

    //设置气泡颜色
    public void setBubbleColor(int color) {
        this.bgColor = ContextCompat.getColor(getContext(), color);
        invalidate();
    }

    //设置气泡描边
    public void setStroke(int color, int width) {
        this.strokeColor = ContextCompat.getColor(getContext(), color);
        this.strokeWidth = width;
        invalidate();
    }
}

使用

        <com.lf.widget.BubbleView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:padding="6dp"
            android:text="向上向上"
            android:textColor="#000000"
            android:textSize="20sp"
            app:bubbleColor="#ffffff"
            app:bubbleStrokeColor="#000000"
            app:bubbleStrokeWidth="2dp"
            app:triangleDirection="top"
            app:triangleHeight="10dp" />

相关文章

网友评论

    本文标题:Android 自定义气泡TextView

    本文链接:https://www.haomeiwen.com/subject/wswtictx.html