学习Android也将近4个年头了,一直想写点自己所学的内容来帮助后来人,为互联网奉献自己的一份力量,也算自己的积累。但是之前由于自己的惰性一直没有下笔,那就从今天这一篇开始吧!

我们做Android开发经常会有做即时聊天的需求,产品经理不管做啥APP,都要塞个IM,那就算是扯上社交了。我今天要讲的就是如何实现Android聊天界面。可能听到这个,在看文章的你就准备关闭网页了然后开喷了,但请别急,我写这篇文章自然有写这篇文章的道理。

1、首先我们创建项目,写好布局。布局比较简单,上面是个RecyclerView,用来显示聊天的对话。下面一个水平布局的LinearLayout,里面一个EditText作为文本编辑框,一个Button用来发送。这样布局就算写好了。

<?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.support.v7.widget.RecyclerViewandroid:id="@+id/recyclerView_chat"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"android:overScrollMode="never"android:scrollbars="vertical"/><LinearLayoutandroid:layout_width="match_parent"android:layout_height="55dp"android:orientation="horizontal"><EditTextandroid:id="@+id/editText_message"android:layout_width="0dp"android:layout_weight="1"android:layout_height="match_parent"android:hint="输入消息内容"android:padding="10dp" /><Buttonandroid:id="@+id/btn_send"android:layout_width="wrap_content"android:layout_height="match_parent"android:text="发送" /></LinearLayout>
</LinearLayout>

2、我们在MainActivity里面初始化一下布局,同样也非常的简单。

package com.liuxiaoyi.chatdemo;import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.widget.Button;
import android.widget.EditText;import java.util.ArrayList;public class MainActivity extends AppCompatActivity {private RecyclerView recyclerView_chat;private EditText editText_message;private Button btn_send;private ChatAdapter chatAdapter;private ArrayList<Chat> chatArrayList = new ArrayList<>();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);recyclerView_chat = (RecyclerView) findViewById(R.id.recyclerView_chat);editText_message = (EditText) findViewById(R.id.editText_message);btn_send = (Button) findViewById(R.id.btn_send);chatArrayList.add(new Chat("你好啊。",ChatAdapter.TYPE_SEND));chatArrayList.add(new Chat("你叫什么名字啊?",ChatAdapter.TYPE_SEND));chatArrayList.add(new Chat("你好,我叫小丽",ChatAdapter.TYPE_RECEIVE));chatArrayList.add(new Chat("你是哪里人啊?",ChatAdapter.TYPE_SEND));chatArrayList.add(new Chat("我是湖南长沙人",ChatAdapter.TYPE_RECEIVE));chatArrayList.add(new Chat("好巧啊,我也是长沙的",ChatAdapter.TYPE_SEND));chatArrayList.add(new Chat("咱们真有缘分诶",ChatAdapter.TYPE_SEND));chatArrayList.add(new Chat("我也觉得呢",ChatAdapter.TYPE_RECEIVE));chatAdapter = new ChatAdapter(MainActivity.this,chatArrayList);LinearLayoutManager linearLayoutManager = new LinearLayoutManager(MainActivity.this);recyclerView_chat.setLayoutManager(linearLayoutManager);recyclerView_chat.setAdapter(chatAdapter);}}

3、构造一下聊天实体

package com.liuxiaoyi.chatdemo;public class Chat {private String chatContent;private int type;public Chat(String chatContent, int type) {this.chatContent = chatContent;this.type = type;}public String getChatContent() {return chatContent;}public void setChatContent(String chatContent) {this.chatContent = chatContent;}public int getType() {return type;}public void setType(int type) {this.type = type;}
}

4、最后写好适配器

