解决:(聊天布局)点击底部EditText 弹出软键盘遮挡住上方RecyclerView的内容,实现软键盘将RecyclerView上移效果

最终效果: 

我的页面整体是一个LinearLayout 里面由二个部分组成上面是一个协调布局,底部是一个线性布局

问题1:点击EditText键盘不会把底部EditText顶上去,怎么解决

方法有很多,我这里给一个方法

  • 根部局设置    android:fitsSystemWindows="true" 的属性即可

问题2:点击进入聊天界面总是显示在最底部

当首次进入或者数据集发送改变时,让它总是滑动到最底部即可

mRecyclerView.scrollToPosition(数据集长度 - 1);

问题3:点击EditText弹出软键盘会把RecyclerView的内容遮住,并不会向上移动

曾经采取过的方法

方式1: 

  • 第一种:首先在清单文件中的Activity节点增加
android:windowSoftInputMode="adjustResize"
  • 然后
LinearLayoutManager manager = new LinearLayoutManager(context);
manager.setStackFromEnd(true);//设置从底部开始,最新添加的item每次都会显示在最下面 
recyclerView.setLayoutManager(manager);

效果:当聊天数据少于一页时,看起来很奇怪!不符合QQ和微信这样的方法!

方式2: 

  • 在清单文件中的Activity节点增加
android:windowSoftInputMode="adjustPan"

效果:RecyclerView是整体上移了,但是顶部的Toolbar也被顶出屏幕了。

方式3: 最终办法

参考了:解决RecyclerView实现聊天界面,但点击下面的EditText后弹出的输入法会遮盖RecyclerView内容的方法

微信和QQ的实现方案:

不管我当前在RecyclerView 的哪个位置,只要点击输入框,就会跳回最后一条消息的位置。

我们只需要在我们点击输入框的时候滚到最后一个位置就可以了。思路就是这样,非常的简单。

那是不是,给EditText设置监听,然后再给recycleview设置 滑动到底部就可以了呢?

当然不行!

问题:当给EditText设置点击监听的时候,发现只弹出了键盘,设置recyclerView的指定滑动并不起作用

mRecyclerView.scrollToPosition(数据集长度 - 1);

原因是什么呢?

