•准备工作

  首先制作一张 .9 格式的聊天气泡,参见我的这篇博客

  需要注意的是,制作完成后,应该将原始文件删除,否则AS会分不清楚而报错。

  新建一个 Empty Activity,Java 和 XML 文件的命名分别为 MainActivity.java 和 activity_main.xml;

•编写精美的聊天界面

  首先编写主界面,修改 activity_main.xml 中的代码,如下所示:

<?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"
android:padding="10dp"
android:background="#d8e0e8"> <androidx.recyclerview.widget.RecyclerView
android:id="@+id/msg_recycler_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:orientation="horizontal"> <EditText
android:id="@+id/input_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="Type message here"
android:textAllCaps="false"
android:maxLines="2"
android:gravity="left"/> <Button
android:id="@+id/send"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Send"
android:textAllCaps="false"
android:textSize="20sp"/>
</LinearLayout> </LinearLayout>

  我们在主界面中放置了一个 RecyclerView 用于显示聊天的消息内容;

  又放置了一个 EditText 用于输入消息,还放置了一个 Button 用于发送消息;

  然后,定义消息的实体类,新建 Msg.java,代码如下:

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

  Msg 类中只有两个字段:

    • content 表示消息的内容
    • type 表示消息的类型;

  其中消息的类型有两个可选值:

    • TYPE_RECEIVED 表示这是一条收到的消息
    • TYPE_SEND 表示这是一条发出的消息

  接下来编写 RecyclerView 子项的布局,新建 msg_item.xml 文件,添加代码如下:

<?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:orientation="vertical"> <LinearLayout
android:id="@+id/left_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:orientation="vertical"
android:background="@drawable/message_left"> <TextView
android:id="@+id/left_msg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="10dp"
android:textColor="@color/black"/> </LinearLayout> <LinearLayout
android:id="@+id/right_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:orientation="vertical"
android:background="@drawable/message_left"> <TextView
android:id="@+id/right_msg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="10dp"
android:textColor="@color/black"/> </LinearLayout>
</LinearLayout>

  这里我们让收到的消息居左对齐,发出的消息居右对其;

  并且使用 message_left.9 作为聊天气泡;

  接下来需要创建 RecyclerView 的适配器类,新建 MsgAdapter.java,添加代码如下:

public class MsgAdapter extends RecyclerView.Adapter<MsgAdapter.ViewHolder>{

    private List<Msg> list;
public MsgAdapter(List<Msg> list){
this.list = list;
}
static class ViewHolder extends RecyclerView.ViewHolder{
LinearLayout leftLayout;
TextView left_msg; LinearLayout rightLayout;
TextView right_msg; public ViewHolder(View view){
super(view);
leftLayout = view.findViewById(R.id.left_layout);
left_msg = view.findViewById(R.id.left_msg); rightLayout = view.findViewById(R.id.right_layout);
right_msg = view.findViewById(R.id.right_msg);
}
} @NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.msg_item,parent,false);
return new ViewHolder(view);
} @Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
Msg msg = list.get(position);
if(msg.getType() == Msg.TYPE_RECEIVED){
//如果是收到的消息,则显示左边的消息布局,将右边的消息布局隐藏
holder.leftLayout.setVisibility(View.VISIBLE);
holder.left_msg.setText(msg.getContent()); //注意此处隐藏右面的消息布局用的是 View.GONE
holder.rightLayout.setVisibility(View.GONE);
}else if(msg.getType() == Msg.TYPE_SEND){
//如果是发出的消息,则显示右边的消息布局,将左边的消息布局隐藏
holder.rightLayout.setVisibility(View.VISIBLE);
holder.right_msg.setText(msg.getContent()); //同样使用View.GONE
holder.leftLayout.setVisibility(View.GONE);
}
} @Override
public int getItemCount() {
return list.size();
}
}

  最后修改 MainActivity.java 中的代码,来为 RecyclerView 初始化一些数据,并给发送按钮加入事件响应;

  代码如下:

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";
private List<Msg> msgList = new ArrayList<>();
private RecyclerView msgRecyclerView;
private EditText inputText;
private Button send;
private LinearLayoutManager layoutManager;
private MsgAdapter adapter; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); msgRecyclerView = findViewById(R.id.msg_recycler_view);
inputText = findViewById(R.id.input_text);
send = findViewById(R.id.send);
layoutManager = new LinearLayoutManager(this);
adapter = new MsgAdapter(msgList = getData()); msgRecyclerView.setLayoutManager(layoutManager);
msgRecyclerView.setAdapter(adapter); /* 我们还需要为button建立一个监听器,我们需要将编辑框的内容发送到 RecyclerView 上:
①获取内容,将需要发送的消息添加到 List 当中去。
②调用适配器的notifyItemInserted方法,通知有新的数据加入了,赶紧将这个数据加到 RecyclerView 上面去。
③调用RecyclerView的scrollToPosition方法,以保证一定可以看的到最后发出的一条消息。*/
send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String content = inputText.getText().toString();
if(!content.equals("")) {
msgList.add(new Msg(content,Msg.TYPE_SEND));
adapter.notifyItemInserted(msgList.size()-1);
msgRecyclerView.scrollToPosition(msgList.size()-1);
inputText.setText("");//清空输入框中的内容
}
// 自定义一问一答
if(msgList.size() == 2){
msgList.add(new Msg("What's your name?",Msg.TYPE_RECEIVED));
adapter.notifyItemInserted(msgList.size()-1);
msgRecyclerView.scrollToPosition(msgList.size()-1);
}
if(msgList.size() == 4){
msgList.add(new Msg("Nice to meet you,Bye!",Msg.TYPE_RECEIVED));
adapter.notifyItemInserted(msgList.size()-1);
msgRecyclerView.scrollToPosition(msgList.size()-1);
}
}
});
} private List<Msg> getData(){
List<Msg> list = new ArrayList<>();
list.add(new Msg("Hello",Msg.TYPE_RECEIVED));
return list;
}
}