package com.liuxiaoyi.chatdemo;import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;import java.util.ArrayList;public class ChatAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{public static final int TYPE_SEND = 0;public static final int TYPE_RECEIVE = 1;private Context context;private ArrayList<Chat> chatArrayList = new ArrayList<>();public ChatAdapter(Context context,ArrayList<Chat> chatArrayList){this.context = context;this.chatArrayList = chatArrayList;}@Overridepublic int getItemViewType(int position) {if(chatArrayList.get(position).getType() == TYPE_SEND){return TYPE_SEND;}else if(chatArrayList.get(position).getType() == TYPE_RECEIVE){return TYPE_RECEIVE;}else {return super.getItemViewType(position);}}@Overridepublic RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {View view;if(viewType==TYPE_SEND){view = LayoutInflater.from(context).inflate(R.layout.item_send,parent,false);return new SendViewHolder(view);}else {view = LayoutInflater.from(context).inflate(R.layout.item_receive,parent,false);return new ReceiveViewHolder(view);}}@Overridepublic void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {if(holder instanceof SendViewHolder){SendViewHolder viewHolder = (SendViewHolder) holder;viewHolder.textView_send.setText(chatArrayList.get(position).getChatContent());}else if(holder instanceof ReceiveViewHolder){ReceiveViewHolder viewHolder = (ReceiveViewHolder) holder;viewHolder.textView_receive.setText(chatArrayList.get(position).getChatContent());}}@Overridepublic int getItemCount() {return chatArrayList.size();}private class SendViewHolder extends RecyclerView.ViewHolder{private TextView textView_send;public SendViewHolder(View itemView) {super(itemView);textView_send = (TextView) itemView.findViewById(R.id.textView_send);}}private class ReceiveViewHolder extends RecyclerView.ViewHolder{private TextView textView_receive;public ReceiveViewHolder(View itemView) {super(itemView);textView_receive = (TextView) itemView.findViewById(R.id.textView_receive);}}
}

这样也就算完工了。我们看一下效果。

感觉好像不错,是这么个意思。这时候我们心里就在暗自庆幸,聊天界面也不过如此嘛,做出微信这样的APP也太简单了,老子天下代码水平天下第一。

但是稍微点击一下,我们就会发现问题。我们看图

当我们点击EditText的时候,键盘弹了出来。但是他好像和微信QQ又那么一点点不一样,微信QQ的聊天框弹出之后,键盘是不会遮住聊天内容的。

这怎么能难倒我们呢?网上搜一下解决方案不就可以了么?于是我们开始上网搜。

网上给出的方法总得来说有两种。

第一种:首先在清单文件中的Activity节点增加android:windowSoftInputMode="adjustResize"这么一句话,然后

LinearLayoutManager manager = new LinearLayoutManager(context);
manager.setStackFromEnd(true);
recyclerView.setLayoutManager(manager);

好的,马上修改清单文件为

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.liuxiaoyi.chatdemo" ><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/AppTheme" ><activity android:name=".MainActivity"android:windowSoftInputMode="stateHidden|adjustResize"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity></application></manifest>

MainActivity修改为

package com.liuxiaoyi.chatdemo;import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.widget.Button;
import android.widget.EditText;import java.util.ArrayList;public class MainActivity extends AppCompatActivity {private RecyclerView recyclerView_chat;private EditText editText_message;private Button btn_send;private ChatAdapter chatAdapter;private ArrayList<Chat> chatArrayList = new ArrayList<>();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);recyclerView_chat = (RecyclerView) findViewById(R.id.recyclerView_chat);editText_message = (EditText) findViewById(R.id.editText_message);btn_send = (Button) findViewById(R.id.btn_send);chatArrayList.add(new Chat("你好啊。",ChatAdapter.TYPE_SEND));chatArrayList.add(new Chat("你叫什么名字啊?",ChatAdapter.TYPE_SEND));chatArrayList.add(new Chat("你好,我叫小丽",ChatAdapter.TYPE_RECEIVE));chatArrayList.add(new Chat("你是哪里人啊?",ChatAdapter.TYPE_SEND));chatArrayList.add(new Chat("我是湖南长沙人",ChatAdapter.TYPE_RECEIVE));chatArrayList.add(new Chat("好巧啊,我也是长沙的",ChatAdapter.TYPE_SEND));chatArrayList.add(new Chat("咱们真有缘分诶",ChatAdapter.TYPE_SEND));chatArrayList.add(new Chat("我也觉得呢",ChatAdapter.TYPE_RECEIVE));chatAdapter = new ChatAdapter(MainActivity.this,chatArrayList);LinearLayoutManager linearLayoutManager = new LinearLayoutManager(MainActivity.this);linearLayoutManager.setStackFromEnd(true);recyclerView_chat.setLayoutManager(linearLayoutManager);recyclerView_chat.setLayoutManager(linearLayoutManager);recyclerView_chat.setAdapter(chatAdapter);}
}

