实现微信聊天界面的泡泡对话框效果(改进)

=2019.05.31 下午更新====
实际测试发现改进以后的方案会有BUG,目前暂时没有解决办法,因此建议使用最早的方案
=2019.05.31 上午更新====
**昨晚连夜赶了一个DEMO出来,今天实际使用的时候发现很不友好,于是做了一下改进,改进以后的代码只需要设置.9图片作为背景图即可,代码如下 该方案有严重BUG请勿实际运用到项目中 **

public class ChatItemLayout extends FrameLayout {
    String tag = "ChatItemLayout";

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

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

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



    @Override
    protected void dispatchDraw(Canvas canvas) {
        int layer = canvas.saveLayer(new RectF(0, 0, canvas.getWidth(), canvas.getHeight()), null, Canvas
                .ALL_SAVE_FLAG);
        super.dispatchDraw(canvas);
        Drawable background = getBackground();
        //这里只绘制.9 因为非.9图片的Drawable对象 无法获取Paint 所以无法设置混合模式
        //所以大家使用的时候 需要把图片做一下处理 都转为.9
        if (background instanceof NinePatchDrawable) {
            NinePatchDrawable drawable = (NinePatchDrawable) background;
            Paint mPaint = drawable.getPaint();
            mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
            drawable.draw(canvas);
        }
        canvas.restoreToCount(layer);
    }
}

=2019.05.30更新====

我们先来看看这个泡泡效果具体是什么

如上图所示,这是聊天界面中有人发送的视频,这个泡泡背景左上有个尖角,按照我们普通的设计来说,这个角要么是空白的,要么视频内容完全覆盖了那个尖角。
那么我们如何才能实现截图中的效果呢,这里我们就需要用到安卓自定义UI中遮罩相关的API了,网上关于这个说明很多了,我这里就提一个关键字,大家可以去搜相关的文章来看:PorterDuffXfermode
另外我们这里还需要涉及到另外一个知识点,那就是这个泡泡背景一般情况下为了能够自定义内容大小,一般都是做成了.9图片的,那么.9图片在这里面如何进行绘制呢?这里我们就要依赖另外一个类:NinePatch。下面我们就开始进行自定义吧。
首先我们为了扩展方便,这里我们自定义的控件选择继承FrameLayout,这样的话我们可以选择在里面放我们任何需要放置的控件。
接下来我们首先就要取出我们的.9背景图并且转换为Bitmap

//R.drawable.chat_bubbles_from2 是我这里的.9图 大家可以改成自己的.9图
mBackgroundBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.chat_bubbles_from2);
//这里我们创建一个NinePatch对象,这个对象一会儿我们就能直接用于绘制
mNinePatch = new NinePatch(mBackgroundBitmap,mBackgroundBitmap.getNinePatchChunk(),null);

然后我们就需要在dispatchDraw方法中绘制我们的遮罩了

	@Override
    protected void dispatchDraw(Canvas canvas) {
    //这里相当于我们创建了一个新的图层,如果不创建的话,最后出来的效果图会存在黑边
        int layer = canvas.saveLayer(new RectF(0, 0, canvas.getWidth(), canvas.getHeight()), null, Canvas
                .ALL_SAVE_FLAG);
      //绘制需要展示的内容,也就是先画DST,我们的泡泡背景图作为SRC
      //这里需要注意的是,我们在xml写布局的时候,还是需要设置background的,我们这里只是拿了一张和
      //background一样的图片来做遮罩效果
        super.dispatchDraw(canvas);
        //创建一个和控件一样大小的矩阵
        Rect r = new Rect(0,0,getWidth(),getHeight());
        //设置画笔的混合模式 DST_IN 表示绘制相交部分的DST的内容
        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
        //后绘制SRC 
        mNinePatch.draw(canvas,r,mPaint);
        //恢复图层
        canvas.restoreToCount(layer);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值