•运行效果

  

Android Studio 之 编写精美的聊天界面的更多相关文章

  1. 0.[WP Developer体验Andriod开发]之从零安装配置Android Studio并编写第一个Android App

    0. 所需的安装文件 笔者做了几年WP,近来对Android有点兴趣,尝试一下Android开发,废话不多说,直接进入主题,先安装开发环境,笔者的系统环境为windows8.1&x64. 安装 ...

  2. 0.[Andriod]之从零安装配置Android Studio并编写第一个Android App

    0. 所需的安装文件 笔者做了几年WP,近来对Android有点兴趣,尝试一下Android开发,废话不多说,直接进入主题,先安装开发环境,笔者的系统环境为windows8.1&x64. 安装 ...

  3. Android Studio 使用笔记:在图形界面使用 Gradle 配置项目所需jar包

    在 Android Studio 中使用第三方 jar 包,可以直接下载后添加到项目中,也可以使用 Gradle 配置进行管理.图形界面下十分简单. 点击下图中间的图标,或者选中 Model ,按F4 ...

  4. 【Android】17.0 UI开发(八)——利用RecyclerView列表控件实现精美的聊天界面

    1.0 首先新建一个项目,名叫:UIBestPractice,目录如下: 2.0 这里需要先准备两张图片,放在app\src\main\res\drawable-xhdpi目录下. 这里图片名称已经制 ...

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

    从0系统学Android--3.7 聊天界面编写 本系列文章目录:更多精品文章分类 本系列持续更新中.... 3.7 编写界面的最佳实践 前面学习了那么多 UI 开发的知识,下面来进行实践,做一个美观 ...

  6. Android基础-系统架构分析,环境搭建,下载Android Studio,AndroidDevTools,Git使用教程,Github入门,界面设计介绍

    系统架构分析 Android体系结构 安卓结构有四大层,五个部分,Android分四层为: 应用层(Applications),应用框架层(Application Framework),系统运行层(L ...

  7. Android Studio 1.0.2项目实战——从一个APP的开发过程认识Android Studio

    Android Studio 1.0.1刚刚发布不久,谷歌紧接着发布了Android Studio 1.0.2版本,和1.0.0一样,是一个Bug修复版本.在上一篇Android Studio 1.0 ...

  8. Android 开发之Windows环境下Android Studio安装和使用教程(图文详细步骤)

    鉴于谷歌最新推出的Android Studio备受开发者的推崇,所以也跟着体验一下. 一.介绍Android Studio  Android Studio 是一个Android开发环境,基于Intel ...

  9. Windows环境下Android Studio安装和使用教程

    Windows环境下Android Studio安装和使用教程 来源: http://www.cnblogs.com/liuhongfeng/archive/2015/12/30/5084896.ht ...

随机推荐

  1. vue & arrow function error

    vue & arrow function error <template> <div class="home"> <img alt=" ...

  2. URL parser All In One

    URL parser All In One const url = new URL(`https://admin:1234567890@cdn.xgqfrms.xyz:8080/logo/icon.p ...

  3. JavaScript for, for...in, for...of, for-await...of difference All In One

    JavaScript for, for...in, for...of, for-await...of difference All In One for for...in for...of for-a ...

  4. JS Object Deep Copy & 深拷贝

    JS Object Deep Copy & 深拷贝 针对深度拷贝,需要使用其他方法 JSON.parse(JSON.stringify(obj));,因为 Object.assign() 拷贝 ...

  5. HTML5 & canvas fingerprinting

    HTML5 & canvas fingerprinting demo https://codepen.io/xgqfrms/full/BaoMWMp window.addEventListen ...

  6. window.URL.createObjectURL

    window.URL.createObjectURL https://html5.xgqfrms.xyz/Canvas/safety-canvas.html var video = document. ...

  7. js & disabled right click & disabled right menu

    js & disabled right click (() => { const log = console.log; log(`disabled copy`); document.bo ...

  8. 人物传记Daniel Bolsonaro:永远不要做一个思维单一的人

    从小经历了移民和不断辗转迁徙搬家的Daniel Bolsonaro(现就职于灵石团队,职位是核心技术架构师)知道,人生不可能只有一条路,也不要局限于只给自己设立一条路.既然父母能带自己离开巴西来到美国 ...

  9. Win10安装VSCode并配置Python环境 完整版超详细简单【原创】

    我们分为三个步骤进行: 一.下载VSCode 二.配置Python环境 三.测试Python 一.下载VSCode 1.打开国内镜像vscode下载地址,即可自动下载:https://vscode.c ...

  10. Linux进程管理工具Supervisor的安装配置

    目录 Linux进程管理工具Supervisor的安装配置 简介 安装Python包管理工具 安装Supervisor 配置 配置文件参数说明 配置进程管理 启动supervisor 控制进程 交互终 ...