Android开发案例 - 自定义虚拟键盘

所有包含IM功能的App(如微信, 微博, QQ, 支付宝等)都提供了Emoji表情之类的虚拟键盘,  如下图:

 Android开发案例 - 自定义虚拟键盘_第1张图片 

本文只着重介绍如何实现输入法键盘和自定义虚拟键盘的流畅切换, 而不介绍如何实现虚拟键盘, 因为后者实现相对容易, 而前者若实现不好, 则会出现体验的问题, 比如输入区域的视图在切换时会跳动等问题.

知识要点:

  • AndroidManifest.xml: activity属性 android:windowSoftInputMode 
  • InputMethodManager
  • Window 管理机制
  • View 管理机制

基本思路:

  • 假设最外层视图为LinearLayout
  • 虚拟键盘以layout形式直接添加到页面layout-xml中, 进入上述图中页面时, 默认是隐藏该虚拟键盘布局的, 输入法键盘也是默认收起的
  • 虚拟键盘高度应该为输入法键盘的高度, 因此, 输入法弹出时需要保存其高度值, 另外, 如果弹出虚拟键盘前未弹出过输入法键盘, 那么这时是不知道其高度值的, 因此需要预设一个高度值
  • 在切换键盘时, 动态调整内容区域(如聊天内容列表)的高度, 当虚拟键盘弹出时, 设置内容区域的高度为固定高度值, 而当虚拟键盘隐藏时, 还原内容区域的高度, 这样就可以实现键盘间的流畅切换了

实现代码:

  • github - VirtualKeyboardController 

Android开发案例 - 自定义虚拟键盘_第2张图片

具体用法:

> 页面布局

<?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>
include_content.xml
<?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>
include_vkb.xml

> 页面代码

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 实现代码.

 

相关:

  • http://www.dss886.com/android/2015/10/18/10-41/

 

END.

 

 

你可能感兴趣的:(Android开发案例 - 自定义虚拟键盘)