运行起来。大神诚不欺我啊,果然可以滚动了。聊天界面也不过如此嘛,做出微信这样的APP也太简单了,老子天下代码水平天下第一。

又稍微点击一下,又发现了问题

开始的界面是这样子的

点击聊天框后变成了这样

发现问题没有?微信QQ点击之后是滚动到底部,而不是只滚动到这一页的底部的哪一个item啊,这不是坑人嘛。唉,大神居然也会欺骗我,世态炎凉啊。

第一种方法不行 我们看第二种方法:

1、设置RecyclerView.scrollToPosition(list.size() - 1);

2、设置mLayoutManager.setStackFromEnd(true);

3、RecyclerView用ScrollView包裹起来,然后获取屏幕的高度和键盘的高度,计算出ScrollView需要滑动到的位置。

大神你不是骗我吧,前面我还能理解,用ScrollView包裹RecyclerView????(此处黑人脸问号),这干嘛还用RecyclerView,直接ScrollView里面add子view不就好了么。

这种方案我就不试了,如果在看文章的你有兴趣,可以尝试一下。

好了,文章写到这里就结束了,拜拜。

当然没有啦,我还没有提出解决方案。接下来看我的。(此处柯南背景音乐),新几子哇,一次莫黑一多次。

首先我们仔细看一下微信和QQ的实现方案,它的方案是不管我当前在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="match_parent"android:orientation="vertical"><android.support.v7.widget.RecyclerViewandroid:id="@+id/recyclerView_chat"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"android:overScrollMode="never"android:scrollbars="vertical"/><LinearLayoutandroid:layout_width="match_parent"android:layout_height="55dp"android:orientation="horizontal"><FrameLayoutandroid:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"><EditTextandroid:id="@+id/editText_message"android:layout_width="match_parent"android:layout_height="match_parent"android:hint="输入消息内容"android:padding="10dp" /><LinearLayoutandroid:id="@+id/layout_edit"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"/></FrameLayout><Buttonandroid:id="@+id/btn_send"android:layout_width="wrap_content"android:layout_height="match_parent"android:text="发送" /></LinearLayout>
</LinearLayout>

仔细看,我在EditText上增加了一个布局,用他来控制EditText的点击事件(当点击的时候,手动请求焦点)。

看MainActivity里面的操作

