Android实现好看的微信聊天气泡效果

目录
  • 前言
  • 代码实现
  • 踩坑记录
  • 总结

前言

在聊天类应用中,通常用气泡作为聊天内容的背景色,比如微信的聊天背景,别人发过来的是白色的气泡,自己发的是绿色的气泡。

上面这种是比较普通的,这篇我们玩点有趣的,让聊天气泡是渐变色的。可能很多人会觉得渐变很简单,给 Container 来个decoration或者使用 DecoratedBox,使用渐变填充色就可以了,比如下面这种效果: 这个感觉也太丑了,本篇我们来一个高级的 —— 整个聊天窗口的气泡颜色是渐变的,而且随着滚动还会变化!先看看实现的效果,这里有两个效果:

整个窗口的聊天气泡背景色是连续渐变的,而不是每个气泡重复的渐变。

滚动的时候,气泡的背景色会随着滚动的位置变化。

代码实现

使用 ContainerdecorationDecoratedBox 只能在渲染之前就确定好背景色,因此没法在绘制过程中动态改变气泡的背景色,要动态改变气泡背景色就需要自己绘制背景,那就需要使用到 CustomPaint

首先,我们来看如何绘制渐变背景色。画笔 Paint 对象有个shader 属性,可以配置绘制时的填充行为。来源可以是渐变填充的 Gradient 对象,或是图片的 Image 对象。比如我们要用线性渐变填充,那就可以使用下面的代码实现:

final paint = Paint()
  ..shader = LinearGradient(
    begin: Alignment.topCenter,
    end: Alignment.bottomCenter,
    colors: colors
  ).createShader(rect);

其中 createShader 函数就是用于将Gradient 转换为 shader对象。这里需要传一个矩形,即填充的矩形范围,这个参数我们可以利用来实现整个窗口的渐变填充,比如滚动的窗口我们可以设置为整个滚动窗口的矩形,这样填充范围就可以从当前气泡绘制的扩大到整个聊天窗口。

接下来是如何让当前气泡的填充色跟随滚动位置变化而变化。这里需要做两个操作:

  • 获取滚动过程中气泡在窗口的位置;
  • 将填充色转变到气泡滚动的位置。

获取滚动过程中气泡在窗口的位置需要使用滚动状态的 ScrollableState 对象,这个可以通过 Scrollable.of(context) 获取,这个方法会从组件树中最近的滚动组件中获取滚动状态对象,如果没有找到滚动组件的话则返回 nullScrollableState中可以找到当前渲染的滚动组件的窗口矩形,有了这个矩形,我们就可以获知气泡在滚动窗口的相对位置了,这个需要使用 localToGlobal 方法实现,代码如下:

final scrollableBox =
        scrollableState.context.findRenderObject() as RenderBox;
final bubbleBox = context.findRenderObject() as RenderBox;
final origin =
    bubbleBox.localToGlobal(Offset.zero, ancestor: scrollableBox);

有了这个相对位置,那么我们就可以把全部渐变颜色填充找到当前位置气饱应该要填充的颜色,这里需要使用到 LinearGradient 的一个 transform 参数。transform是一个 GradientTransform对象,实际是通过三维空间的转变实现的。这里我们自定义一个GradientTransform类为 ScrollGradientTransform,覆盖了GradientTransformtransform 方法,实际只是实现了三维的平移而已:

class ScrollGradientTransform extends GradientTransform {
  const ScrollGradientTransform(this.dx, this.dy, this.dz);

  final double dx, dy, dz;

  @override
  Matrix4 transform(Rect bounds, {TextDirection? textDirection}) {
    return Matrix4.identity()..translate(dx, dy, dz);
  }

  //...
}

然后我们将ScrollGradientTransformLinearGradienttransform 参数:

LinearGradient(
  begin: Alignment.topCenter,
  end: Alignment.bottomCenter,
  colors: colors,
  transform: ScrollGradientTransform(
    -origin.dx,
    -origin.dy,
    0.0,
),

这里取负号主要是往上滚的时候 origin.dy 是负数,为保持和设定的渐变色次序一样,才加上了负号。当然,如果是 横向滚动,就需要根据横向的方向决定origin.dx要不要加负号了。 有了这个之后,我们只需要绘制一个圆角矩形就好了,实际CustomPaintPainter 绘制代码很简单,代码如下:

class BubbleBackgroundPainter extends CustomPainter {
  final List<Color> colors;
  final ScrollableState scrollableState;
  final BuildContext context;
  const BubbleBackgroundPainter({
    Key? key,
    required this.colors,
    required this.scrollableState,
    required this.context,
  });

  @override
  void paint(Canvas canvas, Size size) {
    final scrollableBox =
        scrollableState.context.findRenderObject() as RenderBox;
    final bubbleBox = context.findRenderObject() as RenderBox;
    final origin =
        bubbleBox.localToGlobal(Offset.zero, ancestor: scrollableBox);

    final scrollableRect = Offset.zero & scrollableBox.size;
    final paint = Paint()
      ..shader = LinearGradient(
        begin: Alignment.topCenter,
        end: Alignment.bottomCenter,
        colors: colors,
        transform: ScrollGradientTransform(
          -origin.dx,
          -origin.dy,
          0.0,
        ),
      ).createShader(scrollableRect);

    canvas.drawRRect(
        RRect.fromRectAndRadius(
          Offset.zero & size,
          Radius.circular(10.0),
        ),
        paint);
  }

  @override
  bool shouldRepaint(covariant BubbleBackgroundPainter oldDelegate) {
    return oldDelegate.scrollableState != scrollableState ||
        oldDelegate.context != context ||
        oldDelegate.colors != colors;
  }
}

完整代码已经提交到:绘图相关代码,文件名为:gradient_background_bubble.dart

踩坑记录

这里调试过程发现了一个小坑,就是首次加载的时候是有渐变的,结果滚动后渐变效果消失了,当时百思不得其解,折腾了好久。后面才想起来是列表性能优化时的绘制缓存机制导致的,需要手动设置 ListViewaddRepaintBoundariesfalse,以让每次滚动的时候不复用之前的绘制结果,当然这样会有些性能上的损失。

总结

本篇使用 CustomPaint,通过计算当前绘制的气泡在滚动过程的中的相对位置实现了聊天气泡整个窗口渐变的效果,而且气泡会随着滚动位置不同的填充颜色也不同。相比之前的单一颜色的聊天气泡来说,这种气泡更加有趣,丰富多彩!实际上,对于本篇的渐变绘制我们可以理解为在窗口预先配置了渐变色,只是不会真的渲染,等到绘制气泡的时候才把窗口的渐变色作为气泡的背景色,于是就有了本篇的效果。

以上就是Android实现好看的微信聊天气泡效果的详细内容,更多关于Android聊天气泡的资料请关注我们其它相关文章!

(0)

相关推荐

  • Android自定义View实现气泡动画

    本文实例为大家分享了Android自定义View实现气泡动画的具体代码,供大家参考,具体内容如下 一.前言 最近有需求制作一个水壶的气泡动画,首先在网上查找了一番,找到了一个文章:Android实现气泡动画 测试了一下发现,如果把它作为子视图的话,会出现小球溢出边界的情况.所以简单的修改了一下. 二.代码 1. 随机移动的气泡 Ball类 /** * @author jiang yuhang * @date 2021-04-18 19:57 */ class Ball { // 半径 @kotl

  • Android实现气泡动画

    本文实例为大家分享了Android实现气泡动画的具体代码,供大家参考,具体内容如下 一.前言 本来想做一个类似window气泡屏保的动画效果. 奈何小球间的非对心碰撞公式没研究出来,对于我来说真的太复杂了,等公式给我研究差不多的时候,发现计算角度的问题也很复杂.博主表示高中的时候物理从未及格,而且这是大学物理的课程--然而我大学并没有学物理. 目前做出来的效果也很简单,只是检测了边界碰撞,原理就是动量守恒,速度交换. 实际效果如丝般顺滑,gif录制掉帧了. 二.实现代码 这次就不封装了,反正也只

  • android 仿微信聊天气泡效果实现思路

    微信聊天窗口的信息效果类似iphone上的短信效果,以气泡的形式展现,在Android上,实现这种效果主要用到ListView和BaseAdapter,配合布局以及相关素材,就可以自己做出这个效果,素材可以下一个微信的APK,然后把后缀名改成zip,直接解压,就可以得到微信里面的所有素材了.首先看一下我实现的效果: 以下是工程目录结构: 接下来就是如何实现这个效果的代码: main.xml,这个是主布局文件,显示listview和上下两部分内容. 复制代码 代码如下: <?xml version

  • Android使用贝塞尔曲线仿QQ聊天消息气泡拖拽效果

    本文实例为大家分享了Android仿QQ聊天消息气泡拖拽效果展示的具体代码,供大家参考,具体内容如下 先画圆,都会吧.代码如下: public class Bezier extends View { private final Paint mGesturePaint = new Paint(); private final Path mPath = new Path(); private float mX1 = 100, mY1 = 150; private float mX2 = 300, m

  • Android 实现仿QQ拖拽气泡效果的示例

    目录 效果图: 一.实现思路 二.功能实现 三.全屏拖拽效果实现 源码地址: 效果图: 一.实现思路 在列表中默认使用自定义的TextView控件来展示消息气泡,在自定义的TextView控件中重写onTouchEvent方法,然后在DOWN.MOVE.UP事件中分别处理拖拽效果. 整个拖拽效果我们可以拆分成以下几步来实现: 1.默认状态 2.两气泡相连状态 3.两气泡分离状态 4.气泡消失状态 二.功能实现 默认状态:用来做一个状态的标识,无需特别处理. 两气泡相连状态:绘制一个固定圆和一个移

  • Android气泡效果实现方法

    本文实例讲述了Android气泡效果实现方法.分享给大家供大家参考,具体如下: 最近在看以前在eoe上收藏的一些源代码,准备将这些代码加上一些自己的注释,然后贴出来,方便自己日后查阅,和刚入门的人来学习. 今天先看一个气泡窗口,先看一下效果图和目录结构,然后再上代码 通过第一幅图,我们可以看到一个气泡窗口,这个窗口的结构是里面有2个TextView和1个气泡的背景,这个2个TextView放在了overlay_pop.xml文件中,气泡窗口是这个layout的背景,overlay_pop.xml

  • Android实现好看的微信聊天气泡效果

    目录 前言 代码实现 踩坑记录 总结 前言 在聊天类应用中,通常用气泡作为聊天内容的背景色,比如微信的聊天背景,别人发过来的是白色的气泡,自己发的是绿色的气泡. 上面这种是比较普通的,这篇我们玩点有趣的,让聊天气泡是渐变色的.可能很多人会觉得渐变很简单,给 Container 来个decoration或者使用 DecoratedBox,使用渐变填充色就可以了,比如下面这种效果: 这个感觉也太丑了,本篇我们来一个高级的 —— 整个聊天窗口的气泡颜色是渐变的,而且随着滚动还会变化!先看看实现的效果,

  • Android 使用<layer-list>实现微信聊天输入框功能

    LayerDrawable  <layer-list> 标签可是设置LayerDrawable,一种有层次的Drawable叠加效果,<layer-list> 可以包含多个 <item>标签, 每个 <item>代表一个Drawable.<item>可以通过left.right.top.bottom设置左右上下的偏移量,<item>可以应用一个图片,也可以是一个shape 我们来模仿实现微信的聊天输入框: 先设置绿色的背景: <

  • Android仿硬币转动微信红包动画效果

    项目需要研究了一下微信红包动画,即硬币转动的效果,原理其实就是三张不同角度的图片利用AnimationDrawable帧动画进行播放,在参考了案例之后,给自己记录一下完成的过程. 1,在XML文件中定义动画: 步骤如下: ①新建 Android 项目 ②在drawable目录中新建一个anim.xml(注意文件名小写) <?xml version="1.0" encoding="utf-8"?> <animation-list xmlns:andr

  • Android中使用RecylerView实现聊天框效果

    从Android 5.0开始,谷歌公司推出了一个用于大量数据展示的新控件RecylerView,可以用来代替传统的ListView,更加强大和灵活.在上篇文章给大家介绍了Android RecylerView入门教程,大家可以点击查看详情. 效果图如下:(其中,聊天框背景图用9-patch图,可以内容自适应调节.利用AndroidStudio自带的功能制作就行了,图片->右键->create 9-patch file. 其中要注意的是: 1.将9-patch图保存到drawable目录下才管用

  • Android使用ViewDragHelper实现QQ聊天气泡拖动效果

    QQ聊天气泡拖动效果Android实现代码,供大家参考,具体内容如下 概述 本文的目的是实现类似于QQ消息提醒的气泡的拖拽效果.网上已有大神的实现效果是通过监听控件的OnTouchEvent事件的ACTION_DOWN,ACTION_MOVE,ACTION_UP事件来处理相应的拖拽效果,这里采用ViewDragHelper的方式去实现拖拽,顺便学习了一下ViewDragHelper的使用方式,拖拽时的粘连效果采用贝塞尔曲线来实现. 用ViewDragHelper实现拖拽效果 ViewDragHe

  • Android文本视图TextView实现聊天室效果

    本文实例为大家分享了Android文本视图TextView实现聊天室的具体代码,供大家参考,具体内容如下 Math.random()生成随机数的范围是 0 到 1 之间的 日期时间格式new SimpleDateFormat("dd-MM-yyyy HH:mm:ss"); //年-月-日 时:分:秒  : HH大写24小时, String类的format()方法用于创建格式化的字符串以及连接多个字符串对象. MainActivity package com.example.junior

  • Android仿QQ、微信聊天界面长按提示框效果

    先来看看效果图 如何使用 示例代码 PromptViewHelper pvHelper = new PromptViewHelper(mActivity); pvHelper.setPromptViewManager(new ChatPromptViewManager(mActivity)); pvHelper.addPrompt(holder.itemView.findViewById(R.id.textview_content)); 使用起来还是很简单的 首先new一个PromptViewH

  • JavaScript实现好看的跟随彩色气泡效果

    本文实例为大家分享了js实现跟随彩色气泡的具体代码,供大家参考,具体内容如下 代码: <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> <style> *{ margin:0;padding:0; } body{overflow:hidden;} #canvas{ background-color:black;

随机推荐