我想到的是事件分发机制!!!(个人理解

第一次点击EditText,View获取焦点后弹出了键盘,并不会再将焦点分发下去(也就是不会走监听的方法了)

第二次点击EditText,就会奇怪的发现为什么?它RecyclerView又可以滑动到底部了呢?(焦点没被消费,走了监听的方法)

解决的办法:

EditText(View)布局中添加一个GroupView的布局(LinearLayout、RelativeLayout等)

事件分发机制:焦点先会走GroupView才会走View,当GroupView表示消费这个焦点,那么View就不会有焦点了

我们就可以在GroupView中处理点击EditText需要触发的操作

  1. 弹出软键盘
  2. 实现RecyclerView滑动到底部

随之而来的一些问题:

点击EditText之后不会弹出软件盘了(手动控制键盘弹出和隐藏逻辑)

  • 点击EditText show键盘
  • 滑动RecyclerView 和返回界面时 隐藏hide键盘

逻辑清楚了就好办了。

以下代码copy自:解决RecyclerView实现聊天界面,但点击下面的EditText后弹出的输入法会遮盖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.RecyclerView
        android:id="@+id/recyclerView_chat"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:overScrollMode="never"
        android:scrollbars="vertical"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="55dp"
        android:orientation="horizontal">
        <FrameLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1">
            <EditText
                android:id="@+id/editText_message"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:hint="输入消息内容"
                android:padding="10dp" />
            <LinearLayout
                android:id="@+id/layout_edit"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical"/>
        </FrameLayout>
 
        <Button
            android:id="@+id/btn_send"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:text="发送" />
    </LinearLayout>
</LinearLayout>
 

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

看MainActivity里面的操作

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(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                case 0:
                    recyclerView_chat.scrollToPosition(chatArrayList.size()-1);
                    break;
            }
        }
 
    };
    @Override
    protected 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);
 
         // GroupView的监听
        layout_edit.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //让View 也就是EditText获得焦点
                editText_message.requestFocus();
                showSoftInput(MainActivity.this, editText_message);
                //通过handler保证在主线程中进行滑动操作
                handler.sendEmptyMessageDelayed(0,250);
            }
        });
 
       //触摸recyclerView的监听
        recyclerView_chat.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public 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事件的时候隐藏掉输入法,这样就可以了。
 

 

 

 

 

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
完整版:https://download.csdn.net/download/qq_27595745/89522468 【课程大纲】 1-1 什么是java 1-2 认识java语言 1-3 java平台的体系结构 1-4 java SE环境安装和配置 2-1 java程序简介 2-2 计算机中的程序 2-3 java程序 2-4 java类库组织结构和文档 2-5 java虚拟机简介 2-6 java的垃圾回收器 2-7 java上机练习 3-1 java语言基础入门 3-2 数据的分类 3-3 标识符、关键字和常量 3-4 运算符 3-5 表达式 3-6 顺序结构和选择结构 3-7 循环语句 3-8 跳转语句 3-9 MyEclipse工具介绍 3-10 java基础知识章节练习 4-1 一维数组 4-2 数组应用 4-3 多维数组 4-4 排序算法 4-5 增强for循环 4-6 数组和排序算法章节练习 5-0 抽象和封装 5-1 面向过程的设计思想 5-2 面向对象的设计思想 5-3 抽象 5-4 封装 5-5 属性 5-6 方法的定义 5-7 this关键字 5-8 javaBean 5-9 包 package 5-10 抽象和封装章节练习 6-0 继承和多态 6-1 继承 6-2 object类 6-3 多态 6-4 访问修饰符 6-5 static修饰符 6-6 final修饰符 6-7 abstract修饰符 6-8 接口 6-9 继承和多态 章节练习 7-1 面向对象的分析与设计简介 7-2 对象模型建立 7-3 类之间的关系 7-4 软件的可维护与复用设计原则 7-5 面向对象的设计与分析 章节练习 8-1 内部类与包装器 8-2 对象包装器 8-3 装箱和拆箱 8-4 练习题 9-1 常用类介绍 9-2 StringBuffer和String Builder类 9-3 Rintime类的使用 9-4 日期类简介 9-5 java程序国际化的实现 9-6 Random类和Math类 9-7 枚举 9-8 练习题 10-1 java异常处理 10-2 认识异常 10-3 使用try和catch捕获异常 10-4 使用throw和throws引发异常 10-5 finally关键字 10-6 getMessage和printStackTrace方法 10-7 异常分类 10-8 自定义异常类 10-9 练习题 11-1 Java集合框架和泛型机制 11-2 Collection接口 11-3 Set接口实现类 11-4 List接口实现类 11-5 Map接口 11-6 Collections类 11-7 泛型概述 11-8 练习题 12-1 多线程 12-2 线程的生命周期 12-3 线程的调度和优先级 12-4 线程的同步 12-5 集合类的同步问题 12-6 用Timer类调度任务 12-7 练习题 13-1 Java IO 13-2 Java IO原理 13-3 流类的结构 13-4 文件流 13-5 缓冲流 13-6 转换流 13-7 数据流 13-8 打印流 13-9 对象流 13-10 随机存取文件流 13-11 zip文件流 13-12 练习题 14-1 图形用户界面设计 14-2 事件处理机制 14-3 AWT常用组件 14-4 swing简介 14-5 可视化开发swing组件 14-6 声音的播放和处理 14-7 2D图形的绘制 14-8 练习题 15-1 反射 15-2 使用Java反射机制 15-3 反射与动态代理 15-4 练习题 16-1 Java标注 16-2 JDK内置的基本标注类型 16-3 自定义标注类型 16-4 对标注进行标注 16-5 利用反射获取标注信息 16-6 练习题 17-1 顶目实战1-单机版五子棋游戏 17-2 总体设计 17-3 代码实现 17-4 程序的运行与发布 17-5 手动生成可执行JAR文件 17-6 练习题 18-1 Java数据库编程 18-2 JDBC类和接口 18-3 JDBC操作SQL 18-4 JDBC基本示例 18-5 JDBC应用示例 18-6 练习题 19-1 。。。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值