解決:(聊天佈局)點擊底部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事件的時候隱藏掉輸入法,這樣就可以了。
 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章