博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
recyclerview实战——对话界面
阅读量:5272 次
发布时间:2019-06-14

本文共 7500 字,大约阅读时间需要 25 分钟。

 

最近在做一个电影智能问答系统,需要有一个相应的界面来操作问答,而最近又在学android,使用决定采用recyclerview控件来写相关的内容。

android本身有一种相关的控件叫listview,但是相比recyclerview来说,Listview只能实现上下滑动而且扩展性不好。重要的是recyclerview可以实现复用,即已经移出屏幕的样式会在屏幕的下方进行复用。下面开始进行相关的操作。

一 前期准备

1 对话框素材

开始实现前需要有一个对话框,从icon网站上找到一个对话框png格式,背景透明作为所用的对话框。

 

将其导入drawable之后转换为 9 patch格式,可以确保放大的时候图像部分放大,从而确保不失真不变形。(改变图片左边和上边的黑色条来确定哪里被拉伸)

2 建立recyclerview依赖

因为recyclerview是新增空间,需要在项目的build.gradle中增加其依赖,注意此处的build.gradle的地址为app\build.gradle.在该文件下增加recyclerview依赖如下:

1 dependencies { 2     implementation fileTree(dir: 'libs', include: ['*.jar']) 3     implementation 'com.android.support:appcompat-v7:26.1.0' 4     implementation 'com.android.support.constraint:constraint-layout:1.1.2' 5     testImplementation 'junit:junit:4.12' 6     androidTestImplementation 'com.android.support.test:runner:1.0.2' 7     androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 8  9 //增加recyclerview依赖10     compile 'com.android.support:recyclerview-v7:26.1.0'11 }

新增后记得点击sync now来进行同步。

二 布局文件

1 主界面

首先写主界面,主界面其实有两大部分组成,第一部分是上面的recyclerview控件,存放发出和接收的消息。第二部分是位于底部的输入部分,其中包括editview控件(输入框)和button控件(发送按键)两个小部分。所以整体用线性布局将屏幕分为上下两部分,上部分高度设为0,权重为1,下部分高度设为适应高度。下部分再使用一个线性布局(默认为横向线性),将输入框设宽为0,权重为1;将按钮设为适应宽度,这样就可以很好的分屏了。

1 
2
7 8 //上半部分的滑动列表 9
14 15 //下部分的输入16
19 20
27 28
33 34
35 36

效果如下图:

这里布局的时候要善用weight(权重)这个属性。

比如说有一个linearlayout他的高度是100

 a控件weight=1   b控件weight=2,c控件weight=3,d控件height=40,那么

a控件的高度就是 ((100-40)/(1+2+3)) *1

b控件的高度就是 ((100-40)/(1+2+3)) *2

c控件的高度就是 ((100-40)/(1+2+3)) *3

如果a不设置height=0dp,那么当a控件高度大于((100-40)/(1+2+3)) *1时,weight属性不起作用,设置等于0,那么weight属性什么时候都起作用。

2 对话框布局

对话框布局用在recyclerview布局里,即使recyclerview子项的布局。

将左右对话框的布局集合在一个布局里,再通过setVisiblity中view.visible和gone来设置布局可见不可见。

整体布局任为线性布局,分为两部分,分别是左对话框布局和右对话框布局,设置一个边框内填充的距离padding。左右对话框分别也是线性布局,里面包含一个textview文本框。左对话框设置背景图为准备好的左对话框素材,属性layout_gravity为lift 使其靠左布局,大小设置为适应性大小。里面的文本框也是适应性大小,布局属性为居中,设置一个边外框边界margin使字不会填充太满,字体颜色为黑色。右对话框和左对话框对称。代码如下:

1 
6 7
13 14
21 22
23 24
30 31
39 40
41 42

示例图如下:

注意这里有一个坑,因为是直接从icon下载的素材,而且对话框的宽高为适应性大小,这个适应不但是适应里面的文字框大小,而且还适应背景图本身的大小,这就导致了如果输入文字很少,文本框就会远大于文字大小。解决方法:在ps里将素材进行重新的处理,将其缩小到60*60像素点左右大小,再通过9 patch转化图片,这样效果就很好了。

三 定义消息实体类 Message类

新建Message类,包括两个字段,content表示消息的内容,type表示消息的类型(TYPE_RECEIVED接收的消息 和TYPE_SEND发送的消息 )

1 public class Message { 2     //    设置收到消息类型为0 发送信息类型为1 3     public static final int TYPE_RECEIVED = 0; 4     public static final int TYPE_SEND = 1; 5  6     private String content; 7     private int type; 8  9     //构造函数赋值10     public Message(String content, int type) {11         this.content = content;12         this.type = type;13     }14 15     public String getContent() {16         return content;17     }18 19     public int getType() {20         return type;21     }22 }

四 Recyclerview适配器类

新建MsgAdapter类,代码如下:

1 public class MsgAdapter extends RecyclerView.Adapter
{ 2 3 //展示数据源存放 4 private List
mMsgList; 5 6 //内部类 将子项的所有布局进行传入匹配 7 static class ViewHolder extends RecyclerView.ViewHolder { 8 // 布局元素 9 LinearLayout leftLayout;10 LinearLayout rightLayout;11 TextView leftMsg;12 TextView rightMsg;13 14 // 内部类的构造函数传入recycler子项的布局15 public ViewHolder(View view) {16 super(view);17 leftLayout = (LinearLayout) view.findViewById(R.id.left_layout);18 rightLayout = (LinearLayout) view.findViewById(R.id.right_layout);19 leftMsg = (TextView) view.findViewById(R.id.left_msg);20 rightMsg = (TextView) view.findViewById(R.id.right_msg);21 }22 }23 24 // 传入要展示的数据源25 public MsgAdapter(List
msgList) {26 mMsgList = msgList;27 }28 29 // 用于创建内部类viewholder实例 传入msg_item布局,在构造函数加载出所有布局30 @Override31 public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {32 View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.msg_item, parent, false);33 return new ViewHolder(view);34 }35 36 // 对recyclerview子项数据进行赋值,在子项滚动到屏幕内时执行。通过position参数得到当前项具体内容37 @Override38 public void onBindViewHolder(ViewHolder holder, int position) {39 Message msg = mMsgList.get(position);40 if (msg.getType() == Message.TYPE_RECEIVED) {41 //收到消息,用左边的格式 右边格式隐藏42 holder.leftLayout.setVisibility(View.VISIBLE);43 holder.rightLayout.setVisibility(View.GONE);44 holder.leftMsg.setText(msg.getContent());45 } else if (msg.getType() == Message.TYPE_SEND) {46 //发送消息,用右边格式 左边格式隐藏47 holder.rightLayout.setVisibility(View.VISIBLE);48 holder.leftLayout.setVisibility(View.GONE);49 holder.rightMsg.setText(msg.getContent());50 }51 }52 53 // 返回recyclerview有多少子项54 @Override55 public int getItemCount() {56 return mMsgList.size();57 }58 59 }

这里的重点是重写三个方法 onCreateViewHolder(),onBindViewHolder()和getItemCount()。首先建立一个内部类将子项的所有布局进行传入匹配。

1 onCreateViewHolder()

  用于创建内部类viewholder实例,在这个方法中传入msg_item布局,创建一个viewHolder实例,并把加载出来的布局传入到构造函数中,将viewholder的实例返回。

2 onBindViewHolder()

  用于对recyclerview子项的数据进行赋值,在子项滚动到屏幕内时执行。通过position参数得到当前项的实例,在将其内容设置到实例中即可。

3 getItemCount()

  返回recyclerview有多少子项

五 主函数

主函数主要是分配布局文件,并创建布局管理器,为滑动框设置布局管理器,设置适配器。之后为发送按钮设置点击事件,再初始化一下消息列表。具体的内容在代码的注释中有详细介绍。

1 public class MainActivity extends AppCompatActivity { 2  3     private List
msgList = new ArrayList<>(); 4 private EditText inputText; 5 private Button send; 6 private RecyclerView msgRecyclerView; 7 private MsgAdapter adapter; 8 9 @Override10 protected void onCreate(Bundle savedInstanceState) {11 super.onCreate(savedInstanceState);12 setContentView(R.layout.activity_main);13 14 initMsgs();15 16 //分配布局文件17 inputText = (EditText) findViewById(R.id.input_text);18 send = (Button) findViewById(R.id.send);19 msgRecyclerView = (RecyclerView) findViewById(R.id.msg_recycler_view);20 21 //布局管理器22 LinearLayoutManager layoutManager = new LinearLayoutManager(this);23 //为滑动框设置布局管理器,设置适配器24 msgRecyclerView.setLayoutManager(layoutManager);25 adapter = new MsgAdapter(msgList);26 msgRecyclerView.setAdapter(adapter);27 //为发送按钮设置监听事件28 send.setOnClickListener(new View.OnClickListener() {29 @Override30 public void onClick(View view) {31 String content = inputText.getText().toString();32 //如果输入不为空33 if (!"".equals(content)) {34 Message msg = new Message(content, Message.TYPE_SEND);35 msgList.add(msg);36 //通知列表有新数据插入 这样数据才能在recyclerview中显示37 adapter.notifyItemInserted(msgList.size() - 1);38 //定位将显示的数据定位到最后一行,保证可以看到最后一条消息39 msgRecyclerView.scrollToPosition(msgList.size() - 1);40 inputText.setText("");41 }42 }43 });44 }45 46 //初始化消息列表47 private void initMsgs() {48 Message msg1 = new Message("Hallo,我是电影专家", Message.TYPE_RECEIVED);49 msgList.add(msg1);50 }51 }

 

完成效果图:

 

转载于:https://www.cnblogs.com/Mask-D/p/9261114.html

你可能感兴趣的文章
为什么for循环可以遍历list:Python中迭代器与生成器
查看>>
Python数据分析之pandas基本数据结构:Series、DataFrame
查看>>
从源码看Flask框架配置管理
查看>>
Python数据分析之Pandas读写外部数据文件
查看>>
Python数据分析之numpy数组全解析
查看>>
机器学习回顾篇(5):朴素贝叶斯算法
查看>>
TensorFlow2.0(1):基本数据结构——张量
查看>>
TensorFlow2.0(二):数学运算
查看>>
2019-2020-1 1823《程序设计与数据结构》问题汇总(正在更新)
查看>>
2019-2020-1 1823《程序设计与数据结构》预备作业总结
查看>>
2019-2020-1 1823《程序设计与数据结构》每周成绩
查看>>
2019-2020-1 1823《程序设计与数据结构》第一周作业总结
查看>>
2019-2020-1 1823《程序设计与数据结构》第二、三周作业总结
查看>>
git命令学习4
查看>>
MYSQL数据库学习
查看>>
MySQL常用命令
查看>>
mysql数据处理函数和分组函数
查看>>
centos MySQL服务启动及开机启动
查看>>
centos 安装anaconda
查看>>
CentOS5安装Git
查看>>