所有包含IM功能的App(如微信, 微博, QQ, 支付寶等)都提供了Emoji表情之類的虛擬鍵盤, 如下圖:
本文只着重介紹如何實現輸入法鍵盤和自定義虛擬鍵盤的流暢切換, 而不介紹如何實現虛擬鍵盤, 因為后者實現相對容易, 而前者若實現不好, 則會出現體驗的問題, 比如輸入區域的視圖在切換時會跳動等問題.
知識要點:
- AndroidManifest.xml: activity屬性 android:windowSoftInputMode
- InputMethodManager
- Window 管理機制
- View 管理機制
基本思路:
- 假設最外層視圖為LinearLayout
- 虛擬鍵盤以layout形式直接添加到頁面layout-xml中, 進入上述圖中頁面時, 默認是隱藏該虛擬鍵盤布局的, 輸入法鍵盤也是默認收起的
- 虛擬鍵盤高度應該為輸入法鍵盤的高度, 因此, 輸入法彈出時需要保存其高度值, 另外, 如果彈出虛擬鍵盤前未彈出過輸入法鍵盤, 那么這時是不知道其高度值的, 因此需要預設一個高度值
- 在切換鍵盤時, 動態調整內容區域(如聊天內容列表)的高度, 當虛擬鍵盤彈出時, 設置內容區域的高度為固定高度值, 而當虛擬鍵盤隱藏時, 還原內容區域的高度, 這樣就可以實現鍵盤間的流暢切換了
實現代碼:
具體用法:
> 頁面布局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout android:id="@+id/root_view" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <include android:id="@+id/content" layout="@layout/include_content" /> <include android:id="@+id/vkb_layout" layout="@layout/include_vkb" /> </LinearLayout>

<?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"> <ListView android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1.0" /> <ImageView android:layout_width="match_parent" android:layout_height="wrap_content" android:src="@drawable/divider_vertical" /> <LinearLayout android:id="@android:id/inputArea" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@android:color/white" android:gravity="center_vertical" android:orientation="horizontal" android:paddingLeft="5dp" android:paddingRight="5dp"> <EditText android:id="@android:id/input" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1.0" android:inputType="textMultiLine" android:maxLines="4"> <requestFocus /> </EditText> <ImageView android:id="@+id/emoji" android:layout_width="wrap_content" android:layout_height="match_parent" android:contentDescription="@null" android:paddingBottom="5dp" android:paddingTop="5dp" android:src="@mipmap/ic_launcher" /> </LinearLayout> </LinearLayout>

<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#aaa"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="Hello, Emoji!" /> </FrameLayout>
> 頁面代碼
public class MainActivity extends AppCompatActivity implements View.OnTouchListener, View.OnClickListener { private static final String TAG = "MainActivity"; private ListView mListView; private EditText mEditText; private ImageView mEmojiImage; private View mVirtualKeyboardLayout; private VirtualKeyboardController mVirtualKeyboardController; private LayoutManager mLayoutManager; private SoftKeyboardCompat mSoftKeyboardCompat; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mListView = (ListView) findViewById(android.R.id.list); mListView.setOnTouchListener(this); initListAdapter(); mEditText = (EditText) findViewById(android.R.id.input); mEditText.setOnClickListener(this); mEmojiImage = (ImageView) findViewById(R.id.emoji); mEmojiImage.setOnClickListener(this); mVirtualKeyboardLayout = findViewById(R.id.vkb_layout); mVirtualKeyboardController = new VirtualKeyboardController(this); mSoftKeyboardCompat = new SoftKeyboardCompat(this); mLayoutManager = new LinearLayoutManager(this, mSoftKeyboardCompat); mLayoutManager.setAnchorView(findViewById(R.id.content)); mLayoutManager.setSoftInputFocusView(mEditText); mLayoutManager.setVirtualKeyboardView(mVirtualKeyboardLayout); mVirtualKeyboardController.setLayoutManager(mLayoutManager); } ... }
擴展用法:
如果頁面布局的最外層視圖不是LinearLayout, 擴展 VirtualKeyboardController.LayoutManager 接口即可, 可參考 LinearLayoutManager 實現代碼.
相關:
END.