从0系统学Android--3.7 聊天界面编写



本系列文章目录更多精品文章分类

本系列持续更新中....

3.7 编写界面的最佳实践

前面学习了那么多 UI 开发的知识,下面来进行实践,做一个美观的聊天界面。

3.7.1 制作 Nine-Patch 图片

实战前先学习一个小知识,如何制作 Nine-Patch 图片。

Nine-Patch 是一种被特殊处理的 .png图片,能够指定那些区域可以被拉伸,那些区域不可以。

来看看 Nine-Patch 图片的实际作用。

首先我们用一张普通的图片作为背景

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@mipmap/message_"
android:orientation="vertical">
</LinearLayout>

运行结果

可以看到效果非常糟糕,由于图片的宽度不能填满整个屏幕的宽度,整张图片就被均匀的拉伸的,效果很差,这种情况,我们就可以使用 Nine-Patch 图片来进行改善了。

如何创建 nine-patch 图片呢?

首先在 Android Studio 中选中你要变成 nine-patch 的图片,然后右击--->Create 9-Patch file 就可以创建 Nine-Patch 图片了。

我们可以在图片的四个边框绘制一个个的小黑点。在上边框和左边框的部分表示当前图片需要拉伸的时候就会拉伸黑色点标记的区域,在下边框和右边框的部分表示内容会被放置的区域。用鼠标在图片的边缘拖到就可以进行绘制了。按住 Shift 键拖动可以进行擦除。

再来看看使用 nine-patch 的效果

这样当图片需要拉伸的时候就只拉伸指定区域了。

3.7.2 编写精美的聊天界面

聊天界面肯定有收到的消息和发送的消息,上面我们已经把发送消息的背景图制作好了,再制作一张发送消息的背景图。

图片资源都准备好了,就可以写代码了。

编写主页面布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rlv"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/et_info"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="发送信息"
android:maxLines="2"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="发送"
android:id="@+id/bt_send"/>
</LinearLayout>
</LinearLayout>

建立聊天的消息对象

public class Msg {
public static final int TYPE_RECEIVE = 0;
public static final int TYPE_SEND = 1;
private String content; public Msg(String content, int type) {
this.content = content;
this.type = type;
} private int type; public String getContent() {
return content;
} public void setContent(String content) {
this.content = content;
} public int getType() {
return type;
} public void setType(int type) {
this.type = type;
}
}

type 用来指定消息的类型,是发送的消息还接受的消息

然后编写 RecyclerView 的子项布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:orientation="vertical">
<LinearLayout
android:id="@+id/ll_left"
android:background="@mipmap/message_left"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:id="@+id/tv_left"
android:textColor="#FFF"
android:layout_margin="10dp"/> </LinearLayout> <LinearLayout
android:layout_gravity="right"
android:id="@+id/ll_right"
android:background="@mipmap/message_right"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:id="@+id/tv_right"
android:layout_margin="10dp"/> </LinearLayout>
</LinearLayout>

这里我们把接受消息和发送消息的布局都写进来了,代码中根据消息的类型来调用 visible 方法,显示对应的消息。

建立适配器

public class MsgAdapter extends RecyclerView.Adapter<MsgAdapter.MsgViewHolder> {
private List<Msg> list;
public MsgAdapter(List<Msg> list){
this.list = list;
} class MsgViewHolder extends RecyclerView.ViewHolder{
LinearLayout llLeft,llRight;
TextView tvLeft,tvRight; public MsgViewHolder(@NonNull View itemView) {
super(itemView);
llLeft =itemView.findViewById(R.id.ll_left);
llRight =itemView.findViewById(R.id.ll_right);
tvLeft =itemView.findViewById(R.id.tv_left);
tvRight =itemView.findViewById(R.id.tv_right);
}
} @NonNull
@Override
public MsgViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.msg_item,parent,false);
MsgViewHolder viewHolder = new MsgViewHolder(view); return viewHolder;
} @Override
public void onBindViewHolder(@NonNull MsgViewHolder holder, int position) {
Msg msg = list.get(position);
// 这里根据消息的类型来选择不同的布局
if (msg.getType() == Msg.TYPE_RECEIVE){
holder.llLeft.setVisibility(View.VISIBLE);
holder.llRight.setVisibility(View.GONE);
holder.tvLeft.setText(msg.getContent());
}else {
holder.llRight.setVisibility(View.VISIBLE);
holder.llLeft.setVisibility(View.GONE);
holder.tvRight.setText(msg.getContent());
} } @Override
public int getItemCount() {
return list.size();
}
}

然后写 Activity 代码

public class MsgActivity extends AppCompatActivity {

    List<Msg> list  =new ArrayList<>();
EditText text ;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_nine_patch);
initData();
final RecyclerView recyclerView = findViewById(R.id.rlv);
final MsgAdapter msgAdapter = new MsgAdapter(list);
text = findViewById(R.id.et_info);
Button bt = findViewById(R.id.bt_send);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(msgAdapter);
bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Random random = new Random();
// 这里还是利用随机数来生成消息的类型
int count = random.nextInt(20);
Msg msg = new Msg(text.getText()+"count:"+count,count%2);
list.add(msg);
// 表示在消息的末尾插入内容
msgAdapter.notifyItemInserted(list.size()-1);
// 让 RecyclerView 自动滚动到最底部
recyclerView.scrollToPosition(list.size()-1);
// 清空内容
text.setText("");
}
});
} public void initData(){
Random random = new Random();
for (int i=0;i<40;i++){
int count = random.nextInt(20);
Msg msg = new Msg("消息嗯哼"+i+"count:"+count,count%2);
list.add(msg);
} }
}