package com.liuxiaoyi.chatdemo;import android.app.Activity;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Toast;import java.util.ArrayList;public class MainActivity extends AppCompatActivity {private RecyclerView recyclerView_chat;private EditText editText_message;private Button btn_send;private LinearLayout layout_edit;private ChatAdapter chatAdapter;private ArrayList<Chat> chatArrayList = new ArrayList<>();Handler handler = new Handler(){@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);switch (msg.what){case 0:recyclerView_chat.scrollToPosition(chatArrayList.size()-1);break;}}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);recyclerView_chat = (RecyclerView) findViewById(R.id.recyclerView_chat);editText_message = (EditText) findViewById(R.id.editText_message);btn_send = (Button) findViewById(R.id.btn_send);layout_edit = (LinearLayout) findViewById(R.id.layout_edit);chatArrayList.add(new Chat("你好啊。",ChatAdapter.TYPE_SEND));chatArrayList.add(new Chat("你叫什么名字啊?",ChatAdapter.TYPE_SEND));chatArrayList.add(new Chat("你好,我叫小丽",ChatAdapter.TYPE_RECEIVE));chatArrayList.add(new Chat("你是哪里人啊?",ChatAdapter.TYPE_SEND));chatArrayList.add(new Chat("我是湖南长沙人",ChatAdapter.TYPE_RECEIVE));chatArrayList.add(new Chat("好巧啊,我也是长沙的",ChatAdapter.TYPE_SEND));chatArrayList.add(new Chat("咱们真有缘分诶",ChatAdapter.TYPE_SEND));chatArrayList.add(new Chat("我也觉得呢",ChatAdapter.TYPE_RECEIVE));chatAdapter = new ChatAdapter(MainActivity.this,chatArrayList);LinearLayoutManager linearLayoutManager = new LinearLayoutManager(MainActivity.this);recyclerView_chat.setLayoutManager(linearLayoutManager);recyclerView_chat.setAdapter(chatAdapter);layout_edit.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {editText_message.requestFocus();showSoftInput(MainActivity.this, editText_message);handler.sendEmptyMessageDelayed(0,250);}});recyclerView_chat.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View view, MotionEvent motionEvent) {hideSoftInput(MainActivity.this, editText_message);return false;}});}public static void showSoftInput(Context context, View view) {InputMethodManager imm = (InputMethodManager) context.getSystemService(Activity.INPUT_METHOD_SERVICE);imm.showSoftInput(view, InputMethodManager.SHOW_FORCED);}public static void hideSoftInput(Context context, View view) {InputMethodManager imm = (InputMethodManager) context.getSystemService(Activity.INPUT_METHOD_SERVICE);imm.hideSoftInputFromWindow(view.getWindowToken(), 0);}
}

我在这里获得布局文件中新增加的那个View,然后让他来给EditText请求焦点,同时用Handler的 sendEmptyMessageDelayed( 0 , 250 )方法让recyclerView等一会儿再滑动(此时弹出框已被弹出)。当RecyclerView有Touch事件的时候隐藏掉输入法,这样就可以了。

这里行文就真正结束了,有问题可以在底下留言。谢谢大家。

