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.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;
import com.recycleviewrefresh.android.MyApplication;
import com.recycleviewrefresh.android.R;
import com.recycleviewrefresh.android.utils.ImageUtils;
/**
* Created by wangliang on 0027/2017/3/27.
* 创建时间: 0027/2017/3/27 14:06
* 创建人:王亮(Loren wang)
* 功能作用:气泡对话框
* 思路:使用三层覆盖的方法,最底层使用path绘制出来一个带有箭头的圆角黑图,然后使用图片相交模式中的LIGHTEN方式进行
* 显示截取(其他方法不知道为什么不行反而有问题),然后再使用path再绘制一个带有箭头的圆角边框,然后不要使用paint绘制到画布上
* 修改人:
* 修改时间:
* 备注:
*/
public class BubbleImageView extends ImageView {
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 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 Bitmap mBitmap;
private float[] radiusArray = { 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f };//圆角半径集合
public BubbleImageView(Context context) {
this(context,null);
}
public BubbleImageView(Context context, AttributeSet attrs) {
this(context,attrs,0);
}
public BubbleImageView(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.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);
}
/**
* 将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) {
if(getMeasuredHeight() != 0 && getMeasuredWidth() != 0
&& getDrawable() != null && mBitmap != null){
//绘制底图范围
canvas.drawBitmap(initBubbleBackGroundBitmap(),0,0,paint);
//设置图形相交模式
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.LIGHTEN));
//画覆盖层(蓝色矩形)SRC
canvas.drawBitmap(mBitmap
, new Rect(0,0,getMeasuredWidth(),getMeasuredHeight())
, new Rect(0,0,getMeasuredWidth(),getMeasuredHeight())
, paint);
if(bubbleStrokeWidth != 0) {
//绘制顶图边框
canvas.drawBitmap(initBubbleStrokeBitmap(), 0, 0, null);
}
}
}
/**
* 初始化底图位图
* @return
*/
private Bitmap initBubbleBackGroundBitmap(){
int paddingLeft = getPaddingLeft();
int paddingTop = getPaddingTop();
int paddingRight = getPaddingRight();
int paddingBottopm = getPaddingBottom();
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);
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 = getPaddingLeft();
int paddingTop = getPaddingTop();
int paddingRight = getPaddingRight();
int paddingBottopm = getPaddingBottom();
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 setImageBitmap(Bitmap bm) {
try {
super.setImageBitmap(bm);
mBitmap = bm;
postInvalidate();
}catch (Exception e){
e.printStackTrace();
}
}
@Override
public void setImageDrawable(Drawable drawable) {
try {
super.setImageDrawable(drawable);
mBitmap = ImageUtils.getInstance().getBitmapFromDrawable(drawable);
postInvalidate();
}catch (Exception e){
e.printStackTrace();
}
}
@Override
public void setImageResource(int resId) {
try {
super.setImageResource(resId);
mBitmap = ImageUtils.getInstance().getBitmapFromDrawable(getDrawable());
postInvalidate();
}catch (Exception e){
e.printStackTrace();
}
}
}
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" />
declare-styleable>