自適應(yīng)軟鍵盤的Dialog以及監(jiān)聽軟鍵盤彈起

最近項目中遇到一個需求:新手引導(dǎo)。跟一般的新手引導(dǎo)沒有什么太大區(qū)別,思路都是搞一個帶陰影的遮罩層,然后在上邊兒給一些提示性的文字,由于需求中有些特殊的地方,所以我用了一個全屏的dialog(而且,dialog自帶陰影效果)來做新手引導(dǎo)這個需求。

彈出鍵盤
鍵盤上方具體位置顯示引導(dǎo)

這個需求中有兩個地方需要考慮:1. Dialog的布局要適應(yīng)軟鍵盤的彈起2. 軟鍵盤彈起和收下的時候都會有不同的引導(dǎo),所以要在Dialog上監(jiān)聽軟鍵盤的彈起。

需求的解決:
一:適應(yīng)鍵盤的彈起。
我們知道,在Activity中如果要讓布局不被軟鍵盤遮擋,方法一般是在清單文件中配置windowSoftInputMode屬性, windowSoftInputMode是Android1.5以后的一個新特性,主要是對軟鍵盤操作的,主要有以下屬性:

  1. stateUnspecified:軟鍵盤的狀態(tài)并沒有指定,系統(tǒng)將選擇一個合適的狀態(tài)或依賴于主題的設(shè)置
  2. stateUnchanged:當(dāng)這個activity出現(xiàn)時,軟鍵盤將一直保持在上一個activity里的狀態(tài),無論是隱藏還是顯示
  3. stateHidden:用戶選擇activity時,軟鍵盤總是被隱藏
  4. stateAlwaysHidden:當(dāng)該Activity主窗口獲取焦點時,軟鍵盤也總是被隱藏的
  5. stateVisible:軟鍵盤通常是可見的
  6. stateAlwaysVisible:用戶選擇activity時,軟鍵盤總是顯示的狀態(tài)
  7. adjustUnspecified:默認(rèn)設(shè)置,通常由系統(tǒng)自行決定是隱藏還是顯示
  8. adjustResize:該Activity總是調(diào)整屏幕的大小以便留出軟鍵盤的空間
  9. adjustPan:當(dāng)前窗口的內(nèi)容將自動移動以便當(dāng)前焦點從不被鍵盤覆蓋和用戶能總是看到輸入內(nèi)容的部分

我們可以根據(jù)需求在清單文件中配置具體的屬性,那么如果軟鍵盤是基于Dialog彈出來的話該怎么辦呢?畢竟我們沒有清單文件來配置Dialog的屬性。其實,在清單中配置的屬性本質(zhì)也是告訴當(dāng)前界面對軟鍵盤這種情況的處理。windowSoftInputMode的屬性如果在清單文件中配置的話是這樣寫的:
android:windowSoftInputMode="stateHidden|adjustPan"

其實在清單文件中的某些配置,我們在Activity也能配置,在Activity中用代碼設(shè)置話是這樣寫的:
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);

聰明的你看到這里可能已經(jīng)看出來什么了,沒錯,兩種方式的實質(zhì)就是得到當(dāng)前的窗口實例,來基于當(dāng)前窗口設(shè)置的。我們來進(jìn)入源碼看一下,首先看getWindow()方法:
public Window getWindow() { return mWindow; }

很簡單,得到當(dāng)前的Window實例,再進(jìn)入setSoftInputMode這個方法:

public void setSoftInputMode(int mode) { 
    final WindowManager.LayoutParams attrs = getAttributes(); 
    if (mode !=   WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) 
   {      
   attrs.softInputMode = mode; mHasSoftInputMode = true;
    } else {
   mHasSoftInputMode = false;
   }
  if (mCallback != null) {
      mCallback.onWindowAttributesChanged(attrs); 
   }
 }```
這個方法很短邏輯也很清晰,我們可以看到,倒數(shù)第三行代碼,當(dāng)窗口屬性發(fā)生變化的時候,mCallback會回調(diào)一個方法執(zhí)行某些操作,那么這個,mCallback是什么呢?在源碼中搜索一下你會找到以下代碼和注釋:

/** * Set the Callback interface for this window, used to intercept key

  • events and other dynamic operations in the window.
    • @param callback The desired Callback interface.
      */
      public void setCallback(Callback callback) {
      mCallback = callback;
      }```

由注釋我們可以看到mCallback是給當(dāng)前窗口設(shè)置的一個回調(diào)接口,當(dāng)窗口發(fā)生某些變化的時候可以通過這個回調(diào)接口執(zhí)行某些操作?;氐絤Callback.onWindowAttributesChanged(attrs)這句代碼,首先我們肯定知道,Activity肯定實現(xiàn)了這個接口,那么,還有其他的實現(xiàn)了這個接口嗎?找到定義這個接口的地方:
This is called whenever the current window attributes change. public void onWindowAttributesChanged(WindowManager.LayoutParams attrs);

由注釋我們也可以清楚的明白這個接口的用途:無論在什么時候都會被調(diào)用當(dāng)窗口屬性發(fā)生變化。在Android Studio中我們可以點擊這個接口定義左邊的向上箭頭查看接口的實現(xiàn)類,我們發(fā)現(xiàn),dialog也實現(xiàn)了這個接口,那么回到第一個需求,解決方法就簡單多了,只需要自定義一個Dialog,然后重寫onCreate方法,如下:

super.onCreate(savedInstanceState);   getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); 
}```
其實跟在Activity中設(shè)置是一樣的。

二,基于Dialog監(jiān)聽軟鍵盤的彈起和收下:
其實看完第一個需求,我們可能已經(jīng)猜想到,軟鍵盤也是基于當(dāng)前窗口的,它的彈起和收下肯定會引起當(dāng)前窗口布局的屬性發(fā)生變化,所以解決思路就有了:監(jiān)聽當(dāng)前布局的變化。我這里是比較布局坐標(biāo)中的下坐標(biāo)的,因為如果鍵盤彈起的話,布局的下坐標(biāo)肯定會變小。具體代碼如下:
``` @Override public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { 
        if (oldBottom != 0 && bottom != 0 && (oldBottom - bottom > 0))
        {//軟鍵盤彈起          doSomethinh.. 
        } else if (oldBottom != 0 && bottom != 0 && (bottom - oldBottom > 0)) 
        {//軟件盤關(guān)閉       doSomethinh.. } }```

onLayoutChange這個方法在窗口布局發(fā)生變化的時候會被回調(diào),有興趣的朋友可以去看下源碼,注釋很清楚。這個回調(diào)方法中參數(shù)給我們了改變后view的左上右下的坐標(biāo),以及改變前view的坐標(biāo)。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容