解决RecyclerView实现聊天界面,但点击下面的EditText后弹出的输入法会遮盖RecyclerView内容的方法相关推荐

  1. 解决在小程序/H5上点击输入框键盘弹起后弹框显示不全问题@令狐张豪

    要实现的效果图: 解决思路: 先禁止input键盘弹起时,是否自动上推页面: 点击input的时候获取键盘弹起来的高度: 把获取出来的高度赋值到弹框的margin-bottom上: 键盘失焦或弹框关闭 ...

  2. #解决仿微信聊天界面键盘遮盖聊天的界面

    解决仿微信聊天界面键盘遮盖聊天的界面 注意聊天界面的activity一定不能处于全屏模式 //第一步设置属性 <!--模拟的布局文件--><?xml version="1. ...

  3. 手机调用系统的拍照和裁剪功能,假设界面有输入框EditText,在一些手机会出现点击EditText会弹出输入法,却不能输入的情况。...

    1. 拍照裁剪后 点击EditText会弹出输入法,却不能输入.可是点击点一EdtiText就能够输入了,所以我就写了一个看不见的EdtiText,切换焦点,这样就攻克了这个奇怪的这问题,应该是and ...

  4. 解决点击EditText不弹出键盘,但现实光标闪烁的问题

    好长时间没写博客了,其实博客这个东西有点过时了,说实话,但是先写一段时间把!下一篇写一下这段时间的新的和感悟, 解决点击EditText不弹出软键盘,但实现光标闪烁的问题. 写之前先吐槽一下CSDN和 ...

  5. 案例:文件下载需求:1. 页面显示超链接 2. 点击超链接后弹出下载提示框 3. 完成图片文件下载||中文文件问题

    文件下载需求:     1. 页面显示超链接     2. 点击超链接后弹出下载提示框     3. 完成图片文件下载 * 分析:     1. 超链接指向的资源如果能够被浏览器解析,则在浏览器中展示 ...

  6. 异步任务下载apk文件并弹出对话框提示当前进度,文件下载结束后弹出安装界面

    主要任务 1.下载apk保存到sd卡指定目录 2.下载时显示下载的进度 3.下载完成后弹出对话框提示安装 分析过程: 联网操作不能在UI线程(主线程)进行 需要开启线程下载,为了效率我们这里采用异步线 ...

  7. Bootstrap—解决下拉菜单不弹出问题

    最近学到Bootstrap下拉菜单,学懂了教程内容之后自己敲一个点击按钮底下弹出下拉菜单的小demo,写完代码发现运行之后点击按钮没反应,下拉菜单弹不出来,对照教程感觉代码没错. 我的代码如下: &l ...

  8. win10系统开机总是弹出BitLocker输入恢复密钥如何解决

    最近有win10系统用户到本站咨询这样一个问题,就是每次开机的时候,总是会弹出BitLocker输入恢复密钥窗口,这是怎么回事呢,针对这个问题,小编这就给大家讲解一下win10系统开机总是弹出BitL ...

  9. android App一段时间没有操作或没有点击屏幕后弹出广告,或者一段时间没有点击屏幕进行特定操作。

    android App没有操作一段时间后弹出屏保广告页面 最近做了个项目,里面有个功能是app在任何activity中没有操作一段时间后要跳转到屏保广告页面,点击广告页面是返回上一个activity中 ...

最新文章

  1. 查看LINUX发行版的名称及其版本号
  2. mysql 备份压缩数据库_备份压缩mysql 数据库
  3. (完全解决)ValueError: Invalid RGBA argument: 0.2
  4. ORA-01031:insufficient privileges问题解决
  5. 你认为手机会取代个人电脑吗?
  6. 促使整个团队改善的首要驱动力一定来自技术领域
  7. Redmi K40游戏增强版首发雷电异形闪光灯:电竞气息十足!
  8. 【clickhouse】Too many parts . Merges are processing significantly slower than inserts
  9. 【Spring】Spring Eureka Client 注册报 registration status: 204
  10. java同步调用rabbitmq,使用RabbitMQ可以放慢同步发布/消耗速度
  11. android studio for android learning (二十二 )如何在camera2中加载其它控件和当前摄像头视图显示在一起以及UI优化
  12. Skyline软件二次开发初级——7如何在WEB页面中的三维地图上设置颜色
  13. PowerShell、CMD 和 Windows Terminal 的美化配置方法
  14. 服务器里面mbr稳定转gpt,Win7系统MBR转GPT分区方法(无损数据MBR转UEFI+GPT)
  15. 如何在央行查询企业征信报告?
  16. Java 首字母大写高效方法
  17. 生物岛实验室(省属)招聘电子工程师
  18. 下载微信支付sdk的两个方法
  19. 虚拟串口VSPD安装指南
  20. 阻容感基础02:电阻器原理(2)-电阻器参数

热门文章

  1. 逆行时间的 精神。。。病
  2. 快乐学算法or二分查找深度刨析
  3. 【cocos shader 005】 Grid3D 网格 吸入 扩散 效果 实例讲解
  4. WIN7+Ubuntu双系统 Grub修复
  5. 编程规范学习资料清单
  6. 第一届赣网杯网络安全大赛 2020GW-CTF Web_Writeup
  7. java中drawstring_java – Graphics.drawString()绘制我的旧字符串
  8. 距离2008北京奥运会开幕倒计时网页特效[js]
  9. 什么是ActionBar,详细讲解
  10. 全能科研利器---新一代GPU超级计算平台配置方案