android 隐藏键盘时ui延迟恢复,android 软键盘的显示与隐藏问题的研究
在android中,常常會和輸入法的軟件鍵盤交互。在Manifest文件中,系統(tǒng)給activity的一個屬性-windowSoftInputMode來控制輸入法的顯示方式。
該屬性提供了Activity的window與軟鍵盤的window交互的方式。這里的屬性設(shè)置有雙方面的影響:
1.軟鍵盤的顯示與隱藏。-當(dāng)Activity界面成為用戶的焦點時,或隱藏或顯示。
2。
對Activty的主window窗體進(jìn)行調(diào)整。或者將Activity的window窗體調(diào)小以便為軟鍵盤騰出空間,或者當(dāng)Activity的部分window被軟件蓋住時,移動Activity的內(nèi)容以便用戶可以看到當(dāng)前的焦點。
你至少要從下列屬性值選取一項對其設(shè)置,要么是”state...“,要么是”adjust...“。
你能夠設(shè)置多個值。設(shè)置不同的屬性值。要用|進(jìn)行分開。
比方:
以下是對屬性的值的描寫敘述。
值
描寫敘述
”stateUnSpecified“
不指定軟件的狀態(tài)(顯示或隱藏)。系統(tǒng)會依據(jù)主題中的設(shè)置來選擇對應(yīng)的狀態(tài)。 該屬性軟鍵盤的默認(rèn)設(shè)置。
”stateUnchnaged“
總是保持上次軟鍵盤的狀態(tài)。當(dāng)Activity進(jìn)入到最前端時,不論是它上次它是顯示或隱藏。保持不變。
”stateHidden“
當(dāng)用戶進(jìn)入目標(biāo)Activity時。軟鍵盤保持隱藏狀態(tài)。這里的Activity是用戶是向前進(jìn)入Activity,而不是因為退出其他Activity退回到目標(biāo)Activity。
”stateVisible“
僅僅有條件合適(當(dāng)用戶前進(jìn)進(jìn)入到Activity的主window),就會顯示鍵盤
”stateAlawaysVisible“
當(dāng)用戶選擇進(jìn)入目標(biāo)Activity時。軟鍵盤被設(shè)置為可見的。這里的Activity是用戶向前進(jìn)入的Activity,而不是因為退出其他Activity而回到目標(biāo)Activity
"adjustUnspecified"
不指定是否去調(diào)整Activity的界面。或者調(diào)整Activity窗體的大小以便為軟鍵盤騰出空間或者移動窗體的內(nèi)容來屏幕上當(dāng)前的焦點可見。系統(tǒng)會自己主動選擇當(dāng)中一種模式,這依賴于窗體是包括能夠滑動其內(nèi)容的view.如有這種視圖,窗體的大小就會被調(diào)整。在這種假定的情況下,非常小的滑動就能夠使用窗體的內(nèi)容可見。
該屬性是主windowr默認(rèn)設(shè)置。
”adjustResize“
Activity的窗體總是被調(diào)整其大小以便為軟鍵盤騰出空間。
”adjustPan“
Activity的主窗體不會被調(diào)整其大小以便為軟鍵盤騰出空間。相反,窗體的內(nèi)容會被自己主動移動以便當(dāng)前的焦點不會被軟鍵盤遮住,用戶能夠總是看到他輸入的內(nèi)容。
這個值一般用于用戶非常少想調(diào)整窗體的大小的情況下。由于用戶可能須要關(guān)閉軟鍵盤來與窗體的其他部分進(jìn)行交互。
從上面系統(tǒng)的描寫敘述了解了系統(tǒng)在處理兩個交互時都顯示Activity和軟鍵盤都是看作window窗體來處理的。
非常多的時候,我們都希望可以監(jiān)聽到軟件鍵盤的顯示與關(guān)閉狀態(tài)。比方下圖的情況,
你有一個登錄界面是這樣設(shè)計的
你希望登錄時它是這種,
然后你去嘗試給activity的windowSoftInputMode屬性加上值,當(dāng)你加上?adjustResize時。它是這種
你不甘心。你將adjustResize改動成adjustPan,結(jié)果是這種
沒有辦法。僅僅有靠我們自己來監(jiān)聽鍵盤的顯示或隱藏來動態(tài)改變布局。如今的問題是怎么監(jiān)聽到鍵盤的動態(tài)改變呢。系統(tǒng)并沒有提供對應(yīng)的方法。我們能夠通過兩種方法來實現(xiàn)。
1.在adjustResize屬性下。activity的窗體大小會發(fā)生改變,而窗體中的layout的大小也必定后會發(fā)生改變。
當(dāng)view大小發(fā)生改變時,必定會引起onSizeChanged(int, int, int, int)的回調(diào)。所以可能自己定義一個Layout。來監(jiān)測onSizeChanged()函數(shù)的回調(diào)。然后在當(dāng)中的作對應(yīng)的處理。
這種方法也是網(wǎng)上傳的最多的方法。
2.借助ViewTreeOberserver類。ViewTreeOberserver能夠用來注冊一個監(jiān)聽器。它能監(jiān)聽view樹的全局變化。
這些變化包含但不限于,整個View的布局,繪制傳遞的源頭,觸摸模式的變化。
第一種方法的實現(xiàn):
自己定義一個Layout。以RelativeLayout為例,
能夠在onSizeChanged(intw,inth,intoldw,intoldh)方法里監(jiān)聽界面大小的變化,然后在該方法里定義回調(diào)函數(shù)。當(dāng)監(jiān)聽到鍵盤被調(diào)出時,將鍵盤向上推一段距離,這樣將登錄鍵顯示出來。
package com.example.keyboardlistener;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.RelativeLayout;
public class KeyboardLayout extends RelativeLayout {
private onSizeChangedListener mChangedListener;
private static final String TAG ="KeyboardLayoutTAG";
private boolean mShowKeyboard = false;
public KeyboardLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
public KeyboardLayout(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public KeyboardLayout(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
Log.d(TAG, "onMeasure-----------");
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// TODO Auto-generated method stub
super.onLayout(changed, l, t, r, b);
Log.d(TAG, "onLayout-------------------");
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
// TODO Auto-generated method stub
super.onSizeChanged(w, h, oldw, oldh);
Log.d(TAG, "--------------------------------------------------------------");
Log.d(TAG, "w----" + w + "\n" + "h-----" + h + "\n" + "oldW-----" + oldw + "\noldh----" + oldh);
if (null != mChangedListener && 0 != oldw && 0 != oldh) {
if (h < oldh) {
mShowKeyboard = true;
} else {
mShowKeyboard = false;
}
mChangedListener.onChanged(mShowKeyboard);
Log.d(TAG, "mShowKeyboard----- " + mShowKeyboard);
}
}
public void setOnSizeChangedListener(onSizeChangedListener listener) {
mChangedListener = listener;
}
interface onSizeChangedListener{
void onChanged(boolean showKeyboard);
}
}
在主Activity里創(chuàng)建一個Handler。當(dāng)監(jiān)聽到布局發(fā)生變化時,通過Handler更新UI。
package com.example.keyboardlistener;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.ViewTreeObserver.OnPreDrawListener;
import android.widget.Button;
import com.example.keyboardlistener.KeyboardLayout.onSizeChangedListener;
public class MainActivity extends Activity {
private static final String TAG = "KeyboardLayoutTAG";
private KeyboardLayout mRoot;
private Button mLogin;
private int mLoginBottom;
private static final int KEYBOARD_SHOW = 0X10;
private static final int KEYBOARD_HIDE = 0X20;
private boolean mGetBottom = true;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
switch (msg.what) {
case KEYBOARD_HIDE:
mRoot.setPadding(0, 0, 0, 0);
break;
case KEYBOARD_SHOW:
int mRootBottom = mRoot.getBottom();
Log.d(TAG, "the mLoginBottom is " + mLoginBottom);
mRoot.setPadding(0, mRootBottom - mLoginBottom, 0, 0);
break;
default:
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getActionBar().hide();
mRoot = (KeyboardLayout) findViewById(R.id.root_view);
mLogin = (Button) findViewById(R.id.login);
mRoot.setOnSizeChangedListener(new onSizeChangedListener() {
@Override
public void onChanged(boolean showKeyboard) {
// TODO Auto-generated method stub
if (showKeyboard) {
mHandler.sendMessage(mHandler.obtainMessage(KEYBOARD_SHOW));
Log.d(TAG, "show keyboard");
} else {
mHandler.sendMessage(mHandler.obtainMessage(KEYBOARD_HIDE));
}
}
});
mRoot.getViewTreeObserver().addOnPreDrawListener(new OnPreDrawListener() {
@Override
public boolean onPreDraw() {
// TODO Auto-generated method stub
if (mGetBottom) {
mLoginBottom = mLogin.getBottom();//獲取登錄button的位置信息。
}
mGetBottom = false;
return true;
}
});
}
// @Override
// public boolean onCreateOptionsMenu(Menu menu) {
// // Inflate the menu; this adds items to the action bar if it is present.
// getMenuInflater().inflate(R.menu.main, menu);
// return true;
// }
}
另外一種方法的實現(xiàn):
借助ViewTreeObserver類對你想監(jiān)聽的view加入OnGlobalLayoutListener監(jiān)聽器。然后在onGlobalLayout()方法里窗體的變化情況來推斷鍵盤是否被調(diào)出來了。以下是ViewTreeObserver監(jiān)聽的部分的代碼:
mRoot.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int offset = mRoot.getRootView().getHeight() - mRoot.getHeight();
//依據(jù)視圖的偏移值來推斷鍵盤是否顯示
if (offset > 300) {
mHandler.sendMessage(mHandler.obtainMessage(KEYBOARD_SHOW));
} else {
mHandler.sendMessage(mHandler.obtainMessage(KEYBOARD_HIDE));
}
}
});
當(dāng)中Handler的詳細(xì)實現(xiàn)同上述結(jié)構(gòu)中的Handler一樣。
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結(jié)
以上是生活随笔為你收集整理的android 隐藏键盘时ui延迟恢复,android 软键盘的显示与隐藏问题的研究的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: worklist 设备对接,pe 为例
- 下一篇: 学做菜咯