安卓开发之文本气泡聊天框

ps:个人习惯吧注释以及思路直接放到代码里,所以这里就不直接写过程了,直接上代码

package com.recycleviewrefresh.android.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.widget.TextView;

import com.recycleviewrefresh.android.MyApplication;
import com.recycleviewrefresh.android.R;


/**
 * Created by wangliang on 0027/2017/3/27.
 * 创建时间: 0027/2017/3/27 14:06
 * 创建人:王亮(Loren wang)
 * 功能作用:气泡对话框
 * 思路:使用三层覆盖的方法,最底层使用path绘制出来一个带有箭头的圆角底图,在绘制文字(ps:在初始化的时候要使背景为空,然后使用单独的参数设置背景,否则背景会影响显示)
 *        然后再使用path再绘制一个带有箭头的圆角边框,然后不要使用paint绘制到画布上
 * 修改人:
 * 修改时间:
 * 备注:
 */

public class BubbleTextView extends TextView {


    private Context context;
    private Paint paint;//基础画笔

    private int bubbleArrowWidth;//气泡箭头的宽度
    private int bubbleArrowHeight;//气泡箭头的高度
    private boolean bubbleArrowWhetherCenterVertical;//气泡箭头是否居中
    private int bubbleRadius;//气泡的圆角角度
    private String bubbleDirection;//气泡的方向
    private int bubbleMarginTop;//气泡的如果不居中的话距离顶部的距离
    private int bubbleMarginLeft;//气泡的如果不居中的话距离左边的距离
    private int bubbleStrokeWidth;//气泡边框的宽度
    private int bubbleStrokeColor;//气泡边框的颜色
    private int bubbleBackGround;//气泡背景颜色

    private final String BUBBLE_DIRECTION_LEFT = "0";
    private final String BUBBLE_DIRECTION_TOP = "1";
    private final String BUBBLE_DIRECTION_RIGHT = "2";
    private final String BUBBLE_DIRECTION_BOTTOM = "3";

    private float[] radiusArray = { 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f };//圆角半径集合

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

    public BubbleTextView(Context context, AttributeSet attrs) {
        this(context,attrs,0);
    }

    public BubbleTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        this.context = context;

        TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.bubble);
        this.bubbleArrowWidth = attributes.getDimensionPixelOffset(R.styleable.bubble_bubbleArrowWidth,dip2px(10));
        this.bubbleArrowHeight = attributes.getDimensionPixelOffset(R.styleable.bubble_bubbleArrowHeight,dip2px(10));
        this.bubbleArrowWhetherCenterVertical = attributes.getBoolean(R.styleable.bubble_bubbleArrowWhetherCenterVertical,true);
        this.bubbleRadius = attributes.getDimensionPixelOffset(R.styleable.bubble_bubbleRadius,dip2px(8));
        this.bubbleMarginTop = attributes.getDimensionPixelOffset(R.styleable.bubble_bubbleMarginTop,dip2px(10));
        this.bubbleMarginLeft = attributes.getDimensionPixelOffset(R.styleable.bubble_bubbleMarginLeft,dip2px(10));
        this.bubbleStrokeWidth = attributes.getDimensionPixelOffset(R.styleable.bubble_bubbleStrokeWidth,0);
        this.bubbleStrokeColor = attributes.getColor(R.styleable.bubble_bubbleStrokeColor, Color.RED);
        this.bubbleBackGround = attributes.getColor(R.styleable.bubble_bubbleBackGround, Color.parseColor("#00ffffff"));
        this.bubbleDirection = attributes.getString(R.styleable.bubble_bubbleDirection);
        if(this.bubbleDirection == null || "".equals(this.bubbleDirection)){
            this.bubbleDirection = BUBBLE_DIRECTION_LEFT;
        }

        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setStyle(Paint.Style.FILL);
        paint.setStrokeWidth(bubbleStrokeWidth);
        paint.setColor(bubbleStrokeColor);
        //设置系统背景为空
        setBackground(null);
        int newPaddingLeft = getPaddingLeft();
        int newPaddingTop = getPaddingTop();
        int newPaddingRight = getPaddingRight();
        int newPaddingBottom = getPaddingBottom();
        //设置偏移量
        switch (this.bubbleDirection) {
            case BUBBLE_DIRECTION_LEFT:
                newPaddingLeft += bubbleArrowWidth + bubbleStrokeWidth;
                newPaddingTop += bubbleStrokeWidth;
                newPaddingRight += bubbleStrokeWidth;
                newPaddingBottom += bubbleStrokeWidth;
                break;
            case BUBBLE_DIRECTION_TOP:
                newPaddingLeft += bubbleStrokeWidth;
                newPaddingTop += bubbleArrowHeight + bubbleStrokeWidth;
                newPaddingRight += bubbleStrokeWidth;
                newPaddingBottom += bubbleStrokeWidth;
                break;
            case BUBBLE_DIRECTION_RIGHT:
                newPaddingLeft += bubbleStrokeWidth;
                newPaddingTop += bubbleStrokeWidth;
                newPaddingRight += bubbleArrowWidth + bubbleStrokeWidth;
                newPaddingBottom += bubbleStrokeWidth;
                break;
            case BUBBLE_DIRECTION_BOTTOM:
                newPaddingLeft += bubbleStrokeWidth;
                newPaddingTop += bubbleStrokeWidth;
                newPaddingRight += bubbleStrokeWidth;
                newPaddingBottom += bubbleArrowHeight + bubbleStrokeWidth;
                break;
        }

        setPadding(newPaddingLeft,newPaddingTop,newPaddingRight,newPaddingBottom);

    }


    /**
     * 将dip或dp值转换为px值,保证尺寸大小不变
     *
     * @param dipValue
     * @return
     */
    public int dip2px(float dipValue) {
        if (context == null) {
            context = MyApplication.getContext();
        }
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dipValue * scale + 0.5f);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        //绘制底图范围
        canvas.drawBitmap(initBubbleBackGroundBitmap(),0,0,paint);
        super.onDraw(canvas);
        if(bubbleStrokeWidth != 0) {
            //绘制顶图边框
            canvas.drawBitmap(initBubbleStrokeBitmap(), 0, 0, null);
        }

    }


    /**
     * 初始化底图位图
     * @return
     */
    private Bitmap initBubbleBackGroundBitmap(){
        int paddingLeft = 0;
        int paddingTop = 0;
        int paddingRight = 0;
        int paddingBottopm = 0;
        int viewWidth = getMeasuredWidth();
        int viewHeight = getMeasuredHeight();
        Bitmap bubbleBackGroundBitmap = Bitmap.createBitmap(viewWidth ,viewHeight,Bitmap.Config.ARGB_8888);
        Canvas bubbleBackGroundCanvas = new Canvas(bubbleBackGroundBitmap);
        Paint bubbleBackGroundPaint = new Paint();
        bubbleBackGroundPaint.setAntiAlias(true);
        bubbleBackGroundPaint.setStyle(Paint.Style.FILL);
        bubbleBackGroundPaint.setColor(bubbleBackGround);
        Path bubbleBackGroundPath = new Path();

        int nowBubbleArrowX = 0;//箭头的尖的坐标
        int nowBubbleArrowY = 0;//箭头的尖的坐标
        switch (this.bubbleDirection) {
            case BUBBLE_DIRECTION_LEFT:
                if(bubbleArrowWhetherCenterVertical){
                    nowBubbleArrowX = paddingLeft + bubbleStrokeWidth / 2;
                    nowBubbleArrowY = (viewHeight - paddingTop - paddingBottopm) / 2 + paddingTop;
                }else {
                    nowBubbleArrowX = paddingLeft + bubbleStrokeWidth / 2;
                    nowBubbleArrowY = bubbleMarginTop + paddingTop;
                }
                //绘制实心箭头
                bubbleBackGroundPath.moveTo(nowBubbleArrowX + bubbleArrowWidth,nowBubbleArrowY - bubbleArrowHeight / 2);
                bubbleBackGroundPath.lineTo(nowBubbleArrowX,nowBubbleArrowY);
                bubbleBackGroundPath.lineTo(nowBubbleArrowX + bubbleArrowWidth,nowBubbleArrowY + bubbleArrowHeight / 2);
                //绘制圆角矩形
                bubbleBackGroundPath.addRoundRect(new RectF(nowBubbleArrowX + bubbleArrowWidth
                                ,bubbleStrokeWidth / 2 + paddingTop
                                ,viewWidth - bubbleStrokeWidth / 2 - paddingRight
                                ,viewHeight - bubbleStrokeWidth / 2 - paddingBottopm)
                        ,bubbleRadius,bubbleRadius, Path.Direction.CCW);
                //绘制到画布
                bubbleBackGroundCanvas.drawPath(bubbleBackGroundPath,bubbleBackGroundPaint);
                break;
            case BUBBLE_DIRECTION_TOP:
                if(bubbleArrowWhetherCenterVertical){
                    nowBubbleArrowX = (viewWidth - paddingLeft - paddingRight) / 2 + paddingLeft;
                    nowBubbleArrowY = paddingTop + bubbleStrokeWidth / 2;
                }else {
                    nowBubbleArrowX = paddingLeft + bubbleMarginLeft;
                    nowBubbleArrowY = paddingTop + bubbleStrokeWidth / 2;
                }
                //绘制实心箭头
                bubbleBackGroundPath.moveTo(nowBubbleArrowX + bubbleArrowWidth / 2,nowBubbleArrowY + bubbleArrowHeight);
                bubbleBackGroundPath.lineTo(nowBubbleArrowX,nowBubbleArrowY);
                bubbleBackGroundPath.lineTo(nowBubbleArrowX - bubbleArrowWidth / 2,nowBubbleArrowY + bubbleArrowHeight);
                //绘制圆角矩形
                bubbleBackGroundPath.addRoundRect(new RectF(paddingLeft + bubbleStrokeWidth / 2
                                ,nowBubbleArrowY + bubbleArrowHeight
                                ,viewWidth - bubbleStrokeWidth / 2 - paddingRight
                                ,viewHeight - bubbleStrokeWidth / 2 - paddingBottopm)
                        ,bubbleRadius,bubbleRadius, Path.Direction.CCW);
                //绘制到画布
                bubbleBackGroundCanvas.drawPath(bubbleBackGroundPath,bubbleBackGroundPaint);
                break;
            case BUBBLE_DIRECTION_RIGHT:
                if(bubbleArrowWhetherCenterVertical){
                    nowBubbleArrowX = viewWidth - paddingRight - bubbleStrokeWidth / 2;
                    nowBubbleArrowY = (viewHeight - paddingTop - paddingBottopm) / 2 + paddingTop;
                }else {
                    nowBubbleArrowX = viewWidth - paddingRight - bubbleStrokeWidth / 2;
                    nowBubbleArrowY = bubbleMarginTop + paddingTop;
                }
                //绘制实心箭头
                bubbleBackGroundPath.moveTo(nowBubbleArrowX - bubbleArrowWidth,nowBubbleArrowY - bubbleArrowHeight / 2);
                bubbleBackGroundPath.lineTo(nowBubbleArrowX,nowBubbleArrowY);
                bubbleBackGroundPath.lineTo(nowBubbleArrowX - bubbleArrowWidth,nowBubbleArrowY + bubbleArrowHeight / 2);
                //绘制圆角矩形
                bubbleBackGroundPath.addRoundRect(new RectF(paddingLeft + bubbleStrokeWidth / 2
                                ,bubbleStrokeWidth / 2 + paddingTop
                                ,nowBubbleArrowX - bubbleArrowWidth
                                ,viewHeight - bubbleStrokeWidth / 2 - paddingBottopm)
                        ,bubbleRadius,bubbleRadius, Path.Direction.CCW);
                //绘制到画布
                bubbleBackGroundCanvas.drawPath(bubbleBackGroundPath,bubbleBackGroundPaint);
                break;
            case BUBBLE_DIRECTION_BOTTOM:
                if(bubbleArrowWhetherCenterVertical){
                    nowBubbleArrowX = (viewWidth - paddingLeft - paddingRight) / 2 + paddingLeft;
                    nowBubbleArrowY = viewHeight - paddingBottopm - bubbleStrokeWidth / 2;
                }else {
                    nowBubbleArrowX = paddingLeft + bubbleMarginLeft;
                    nowBubbleArrowY = viewHeight - paddingBottopm - bubbleStrokeWidth / 2;
                }
                //绘制实心箭头
                bubbleBackGroundPath.moveTo(nowBubbleArrowX + bubbleArrowWidth / 2,nowBubbleArrowY - bubbleArrowHeight);
                bubbleBackGroundPath.lineTo(nowBubbleArrowX,nowBubbleArrowY);
                bubbleBackGroundPath.lineTo(nowBubbleArrowX - bubbleArrowWidth / 2,nowBubbleArrowY - bubbleArrowHeight);
                //绘制圆角矩形
                bubbleBackGroundPath.addRoundRect(new RectF(paddingLeft + bubbleStrokeWidth / 2
                                ,paddingTop + bubbleStrokeWidth / 2
                                ,viewWidth - bubbleStrokeWidth / 2 - paddingRight
                                ,nowBubbleArrowY - bubbleArrowHeight)
                        ,bubbleRadius,bubbleRadius, Path.Direction.CCW);
                //绘制到画布
                bubbleBackGroundCanvas.drawPath(bubbleBackGroundPath,bubbleBackGroundPaint);
                break;
        }

        return bubbleBackGroundBitmap;

    }

    /**
     * 流程:先确定方向--》确定箭头尖部的坐标--》确定箭头三个点的位置坐标---》绘制圆角矩形
     * @return
     */
    private Bitmap initBubbleStrokeBitmap(){
        int paddingLeft = 0;
        int paddingTop = 0;
        int paddingRight = 0;
        int paddingBottopm = 0;
        int viewWidth = getMeasuredWidth();
        int viewHeight = getMeasuredHeight();
        Bitmap bubbleStrokeBitmap = Bitmap.createBitmap(viewWidth ,viewHeight,Bitmap.Config.ARGB_8888);
        Canvas bubbleStrokeCanvas = new Canvas(bubbleStrokeBitmap);
        Paint bubbleStrokePaint = new Paint();
        bubbleStrokePaint.setAntiAlias(true);
        bubbleStrokePaint.setStyle(Paint.Style.STROKE);
        bubbleStrokePaint.setColor(bubbleStrokeColor);
        bubbleStrokePaint.setStrokeWidth(bubbleStrokeWidth);
        Path bubbleStrokePath = new Path();
        Paint bubbleStrokeOverlayPaint;
        Path bubbleStrokeOverlayPath;

        int nowBubbleArrowX = 0;//箭头的尖的坐标
        int nowBubbleArrowY = 0;//箭头的尖的坐标
        switch (this.bubbleDirection) {
            case BUBBLE_DIRECTION_LEFT:
                if(bubbleArrowWhetherCenterVertical){
                    nowBubbleArrowX = paddingLeft + bubbleStrokeWidth / 2;
                    nowBubbleArrowY = (viewHeight - paddingTop - paddingBottopm) / 2 + paddingTop;
                }else {
                    nowBubbleArrowX = paddingLeft + bubbleStrokeWidth / 2;
                    nowBubbleArrowY = bubbleMarginTop + paddingTop;
                }
                //绘制实心箭头
                bubbleStrokePath.moveTo(nowBubbleArrowX + bubbleArrowWidth,nowBubbleArrowY - bubbleArrowHeight / 2);
                bubbleStrokePath.lineTo(nowBubbleArrowX,nowBubbleArrowY);
                bubbleStrokePath.lineTo(nowBubbleArrowX + bubbleArrowWidth,nowBubbleArrowY + bubbleArrowHeight / 2);
                bubbleStrokePaint.setStyle(Paint.Style.FILL);
                bubbleStrokeCanvas.drawPath(bubbleStrokePath,bubbleStrokePaint);
                //绘制空心圆角矩形
                bubbleStrokePaint.setStyle(Paint.Style.STROKE);
                bubbleStrokePath.addRoundRect(new RectF(nowBubbleArrowX + bubbleArrowWidth
                        ,bubbleStrokeWidth / 2 + paddingTop
                        ,viewWidth - bubbleStrokeWidth / 2 - paddingRight
                        ,viewHeight - bubbleStrokeWidth / 2 - paddingBottopm)
                        ,bubbleRadius,bubbleRadius, Path.Direction.CCW);
                //绘制到画布
                bubbleStrokeCanvas.drawPath(bubbleStrokePath,bubbleStrokePaint);
                bubbleStrokeCanvas.save();
                //绘制覆盖掉箭头的封闭线的实心三角
                bubbleStrokeOverlayPaint = new Paint(bubbleStrokePaint);
                bubbleStrokeOverlayPaint.setStyle(Paint.Style.FILL);
                bubbleStrokeOverlayPaint.setColor(Color.parseColor("#00ffffff"));//使用透明的颜色可以使范围设置的稍微大一些,防止出现2.5dp这种情况
                bubbleStrokeOverlayPaint.setStrokeWidth(1);
                bubbleStrokeOverlayPaint.setAntiAlias(true);
                bubbleStrokeOverlayPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));//设置覆盖物的显示方式
                bubbleStrokeOverlayPath = new Path();
                bubbleStrokeOverlayPath.moveTo(nowBubbleArrowX + bubbleArrowWidth + bubbleStrokeWidth,nowBubbleArrowY - bubbleArrowHeight / 2);
                bubbleStrokeOverlayPath.lineTo(nowBubbleArrowX + bubbleStrokeWidth,nowBubbleArrowY);
                bubbleStrokeOverlayPath.lineTo(nowBubbleArrowX + bubbleArrowWidth + bubbleStrokeWidth,nowBubbleArrowY + bubbleArrowHeight / 2);
                bubbleStrokeOverlayPath.close();
                //绘制进行覆盖显示
                bubbleStrokeCanvas.drawPath(bubbleStrokeOverlayPath,bubbleStrokeOverlayPaint);
                bubbleStrokeCanvas.restore();
                break;
            case BUBBLE_DIRECTION_TOP:
                if(bubbleArrowWhetherCenterVertical){
                    nowBubbleArrowX = (viewWidth - paddingLeft - paddingRight) / 2 + paddingLeft;
                    nowBubbleArrowY = paddingTop + bubbleStrokeWidth / 2;
                }else {
                    nowBubbleArrowX = paddingLeft + bubbleMarginLeft;
                    nowBubbleArrowY = paddingTop + bubbleStrokeWidth / 2;
                }
                //绘制实心箭头
                bubbleStrokePath.moveTo(nowBubbleArrowX + bubbleArrowWidth / 2,nowBubbleArrowY + bubbleArrowHeight);
                bubbleStrokePath.lineTo(nowBubbleArrowX,nowBubbleArrowY);
                bubbleStrokePath.lineTo(nowBubbleArrowX - bubbleArrowWidth / 2,nowBubbleArrowY + bubbleArrowHeight);
                bubbleStrokePaint.setStyle(Paint.Style.FILL);
                bubbleStrokeCanvas.drawPath(bubbleStrokePath,bubbleStrokePaint);
                //绘制空心圆角矩形
                bubbleStrokePaint.setStyle(Paint.Style.STROKE);
                bubbleStrokePath.addRoundRect(new RectF(paddingLeft + bubbleStrokeWidth / 2
                                ,nowBubbleArrowY + bubbleArrowHeight
                                ,viewWidth - bubbleStrokeWidth / 2 - paddingRight
                                ,viewHeight - bubbleStrokeWidth / 2 - paddingBottopm)
                        ,bubbleRadius,bubbleRadius, Path.Direction.CCW);
                //绘制到画布
                bubbleStrokeCanvas.drawPath(bubbleStrokePath,bubbleStrokePaint);
                bubbleStrokeCanvas.save();
                //绘制覆盖掉箭头的封闭线的实心三角
                bubbleStrokeOverlayPaint = new Paint(bubbleStrokePaint);
                bubbleStrokeOverlayPaint.setStyle(Paint.Style.FILL);
                bubbleStrokeOverlayPaint.setColor(Color.parseColor("#00ffffff"));//使用透明的颜色可以使范围设置的稍微大一些,防止出现2.5dp这种情况
                bubbleStrokeOverlayPaint.setStrokeWidth(1);
                bubbleStrokeOverlayPaint.setAntiAlias(true);
                bubbleStrokeOverlayPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));//设置覆盖物的显示方式
                bubbleStrokeOverlayPath = new Path();
                bubbleStrokeOverlayPath.moveTo(nowBubbleArrowX + bubbleArrowWidth / 2,nowBubbleArrowY + bubbleArrowHeight + bubbleStrokeWidth);
                bubbleStrokeOverlayPath.lineTo(nowBubbleArrowX,nowBubbleArrowY + bubbleStrokeWidth);
                bubbleStrokeOverlayPath.lineTo(nowBubbleArrowX - bubbleArrowWidth / 2,nowBubbleArrowY + bubbleArrowHeight + bubbleStrokeWidth);
                bubbleStrokeOverlayPath.close();
                //绘制进行覆盖显示
                bubbleStrokeCanvas.drawPath(bubbleStrokeOverlayPath,bubbleStrokeOverlayPaint);
                bubbleStrokeCanvas.restore();
                break;
            case BUBBLE_DIRECTION_RIGHT:
                if(bubbleArrowWhetherCenterVertical){
                    nowBubbleArrowX = viewWidth - paddingRight - bubbleStrokeWidth / 2;
                    nowBubbleArrowY = (viewHeight - paddingTop - paddingBottopm) / 2 + paddingTop;
                }else {
                    nowBubbleArrowX = viewWidth - paddingRight - bubbleStrokeWidth / 2;
                    nowBubbleArrowY = bubbleMarginTop + paddingTop;
                }
                //绘制实心箭头
                bubbleStrokePath.moveTo(nowBubbleArrowX - bubbleArrowWidth,nowBubbleArrowY - bubbleArrowHeight / 2);
                bubbleStrokePath.lineTo(nowBubbleArrowX,nowBubbleArrowY);
                bubbleStrokePath.lineTo(nowBubbleArrowX - bubbleArrowWidth,nowBubbleArrowY + bubbleArrowHeight / 2);
                bubbleStrokePaint.setStyle(Paint.Style.FILL);
                bubbleStrokeCanvas.drawPath(bubbleStrokePath,bubbleStrokePaint);
                //绘制空心圆角矩形
                bubbleStrokePaint.setStyle(Paint.Style.STROKE);
                bubbleStrokePath.addRoundRect(new RectF(paddingLeft + bubbleStrokeWidth / 2
                                ,bubbleStrokeWidth / 2 + paddingTop
                                ,nowBubbleArrowX - bubbleArrowWidth
                                ,viewHeight - bubbleStrokeWidth / 2 - paddingBottopm)
                        ,bubbleRadius,bubbleRadius, Path.Direction.CCW);
                //绘制到画布
                bubbleStrokeCanvas.drawPath(bubbleStrokePath,bubbleStrokePaint);
                bubbleStrokeCanvas.save();
                //绘制覆盖掉箭头的封闭线的实心三角
                bubbleStrokeOverlayPaint = new Paint(bubbleStrokePaint);
                bubbleStrokeOverlayPaint.setStyle(Paint.Style.FILL);
                bubbleStrokeOverlayPaint.setColor(Color.parseColor("#00ffffff"));//使用透明的颜色可以使范围设置的稍微大一些,防止出现2.5dp这种情况
                bubbleStrokeOverlayPaint.setStrokeWidth(1);
                bubbleStrokeOverlayPaint.setAntiAlias(true);
                bubbleStrokeOverlayPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));//设置覆盖物的显示方式
                bubbleStrokeOverlayPath = new Path();
                bubbleStrokeOverlayPath.moveTo(nowBubbleArrowX - bubbleArrowWidth - bubbleStrokeWidth ,nowBubbleArrowY - bubbleArrowHeight / 2);
                bubbleStrokeOverlayPath.lineTo(nowBubbleArrowX - bubbleStrokeWidth,nowBubbleArrowY);
                bubbleStrokeOverlayPath.lineTo(nowBubbleArrowX - bubbleArrowWidth - bubbleStrokeWidth,nowBubbleArrowY + bubbleArrowHeight / 2);
                bubbleStrokeOverlayPath.close();
                //绘制进行覆盖显示
                bubbleStrokeCanvas.drawPath(bubbleStrokeOverlayPath,bubbleStrokeOverlayPaint);
                bubbleStrokeCanvas.restore();
                break;
            case BUBBLE_DIRECTION_BOTTOM:
                if(bubbleArrowWhetherCenterVertical){
                    nowBubbleArrowX = (viewWidth - paddingLeft - paddingRight) / 2 + paddingLeft;
                    nowBubbleArrowY = viewHeight - paddingBottopm - bubbleStrokeWidth / 2;
                }else {
                    nowBubbleArrowX = paddingLeft + bubbleMarginLeft;
                    nowBubbleArrowY = viewHeight - paddingBottopm - bubbleStrokeWidth / 2;
                }
                //绘制实心箭头
                bubbleStrokePath.moveTo(nowBubbleArrowX + bubbleArrowWidth / 2,nowBubbleArrowY - bubbleArrowHeight);
                bubbleStrokePath.lineTo(nowBubbleArrowX,nowBubbleArrowY);
                bubbleStrokePath.lineTo(nowBubbleArrowX - bubbleArrowWidth / 2,nowBubbleArrowY - bubbleArrowHeight);
                bubbleStrokePaint.setStyle(Paint.Style.FILL);
                bubbleStrokeCanvas.drawPath(bubbleStrokePath,bubbleStrokePaint);
                //绘制空心圆角矩形
                bubbleStrokePaint.setStyle(Paint.Style.STROKE);
                bubbleStrokePath.addRoundRect(new RectF(paddingLeft + bubbleStrokeWidth / 2
                                ,paddingTop + bubbleStrokeWidth / 2
                                ,viewWidth - bubbleStrokeWidth / 2 - paddingRight
                                ,nowBubbleArrowY - bubbleArrowHeight)
                        ,bubbleRadius,bubbleRadius, Path.Direction.CCW);
                //绘制到画布
                bubbleStrokeCanvas.drawPath(bubbleStrokePath,bubbleStrokePaint);
                bubbleStrokeCanvas.save();
                //绘制覆盖掉箭头的封闭线的实心三角
                bubbleStrokeOverlayPaint = new Paint(bubbleStrokePaint);
                bubbleStrokeOverlayPaint.setStyle(Paint.Style.FILL);
                bubbleStrokeOverlayPaint.setColor(Color.parseColor("#00ffffff"));//使用透明的颜色可以使范围设置的稍微大一些,防止出现2.5dp这种情况
                bubbleStrokeOverlayPaint.setStrokeWidth(1);
                bubbleStrokeOverlayPaint.setAntiAlias(true);
                bubbleStrokeOverlayPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));//设置覆盖物的显示方式
                bubbleStrokeOverlayPath = new Path();
                bubbleStrokeOverlayPath.moveTo(nowBubbleArrowX + bubbleArrowWidth / 2,nowBubbleArrowY - bubbleArrowHeight - bubbleStrokeWidth);
                bubbleStrokeOverlayPath.lineTo(nowBubbleArrowX,nowBubbleArrowY - bubbleStrokeWidth);
                bubbleStrokeOverlayPath.lineTo(nowBubbleArrowX - bubbleArrowWidth / 2,nowBubbleArrowY - bubbleArrowHeight - bubbleStrokeWidth);
                bubbleStrokeOverlayPath.close();
                //绘制进行覆盖显示
                bubbleStrokeCanvas.drawPath(bubbleStrokeOverlayPath,bubbleStrokeOverlayPaint);
                bubbleStrokeCanvas.restore();
                break;
        }

        return bubbleStrokeBitmap;
    }

    @Override
    public void setBackgroundColor(int color) {
        super.setBackgroundColor(color);
    }
}

attrs资源文件:

<!--气泡图片的-->
    <declare-styleable name="bubble">
        <attr name="bubbleDirection">
            <enum name="left" value="0"></enum>
            <enum name="top" value="1"></enum>
            <enum name="right" value="2"></enum>
            <enum name="bottom" value="3"></enum>
        </attr>
        <attr name="bubbleArrowWidth" format="dimension" />
        <attr name="bubbleArrowHeight" format="dimension" />
        <attr name="bubbleArrowWhetherCenterVertical" format="boolean" />
        <attr name="bubbleRadius" format="dimension" />
        <attr name="bubbleMarginTop" format="dimension" />
        <attr name="bubbleMarginLeft" format="dimension" />
        <attr name="bubbleStrokeWidth" format="dimension" />
        <attr name="bubbleStrokeColor" format="color" />
        <attr name="bubbleBackGround" format="color" />
    </declare-styleable>
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值