在項目開發(fā)中,用到編輯框的地方經(jīng)常涉及到要監(jiān)聽或者控制軟鍵盤的顯示/隱藏狀態(tài)。本以為這是很容易解決的一個小問題,沒想到當(dāng)初碰到這個問題才明白還得花點小心思才能整好?,F(xiàn)將針對軟鍵盤的顯示/隱藏狀態(tài)的監(jiān)聽/監(jiān)控方法做一些總結(jié),以備后用。
10年積累的成都網(wǎng)站建設(shè)、成都網(wǎng)站制作經(jīng)驗,可以快速應(yīng)對客戶對網(wǎng)站的新想法和需求。提供各種問題對應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識你,你也不認(rèn)識我。但先網(wǎng)站制作后付款的網(wǎng)站建設(shè)流程,更有紅崗免費網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。
一、點擊空白處隱藏軟鍵盤
這是具有編輯框焦點的頁面對輸入法軟鍵盤狀態(tài)監(jiān)聽的一般需求和解決方法.
首先獲得InputMethodManager:
InputMethodManager manager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
監(jiān)聽點擊:
/** * 點擊監(jiān)聽 */ @Override public boolean onTouchEvent(MotionEvent event) { onHideSoftInput(event); return super.onTouchEvent(event); } /** * 點擊空白處,關(guān)閉輸入法軟鍵盤 */ public void onHideSoftInput(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { if (getCurrentFocus() != null && getCurrentFocus().getWindowToken() != null) { manager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); } } }
二、popwindow與輸入法軟鍵盤的結(jié)合
先說下自己想實現(xiàn)的效果:點擊頂部按鈕,打開編輯菜單popwindow并自動彈出軟鍵盤;再次點擊頂部按鈕,或者點擊編輯菜單popwindow上面的底部按鈕,關(guān)閉菜單并隱藏軟鍵盤;菜單打開狀態(tài),點擊返回鍵,若菜單已顯示先關(guān)閉軟鍵盤,再點擊則關(guān)閉菜單。
大致效果圖如下:
1.重寫根布局,監(jiān)聽根布局高度變化
對于這個需求,簡單的用上面第一點的方法是無效的。這里沒法直接通過getCurrentFocus()方法判斷頁面是否獲取焦點來控制,需要通過對popwindow的高度變化進(jìn)行判斷。同時也試過下面的方法,同樣無效。
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); boolean isOpen=imm.isActive();//isOpen若返回true,則表示輸入法打開
popwindow的根布局我這里用的是RelativeLayout,RelativeLayout類可以通過重寫onSizeChanged方法來監(jiān)聽布局大小變化。重寫一個RelativeLayout類便實現(xiàn)了對popwindow的高度變化的監(jiān)聽了。
代碼如下:
/** * 監(jiān)聽輸入法軟鍵盤顯示狀態(tài)的自定義RelativeLayout * * @author zeng * */ public class ResizeRelativeLayout extends RelativeLayout { public ResizeRelativeLayout(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); if (mListener != null) { mListener.OnResizeRelative(w, h, oldw, oldh); } } // 監(jiān)聽接口 private OnResizeRelativeListener mListener; public interface OnResizeRelativeListener { void OnResizeRelative(int w, int h, int oldw, int oldh); } public void setOnResizeRelativeListener(OnResizeRelativeListener l) { mListener = l; } }
2.配置布局文件,初始化UI等,代碼如下:
初始化UI代碼:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initUI(); } private void initUI() { mBtn_open = findViewById(R.id.button1); mBtn_open.setOnClickListener(this); // 編輯窗口 LayoutInflater inflater = getLayoutInflater(); View menuLayout = inflater.inflate(R.layout.menu_window, null); mEditMenuWindow = new PopupWindow(menuLayout, LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, true); mEditMenuWindow.setBackgroundDrawable(getResources().getDrawable(R.color.white)); mEditMenuWindow.setTouchable(true); mEditMenuWindow.setFocusable(true); mEditMenuWindow.setAnimationStyle(R.style.MenuAnimation); mEditMenuWindow.setOutsideTouchable(false); mEditMenuWindow.update(); //監(jiān)聽菜單消失 mEditMenuWindow.setOnDismissListener(this); // 菜單控件 mEt_menu = (EditText) menuLayout.findViewById(R.id.menu_edit); TextView btn_send = (TextView) menuLayout.findViewById(R.id.menu_send); btn_send.setOnClickListener(this); // 監(jiān)聽主布局大小變化,監(jiān)控輸入法軟鍵盤狀態(tài) listenerKeyBoardState(menuLayout); }
其中menu_window.xml文件代碼如下:
<?xml version="1.0" encoding="utf-8"?> <com.example.d_popwindow_inputkeyboard.ResizeRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/menu_layout" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" android:padding="8dp" > <EditText android:id="@+id/menu_edit" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_above="@+id/menu_send" android:layout_marginBottom="8dp" android:background="#ffffffff" android:enabled="true" android:focusable="true" android:focusableInTouchMode="true" android:gravity="top|left" android:inputType="none" android:padding="8dp" android:textSize="18sp" > <requestFocus /> </EditText> <TextView android:id="@+id/menu_send" android:layout_width="fill_parent" android:layout_height="60dp" android:layout_alignParentBottom="true" android:layout_gravity="center" android:background="#ff0f0f0f" android:gravity="center" android:text="發(fā)送" android:textColor="#ffFF6004" android:textSize="20sp" android:textStyle="bold" /> </com.example.d_popwindow_inputkeyboard.ResizeRelativeLayout>
3.打開或關(guān)閉編輯窗口,同時自動顯示或隱藏輸入法軟鍵盤。
此方法兩者的控制順序:先顯示軟鍵盤,再打開編輯窗口;先關(guān)閉編輯窗口,若軟鍵盤當(dāng)前已顯示則再隱藏軟鍵盤。代碼如下:
//點擊頂部發(fā)送按鈕,打開/關(guān)閉編輯窗口 private void clickTopSend() { if (mEditMenuWindow.isShowing()) { //先關(guān)閉窗口再隱藏軟鍵盤 mEditMenuWindow.dismiss(); // 隱藏輸入法軟鍵盤 // hideKeyBoard(); } else { // 窗口顯示前顯示輸入法軟鍵盤 showKeyBoard(); // 顯示輸入窗口 mEditMenuWindow.showAsDropDown(mBtn_open, 0, 0); } } // 窗口顯示前顯示輸入法軟鍵盤 private void showKeyBoard() { InputMethodManager inputMgr = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); inputMgr.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);// 調(diào)用此方法才能自動打開輸入法軟鍵盤 mEditMenuWindow.setSoftInputMode( WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); mEditMenuWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED); // 在顯示popupwindow之后調(diào)用,否則輸入法會在窗口底層 } // 隱藏輸入法軟鍵盤 private void hideKeyBoard() { InputMethodManager inputMgr = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); inputMgr.toggleSoftInput(InputMethodManager.HIDE_NOT_ALWAYS, 0);// 輸入法軟鍵盤打開時關(guān)閉,關(guān)閉時打開 mEditMenuWindow.setSoftInputMode( WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); mEditMenuWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED); // 在顯示popupwindow之后調(diào)用,否則輸入法會在窗口底層 //此方法無效 // if(this.getCurrentFocus().getWindowToken() != null) // { // ((InputMethodManager) getSystemService(INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(), // InputMethodManager.HIDE_NOT_ALWAYS);// 關(guān)閉輸入法軟鍵盤 // } } //點擊底部發(fā)送按鈕,關(guān)閉編輯窗口 private void closeButtomSend() { mEditMenuWindow.dismiss(); } //編輯窗口關(guān)閉時,隱藏輸入法軟鍵盤 @Override public void onDismiss() { // 如果軟鍵盤打開,隱藏輸入法軟鍵盤 if(mIsKeyboardOpened) { hideKeyBoard(); } }
4.判斷軟鍵盤的顯示/隱藏狀態(tài)。
通過對編輯窗口的根布局高度變化來判斷軟鍵盤是否處于顯示狀態(tài),在接口方法OnResizeRelative(int w, int h, int oldw, int oldh)里實現(xiàn)對高度變化的判斷。這里主要判斷以下幾種高度變化場景:
(1)布局的當(dāng)前高度小于上一次的高度,即h < oldh,因為布局被軟鍵盤頂上去了,高度變小了。這種場景同樣適用于點擊按鈕第一次打開窗口時的場景,雖然點擊按鈕時,肉眼看到的是窗口一下就充滿了大半個屏幕,也就是當(dāng)前h > oldh(oldh = 0)。但事實上是,第一次打開窗口時,窗口菜單首先是充滿整個屏幕然后再根據(jù)軟鍵盤高度自動縮進(jìn)的。以下是點擊【打開/發(fā)送】按鈕后,根布局的高度變化日志:
可以看出,首次打開時,窗口高度先是1038,然后自動縮進(jìn)成544,并非一打開便已計算好填充高度。
(2)還有一種特殊情況,就是三星輸入法在軟鍵盤初次打開時,輸入字符后軟鍵盤高度會產(chǎn)生變化,同時造成根布局高度變小;若再清除已輸入的字符,此時軟鍵盤高度變小,根布局高度變大。而這兩種情況下,也就是h < oldh 或者 h > oldh時,軟鍵盤都是處于顯示狀態(tài)。
針對這種情況,我的解決方法是記錄下初次打開時根布局的初始高度值,由于h < oldh時在第(1)步已經(jīng)進(jìn)行了判斷了,所以這里只要判斷 h > oldh時的情況。而無論 h > oldh變化多大,只要h不超過初始高度值(且初始高度值不為0),那么便可認(rèn)為當(dāng)前軟鍵盤仍是處于打開狀態(tài)。
此方法運(yùn)行后的日志如下:
兩種狀況下,軟鍵盤都是顯示狀態(tài)。
以下是監(jiān)聽高度變化判斷的代碼:
/** * 監(jiān)聽主布局大小變化,監(jiān)控輸入法軟鍵盤狀態(tài) * @param menuLayout */ private void listenerKeyBoardState(View menuLayout) { ResizeRelativeLayout mMenuLayout = (ResizeRelativeLayout) menuLayout.findViewById(R.id.menu_layout); mMenuLayout.setOnResizeRelativeListener(new ResizeRelativeLayout.OnResizeRelativeListener() { @Override public void OnResizeRelative(int w, int h, int oldw, int oldh) { mIsKeyboardOpened = false; Log.e("菜單高度", "h = " + h + ",oldh = " + oldh); //記錄第一次打開輸入法時的布局高度 if (h < oldh && oldh > 0 && mMenuOpenedHeight == 0) { mMenuOpenedHeight = h; } // 布局的高度小于之前的高度 if (h < oldh ) { mIsKeyboardOpened = true; } //或者輸入法打開情況下, 輸入字符后再清除(三星輸入法軟鍵盤在輸入后,軟鍵盤高度增加一行,清除輸入后,高度變小,但是軟鍵盤仍是打開狀態(tài)) else if((h <= mMenuOpenedHeight) && (mMenuOpenedHeight != 0)) { mIsKeyboardOpened = true; } Log.e("是否打開", "軟鍵盤 = " + mIsKeyboardOpened); } }); }
最后附上DEMO源碼,詳見附件。
三、InputMethodManager的一些相關(guān)方法(未有效使用過,僅作筆記)
1.調(diào)用顯示系統(tǒng)默認(rèn)的輸入法
方法一、
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.showSoftInput(m_receiverView,InputMethodManager.SHOW_FORCED);
m_receiverView(接受軟鍵盤輸入的視圖(View)
InputMethodManager.SHOW_FORCED(提供當(dāng)前操作的標(biāo)記,SHOW_FORCED表示強(qiáng)制顯示)
方法二、
InputMethodManager m=(InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); m.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
這個InputMethodManager類里面的toggleSoftInput方法的API中的解釋是:
This method toggles the input method window display. If the input window is already displayed, it gets hidden. If not the input window will be displayed.
這個方法在界面上切換輸入法的功能,如果輸入法出于現(xiàn)實狀態(tài),就將他隱藏,如果處于隱藏狀態(tài),就顯示輸入法。
2.調(diào)用隱藏系統(tǒng)默認(rèn)的輸入法
((InputMethodManager)getSystemService(INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(WidgetSearchActivity.this.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
(WidgetSearchActivity是當(dāng)前的Activity)
3.獲取輸入法打開的狀態(tài)
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); boolean isOpen=imm.isActive();
isOpen若返回true,則表示輸入法打開
四、SoftInputMode輸入法軟鍵盤模式相關(guān)說明
輸入法軟鍵盤模式選項:
public int softInputMode;
以下與輸入法模式有關(guān)的各選項說明:
軟輸入?yún)^(qū)域是否可見。
public static final int SOFT_INPUT_MASK_STATE = 0x0f;
未指定狀態(tài)。
public static final int SOFT_INPUT_STATE_UNSPECIFIED = 0;
不要修改軟輸入法區(qū)域的狀態(tài)。
public static final int SOFT_INPUT_STATE_UNCHANGED = 1;
隱藏輸入法區(qū)域(當(dāng)用戶進(jìn)入窗口時)。
public static final int SOFT_INPUT_STATE_HIDDEN = 2;
當(dāng)窗口獲得焦點時,隱藏輸入法區(qū)域。
public static final int SOFT_INPUT_STATE_ALWAYS_HIDDEN = 3;
顯示輸入法區(qū)域(當(dāng)用戶進(jìn)入窗口時)。
public static final int SOFT_INPUT_STATE_VISIBLE = 4;
當(dāng)窗口獲得焦點時,顯示輸入法區(qū)域。
public static final int SOFT_INPUT_STATE_ALWAYS_VISIBLE = 5;
窗口應(yīng)當(dāng)主動調(diào)整,以適應(yīng)軟輸入窗口。
public static final int SOFT_INPUT_MASK_ADJUST = 0xf0;
未指定狀態(tài),系統(tǒng)將根據(jù)窗口內(nèi)容嘗試選擇一個輸入法樣式。
public static final int SOFT_INPUT_ADJUST_UNSPECIFIED = 0x00;
當(dāng)輸入法顯示時,允許窗口重新計算尺寸,使內(nèi)容不被輸入法所覆蓋。
不可與SOFT_INPUT_ADJUSP_PAN混合使用;如果兩個都沒有設(shè)置,系統(tǒng)將根據(jù)窗口內(nèi)容自動設(shè)置一個選項。
public static final int SOFT_INPUT_ADJUST_RESIZE = 0x10;
輸入法顯示時平移窗口。它不需要處理尺寸變化,框架能夠移動窗口以確保輸入焦點可見。
不可與SOFT_INPUT_ADJUST_RESIZE混合使用;如果兩個都沒有設(shè)置,系統(tǒng)將根據(jù)窗口內(nèi)容自動設(shè)置一個選項。
public static final int SOFT_INPUT_ADJUST_PAN = 0x20;
當(dāng)用戶轉(zhuǎn)至此窗口時,由系統(tǒng)自動設(shè)置,所以你不要設(shè)置它。
當(dāng)窗口顯示之后該標(biāo)志自動清除。
public static final int SOFT_INPUT_IS_FORWARD_NAVIGATION = 0x100;
網(wǎng)站名稱:Android項目:輸入法軟鍵盤顯示/隱藏的監(jiān)聽和控制,InputMethodManager用法研究
當(dāng)前地址:http://www.rwnh.cn/article20/jsdojo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供建站公司、做網(wǎng)站、定制網(wǎng)站、ChatGPT、微信公眾號、標(biāo)簽優(yōu)化
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)