布局:
最上面是recycleView, 中间有一个输入框和一个按钮,下面灰色一块称之为功能区,功能区和键盘区可以互相切换。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/rv_list"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
>
</android.support.v7.widget.RecyclerView>
<LinearLayout
android:id="@+id/ll_input"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/et_input"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"/>
<Button
android:id="@+id/btn_switch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="切换"/>
</LinearLayout>
<LinearLayout
android:id="@+id/ll_function"
android:layout_width="match_parent"
android:layout_height="237dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<TextView
android:id="@+id/tv_show"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#CCCCCC" />
</LinearLayout>
</LinearLayout>
package com.example.keyboardapplication;
import android.content.Context;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
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;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private static final String TAG = "MainActivity";
private EditText mEtInput;
private Button mBtnSwitch;
private LinearLayout mLlFunction;
private InputMethodManager imm;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mEtInput = findViewById(R.id.et_input);
mBtnSwitch = findViewById(R.id.btn_switch);
mLlFunction = findViewById(R.id.ll_function);
imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
//默认隐藏功能区
mLlFunction.setVisibility(View.GONE);
mBtnSwitch.setOnClickListener(this);
mEtInput.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_switch:
mEtInput.requestFocus(); //1----------
// imm.hideSoftInputFromWindow(mEtInput.getWindowToken(),0);
if(imm.hideSoftInputFromWindow(mEtInput.getWindowToken(), 0)) { //2-
// imm.showSoftInput(editText,0);
Log.d(TAG, "onClick: 1111");
//软键盘已弹出
if (mLlFunction.getVisibility() == View.GONE) {
//隐藏状态则显示
imm.hideSoftInputFromWindow(mEtInput.getWindowToken(),0);
mLlFunction.setVisibility(View.VISIBLE);
} else {
//去隐藏
mLlFunction.setVisibility(View.GONE);
}
} else {
//软键盘未弹出
Log.d(TAG, "onClick: 2222");
if (mLlFunction.getVisibility() == View.GONE) {
//隐藏状态则显示
mLlFunction.setVisibility(View.VISIBLE);
imm.hideSoftInputFromWindow(mEtInput.getWindowToken(),0);
} else {
//去隐藏
mLlFunction.setVisibility(View.GONE);
imm.showSoftInput(mEtInput, 0);
}
}
break;
case R.id.et_input:
Log.d(TAG, "onClick: 33333"); //3----
if (mLlFunction.getVisibility() == View.VISIBLE) {
mLlFunction.setVisibility(View.GONE);
}
break;
}
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: //4----
Log.d(TAG, "dispatchTouchEvent: 2222");
View view = getCurrentFocus();
if (view != null) {
if (view instanceof EditText) {
int[] location = { 0, 0 };
view.getLocationInWindow(location);
// int left = location[0], //5-----
int top = location[1];
// right = left + view.getWidth(),
// bottom = top + view.getHeight();
// 判断焦点位置坐标是否在空间内,如果位置在控件外,则隐藏键盘
if (event.getY() < top) {
// 隐藏键盘
imm.hideSoftInputFromWindow(mEtInput.getWindowToken(),0);
mLlFunction.setVisibility(View.GONE);
}
}
}
break;
default:
break;
}
return super.dispatchTouchEvent(event);
}
@Override
protected void onPause() {
super.onPause(); //6------
mLlFunction.setVisibility(View.GONE);
}
}
MainActivity主要分为三块
1.onCreate()
初始化,主要是初始化的InputMethodManager对象,这个对象用来管理软键盘的状态。
2.onClick()方法:
先不看requestFouse(),这个方法使得输入框获得焦点
看注释为(2)的地方,这个if可以判断当前的软键盘的状态,这样可以明确知道当前软键盘是显示还隐藏。
先判断当前软键盘的显示状态,然后再控制是显示功能区还是隐藏。
到此已经解决了大部分问题,还有几个细节需要优化。
(3)监听输入框是为了当输入框有焦点的时候,再点击输入框就会触发这个点击事件,这个点击会使得软键盘自动弹出,所以需要手动把功能区隐藏。
前面也说了,在输入框有焦点的情况下才会触发点击事件,那么有一种情况是:一开始进入这个界面的时候,输入框并没有焦点,而点击“切换”按钮时,显示功能区,如果再点击输入框,则此时输入框获得焦点,显示软键盘,但是又不会触发输入框的点击事件,因此会同时显示功能区和软键盘。所以在“切换”按钮的点击事件增加了输入框获得焦点的操作,同时把此时应该弹出的软键盘给隐藏。
(4)处的触摸事件是为了监听点击输入框上方的空白处使得软键盘和功能区隐藏
(6)处的onPause()是为了控制,当功能区显示的时候,切换应用到后台再显示到前台,由于输入框有焦点,就会自动显示软键盘,但是如果此时功能区处于显示状态,则两者会一同显示,这个方法就是为了规避这个问题。
当前还有的问题:
1.在切换功能区和软键盘的时候,输入框这一行还是会有闪烁的现象,
2.应该把功能区的高度设置为和软键盘一样的高度,这样过度会更加自然。