在開發App時
是否有發現手機螢幕小小
手機彈出的軟鍵盤卻大大的困擾呢?
總是導致軟鍵盤擋住輸入框

 

使用者os:「鬼才知道我輸入了什麼啊啊啊啊啊!!!!」

 

哈哈哈
請這位使用者消消氣
我們今天就是來解決這個問題的

 

這問題分入門款 & 進階款
首先來說說入門款的藥方

 

(入門款藥方)
其實只要在Activity 加入一些屬性就行了

<activity
    android:name=".app.MainActivity"
    android:windowSoftInputMode="adjustResize"/>

或是

<activity
    android:name=".app.MainActivity"
    android:windowSoftInputMode="adjustPan"/>

這兩個屬性都可以做到不擋畫面的效果
那麼差別在哪呢?
adjustResize 會重設畫面的高度
adjustPan     則是把整個畫面向上平移

 

但這個方法有個限制,就是不能有WebView
因為WebView是由網頁元件去call軟鍵盤出來的
在全屏模式的狀況下,兩個屬性都不能用
但如果不是全屏,adjustResize還是可以用的
如下表

 

 

(偏方)
我在實做的時候發現了一個小技巧
如果只是要讓 EditText 可以看到
不要被擋住的話,只要設一個屬性

<EditText
    android:id="@+id/groupBuy_contentEdit"
    android:minHeight="42dp" />

這個minHeight 就可以確保至少有 42dp 的高度
這樣輸入框就不會被擋住了
Android 彈出軟鍵盤後也還會有42dp的高度存在

 

 

(進階款藥方)
此藥方是一個在stackoverflow裡
其中一位大神寫的類
使用方也很簡啦
只要在Activity 的 onCreate 中加上一句
AndroidBug5497Workaround.assistActivity(this) 即可

 

這個神奇的類倒底做了什麼呢?
讓我們來看看吧
首先是剛剛我們呼叫的 AndroidBug5497Workaround.assistActivity(this)

public static void assistActivity (Activity activity) {
    new AndroidBug5497Workaround(activity);
}

這裡只是單純的一個接口
接著往 AndroidBug5497Workaround(activity) 看

private View mChildOfContent;
private int usableHeightPrevious;
private FrameLayout.LayoutParams frameLayoutParams;

private AndroidBug5497Workaround(Activity activity) {
    FrameLayout content = (FrameLayout) activity.
                findViewById(android.R.id.content);
    mChildOfContent = content.getChildAt(0);
    mChildOfContent.getViewTreeObserver()
                   .addOnGlobalLayoutListener(
    new ViewTreeObserver.OnGlobalLayoutListener() {
        public void onGlobalLayout() {
            possiblyResizeChildOfContent();
        }
    });
    frameLayoutParams = (FrameLayout.LayoutParams) 
                        mChildOfContent.getLayoutParams();
}

前面的3個屬性是這個類的全域變數
從這段可以看到
我們找到 Activity 的 root View
並用 getCJildAt(0)
找到我們 Activity setContenView(View view) & setContent(int layRes) 的 View

 

再來設定 OnGlobalLayoutListener 來監聽 View 的可視狀態變化
只要有變化,就執行 possiblyresizeChildOfContent()
在看 possiblyresizeChildOfContent() 之前
我們先看下面這段 method

private int computeUsableHeight() {
    Rect r = new Rect();
    mChildOfContent.getWindowVisibleDisplayFrame(r);
    return (r.bottom - r.top);
}

這是為了取得顯視中UI 高度所寫的method
其中的 r.bottom & r.top
看下圖應該會比較好理解

 

最後一步就是看possiblyResizeChildOfContent()在做什麼事了

private void possiblyResizeChildOfContent() {
    int usableHeightNow = computeUsableHeight();
    if (usableHeightNow != usableHeightPrevious) {
        int usableHeightSansKeyboard = mChildOfContent
                                       .getRootView()
                                       .getHeight();
        int heightDifference = 
            usableHeightSansKeyboard - usableHeightNow;
        if (heightDifference > (usableHeightSansKeyboard/4)) {
            // keyboard probably just became visible
            frameLayoutParams.height = 
            usableHeightSansKeyboard - heightDifference;
        } else {
          // keyboard probably just became hidden
          frameLayoutParams.height = usableHeightSansKeyboard;
        }
        mChildOfContent.requestLayout();
        usableHeightPrevious = usableHeightNow;
    }
}

這裡就是做了一些運算得知目前的可顯示 UI 高度
再進行重設
比較值得一提的是
usableHeightSansKeyboard/4
會有這個條件是因為
OnGlobalLayoutListener 監聽的事件太多了
這裡多一個條件就是當高度的改變大於1/4的時候
我們再進行重設的動作就好
避免不必要的重設

 

以上藥方就可以決定issue 5497的問題囉!!!







資料來源:
https://www.diycode.cc/topics/383
http://stackoverflow.com/questions/7417123/android-how-to-adjust-layout-in-full-screen-mode-when-softkeyboard-is-visible/19494006#19494006


arrow
arrow
    全站熱搜

    顏澤偉 發表在 痞客邦 留言(0) 人氣()