notifyItemInserted() 方法,用于通知列表有新的数据插入了,这样新增加的一条消息才能显示出来。

scrolltoPosition() 方法将数据定位到最后一行,保证我们可以看到最后发送的内容。

从0系统学Android--3.7 聊天界面编写的更多相关文章

  1. 从0系统学Android-2.5更多隐式Intent用法

    本系列文章,参考<第一行代码>,作为个人笔记 更多内容:更多精品文章分类 从0系统学Android-2.5更多隐式Intent用法 上一节中我们学习了通过隐式 Intent 来启动 Act ...

  2. 从0系统学Android--4.1探究碎片

    从0系统学Android--4.1探究碎片 本系列文章目录:更多精品文章分类 本系列持续更新中.... 初级阶段内容参考<第一行代码> 第四章:手机平板要兼顾--探究碎片 平板电脑和手机最 ...

  3. 从0系统学Android--3.6 RecyclerView

    从0系统学Android--更强大的滚动控件---RecyclerView 本系列文章目录:更多精品文章分类 本系列持续更新中.... 参考<第一行代码> 首先说明一点昨天发了一篇关于 L ...

  4. 从0系统学Android--3.5 最常用和最难用的控件---ListView

    从0系统学Android-- 3.5 最常用和最难用的控件---ListView 本系列文章目录:更多精品文章分类 本系列持续更新中.... 3.5 最常用和最难用的控件---ListView Lis ...

  5. 从0系统学Android--3.2四种基本布局

    从0系统学Android--3.2四种基本布局 本系列文章目录:更多精品文章分类 本系列持续更新中.... 3.3 系统控件不够用?创建自定义控件 上一节我们学习了 Android 中的一些常用的控件 ...

  6. 从0系统学Android--3.1编写UI界面

    从0系统学Android--3.1编写UI界面 本系列文章目录:更多精品文章分类 本系列持续更新中.... 界面设计和功能开发同样重要,界面美观的应用程序不仅可以大大增加用户粘性,还能帮我们吸引到更多 ...

  7. 从0系统学Android--2.6 Activity 的最佳实践

    从0系统学Android--2.6 Activity 的最佳实践 本系列文章目录:更多精品文章分类 本系列持续更新中.... 实践中的技巧 2.6.1 知晓当前是在哪个 Activity 这个其实很简 ...

  8. 从0系统学Android--5.2 发送广播

    从0系统学Android--52 发送广播 本系列文章目录:更多精品文章分类 本系列持续更新中.... 初级阶段内容参考<第一行代码> 5.3 发送自定义广播 前面已经学习了如何接受广播了 ...

  9. 从0系统学Android--1.3创建你的第一个 Android 项目

    1.3 创建你的第一个 Android 项目 环境搭建完成后,我们就可以写下我们的第一个项目了. 1.3.1 创建 HelloWorld 项目 在 Android Studio 的欢迎页面点击 Sta ...

随机推荐

  1. syslog日志

    Syslog协议 系统日志(Syslog)协议是在一个IP网络中转发系统日志信息的标准,它是在美国加州大学伯克利软件分布研究中心(BSD)的TCP/IP系统实施中开发的,目前已成为工业标准协议,可用它 ...

  2. RocketMQ 主题扩分片后遇到的坑

    目录 1.案情回顾 1.1 集群现状 1.2.RocketMQ 在线扩容队列 1.3 消息发送 2.问题暴露 3.问题分析 4.问题复盘 消息组接到某项目组反馈,topic 在扩容后出现部分队列无法被 ...

  3. IO 单个文件的多线程拷贝

    package FileCopyThread; //自建的包,根据个人调整 import java.io.File; import java.io.FileNotFoundException; imp ...

  4. [TimLinux] django 全局变量在WSGI多进程多线程环境中的研究

    场景1: 2个进程,每个进程1个线程,请求函数中设置了10秒sleep,9个请求同一URL: 结果: 1. 全局变量ID值,在每一个进程中相同,不同进程中不相同 2. 并行只能接受2个请求,同时发起多 ...

  5. C++与数据结构课程设计---定票咨询系统

    订票咨询管理系统 设计编制一个订票管理系统,考虑旅客不同的要求.例如,选择不同的交通工具,希望在旅途中的时间尽可能地短,期望旅费尽可能省,或要求中转次数最少等.为旅客提供两种或三种最优决策.车票基本信 ...

  6. Python3 网络编程和并发编程总结

    目录 网络编程 开发架构 OSI七层模型 socket subprocess 粘包问题 socketserver TCP UDP 并发编程 多道技术 并发和并行 进程 僵尸进程和孤儿进程 守护进程 互 ...

  7. Ubuntu上面安装sqlite3可视化数据库软件

    .介绍:sqlite 3是linux上的小巧的数据库,一个文件就是一个数据库. 2.安装:要安装sqlite 3,可以在终端提示符后运行下列命令: sudo apt-get install sqlit ...

  8. 牛客国庆集训派对Day1 L New Game!(堆优化dijkstra+建图)

    链接:https://ac.nowcoder.com/acm/contest/201/L来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 1048576K,其他语言2097 ...

  9. Sql中将datetime转换成字符串的方法(CONVERT())

    语法格式:CONVERT (<data_ type>[ length ], <expression> [, style]) style的含义:style 是将DATATIME ...

  10. 调用高德API,通过输入的地址,如省份、市、区获取经纬度 ,通过输入的经纬度,获取区域详情

    一.pom <?xml version="1.0" encoding="UTF-8"?><projectxmlns="http:// ...