1. 程式人生 > >Android之控制元件保持在軟鍵盤上面

Android之控制元件保持在軟鍵盤上面

本文主要記錄一些零碎的東西

軟體盤彈出時,底部的控制元件在軟鍵盤上面,即隨著軟鍵盤彈出而向上移動

activity非全屏時,使用RelativeLayout + ScrollView 可以很簡單的實現,簡單演示一下


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="450dp"
        android:orientation="vertical">

        <!-- your view ... -->

    </LinearLayout>

    <!-- 沒有用,主要用於主動彈出軟鍵盤,後面的控制元件彈到軟鍵盤上面
     非全屏時有效,activity全屏時失效了... -->
   <ScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>


    <!-- 需要隨軟鍵盤彈出的控制元件 -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="47dp"
        android:paddingRight="10dp"
        android:paddingBottom="11dp"
        android:gravity="center_vertical|right"
        android:layout_alignParentBottom="true"
        >
        <TextView
            android:id="@+id/share_photo_weibo_content_num"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_marginRight="13dp"
            android:text="-10"
            android:textColor="#ff3f56"
            android:textSize="16dp"
            android:gravity="center"
            />

        <ImageView
            android:id="@+id/share_photo_weibo_user"
            android:layout_width="100dp"
            android:layout_height="32dp"
            android:src="@drawable/weibobutton"/>
    </LinearLayout>


</RelativeLayout>
可是全屏時失效了

avtivity全屏:

this.requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);

想法是監聽到軟鍵盤的彈出與消失,然後測量出軟鍵盤的高度,底部需要移動的佈局再做移動動畫

思路還是想著監聽軟鍵盤的彈出與消失,查了一圈,發現SDK 不能提供任何有效的解決方案,只能換一個思路

不直接監聽軟鍵盤的事件,當軟鍵盤顯示變化時,會觸發當前佈局中View的全域性佈局變化。通過監聽全域性佈局的變化就可以得知軟鍵盤的狀態使用ViewTreeObserver類,它是一個View檢視樹的觀察者類。

想測量出軟鍵盤的高度,需要用到View中提供的一個方法getWindowVisibleDisplayFrame(),此方法會返回該view所附著的視窗的可見區域大小。當軟鍵盤顯示時,視窗的可見區域大小會被壓縮,當軟鍵盤隱藏時,視窗的可見區域大小會還原。

先看看實現的效果:


    private void showInputManager(EditText editText) {
        editText.setFocusable(true);
        editText.setFocusableInTouchMode(true);
        editText.requestFocus();

        /** 目前測試來看,還是挺準的
         * 原理:OnGlobalLayoutListener 每次佈局變化時都會呼叫
         * 介面view 顯示消失都會呼叫,軟鍵盤顯示與消失時都呼叫
         * */
        mRootView.getViewTreeObserver().addOnGlobalLayoutListener(mLayoutChangeListener);
        InputMethodManager inputManager =
                (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
        inputManager.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT);

    }

    ViewTreeObserver.OnGlobalLayoutListener mLayoutChangeListener = new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            //判斷視窗可見區域大小
            Rect r = new Rect();
            // getWindowVisibleDisplayFrame()會返回視窗的可見區域高度
            getWindow().getDecorView().getWindowVisibleDisplayFrame(r);
            //如果螢幕高度和Window可見區域高度差值大於整個螢幕高度的1/3,則表示軟鍵盤顯示中,否則軟鍵盤為隱藏狀態。
            int heightDifference = WT.mScreenHeight - (r.bottom - r.top);
            boolean isKeyboardShowing = heightDifference > WT.mScreenHeight / 3;
            if(isKeyboardShowing){
//                D.i("slack","show..."+ r.bottom + " - " + r.top + " = " + (r.bottom - r.top) +","+ heightDifference);
                // bottomView 需要跟隨軟鍵盤移動的佈局  
                // setDuration(0) 預設300, 設定 0 ,表示動畫執行時間為0,沒有過程,只有動畫結果了
                bottomView.animate().translationY(-heightDifference).setDuration(0).start();
            }else{
//                D.i("slack","hide...");
                bottomView.animate().translationY(0).start();
            }
        }
    };