Android開發案例 - 自定義虛擬鍵盤


所有包含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>
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 實現代碼.

 

相關:

 

END.

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM