1. 程式人生 > >Android 模仿QQ登入介面解決軟鍵盤遮擋問題

Android 模仿QQ登入介面解決軟鍵盤遮擋問題

Android 軟體盤彈出可能會遮擋住介面上的某些控制元件。當 windowSoftInputMode 為 adjustPan 時,一般不會擋住 EditText,但是假如 EditText 下面是一個登入按鈕,那麼這個按鈕就可能被擋住,但有時我們希望使用者輸完密碼可以直接點選登入按鈕,而不用把軟鍵盤收起來。這時就需要用到 adjustResize,這種模式能夠獲取到軟鍵盤的高度,這樣我們就能夠精確的對介面進行控制。

在閱讀本章之前,你應該瞭解 windowSoftInputMode 的一些屬性,特別是 adjustResize,如果還不熟悉,建議先閱讀Android 軟鍵盤之 windowSoftInputMode 分析

再回過頭來繼續往下看。

QQ 登入介面很好的解決了軟鍵盤遮擋問題,當然在大屏手機上軟鍵盤並不會擋住登入按鈕。今天我們也來模仿一個 QQ 登入介面,最終效果如下:
QQ登入介面

監聽軟鍵盤彈出及收起事件

step1. 指定 windowSoftInputMode=”adjustResize”

在 AndroidManifest.xml 中相應的 Activity 設定 android:windowSoftInputMode=”adjustResize”,也可以在 java 程式碼中設定。

step2. 監聽 contentView 寬高(layout) 變化

獲取 ViewTreeObserver 並監聽 OnGlobalLayoutListener, 當viewTree的佈局發生變化時onGlobalLayout將會回撥。我們新建一個KeyboardHelper輔助類。

KeyboardHelper.java

public class KeyboardHelper {
    private Activity activity;
    private OnKeyboardStatusChangeListener onKeyboardStatusChangeListener;
    private int windowBottom = -1;
    private int keyboardHeight = 0;

    public KeyboardHelper(Activity activity) {
        this.activity = activity;
        activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
        if
(activity.getRequestedOrientation() != ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) { activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } } public void onCreate() { View content = activity.findViewById(android.R.id.content); // content.addOnLayoutChangeListener(listener); 這個方法有時會出現一些問題 content.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener); } public void onDestroy() { View content = activity.findViewById(android.R.id.content); ViewUtils.removeOnGlobalLayoutListener(content, onGlobalLayoutListener); } private OnGlobalLayoutListener onGlobalLayoutListener = new OnGlobalLayoutListener() { @Override public void onGlobalLayout() { Rect rect = new Rect(); activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(rect); Log.d("KeyboardHelper", "onGlobalLayout: " + rect + ", " + windowBottom); int newBottom = rect.bottom; if (windowBottom != -1 && windowBottom != newBottom) { if (newBottom < windowBottom) { // keyboard pop keyboardHeight = windowBottom - newBottom; if (onKeyboardStatusChangeListener != null) { onKeyboardStatusChangeListener.onKeyboardPop(keyboardHeight); } } else { // keyboard close if (onKeyboardStatusChangeListener != null) { onKeyboardStatusChangeListener.onKeyboardClose(keyboardHeight); } } } windowBottom = newBottom; } }; public void setOnKeyboardStatusChangeListener( OnKeyboardStatusChangeListener onKeyboardStatusChangeListener) { this.onKeyboardStatusChangeListener = onKeyboardStatusChangeListener; } public interface OnKeyboardStatusChangeListener { void onKeyboardPop(int keyboardHeight); void onKeyboardClose(int keyboardHeight); } }

ViewUtils.java


public class ViewUtils {

    public static void removeOnGlobalLayoutListener(View view, ViewTreeObserver.OnGlobalLayoutListener onGlobalLayoutListener) {
        if (Build.VERSION.SDK_INT < 16) {
            view.getViewTreeObserver().removeGlobalOnLayoutListener(onGlobalLayoutListener);
        } else {
            view.getViewTreeObserver().removeOnGlobalLayoutListener(onGlobalLayoutListener);
        }
    }

}

程式碼比較簡單,無非是獲取window的可視座標,通過比較bottom的值來判斷軟鍵盤是彈出還是收起。

實現 QQ 登入介面

有了這個 KeyBoardHelper,那麼要實現和 QQ 登入介面一樣的效果就不難了。我們甚至不需要任何自定義控制元件。思路是在軟鍵盤彈出時,把登入按鈕以上的佈局往上移,只要為其設定一個負值的 topMargin 即可。

如圖所示:
QQ登入介面示意圖

MainActivity 程式碼如下:


public class MainActivity extends Activity {

    private int bottomHeight;
    private KeyboardHelper keyboardHelper;
    private View layoutBottom;
    private View layoutContent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_qq_login);

        layoutContent = findViewById(R.id.layout_content);
        layoutBottom = findViewById(R.id.layout_bottom);
        keyboardHelper = new KeyboardHelper(this);
        keyboardHelper.onCreate();
        keyboardHelper.setOnKeyboardStatusChangeListener(onKeyBoardStatusChangeListener);
        layoutBottom.post(new Runnable() {
            @Override
            public void run() {
                bottomHeight = layoutBottom.getHeight();
            }
        });
    }

    private OnKeyboardStatusChangeListener onKeyBoardStatusChangeListener = new OnKeyboardStatusChangeListener() {

        @Override
        public void onKeyboardPop(int keyboardHeight) {

            final int height = keyboardHeight;
            if (bottomHeight > height) {
                layoutBottom.setVisibility(View.GONE);
            } else {
                int offset = bottomHeight - height;
                final ViewGroup.MarginLayoutParams lp = (MarginLayoutParams) layoutContent
                        .getLayoutParams();
                lp.topMargin = offset;
                layoutContent.setLayoutParams(lp);
            }

        }

        @Override
        public void onKeyboardClose(int keyboardHeight) {
            if (View.VISIBLE != layoutBottom.getVisibility()) {
                layoutBottom.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        layoutBottom.setVisibility(View.VISIBLE);
                    }
                }, 300);
            }
            final ViewGroup.MarginLayoutParams lp = (MarginLayoutParams) layoutContent
                    .getLayoutParams();
            if (lp.topMargin != 0) {
                lp.topMargin = 0;
                layoutContent.setLayoutParams(lp);
            }

        }
    };

    @Override
    protected void onDestroy() {
        super.onDestroy();
        keyboardHelper.onDestroy();
    }
}

佈局檔案:activity_qq_login.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/layout_root"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:id="@+id/layout_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:paddingTop="50dp">

        <ImageView
            android:id="@+id/imageView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:layout_marginTop="18dp"
            android:contentDescription="marginTop68dp"
            android:scaleType="centerInside"
            android:src="@drawable/qq_ava"
            android:visibility="visible" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="18dp"
            android:background="#f3f0f0"
            android:paddingBottom="100dp"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:paddingTop="100dp"
            android:text="這裡為了演示增加一個TextView使登陸按鈕在鍵盤底部"
            android:textColor="#333333"
            android:textSize="13sp" />

        <LinearLayout
            android:id="@+id/layout_ed"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#ffffff"
            android:divider="@drawable/divider"
            android:orientation="vertical"
            android:showDividers="middle">

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@null"
                android:hint="QQ號/手機號/郵箱"
                android:padding="10dp"
                android:textColor="#000000"
                android:textColorHint="#d2d2d2"
                android:textCursorDrawable="@null" />

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@null"
                android:hint="密碼"
                android:padding="10dp"
                android:textColor="#000000"
                android:textColorHint="#d2d2d2"
                android:textCursorDrawable="@null" />
        </LinearLayout>

        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="14dp"
            android:layout_marginRight="14dp"
            android:layout_marginTop="14dp"
            android:background="@drawable/btn_login"
            android:text="登陸"
            android:textSize="17sp" />

        <RelativeLayout
            android:id="@+id/layout_bottom"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <TextView
                android:id="@+id/tv_cannot_login"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentBottom="true"
                android:layout_margin="14dp"
                android:text="無法登陸?"
                android:textColor="@color/action_bar_bg"
                android:textSize="14sp" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentBottom="true"
                android:layout_alignParentRight="true"
                android:layout_margin="14dp"
                android:text="新使用者"
                android:textColor="@color/action_bar_bg"
                android:textSize="14sp" />
        </RelativeLayout>
    </LinearLayout>

    <include
        android:id="@+id/appbar"
        layout="@layout/appbar"
        android:layout_width="match_parent"
        android:layout_height="50dp" />

</FrameLayout>

相關推薦

Android 模仿QQ登入介面解決鍵盤遮擋問題

Android 軟體盤彈出可能會遮擋住介面上的某些控制元件。當 windowSoftInputMode 為 adjustPan 時,一般不會擋住 EditText,但是假如 EditText 下面是一個登入按鈕,那麼這個按鈕就可能被擋住,但有時我們希望使用者輸完

一個可以隨手勢拖動的EditText,點選更改內容,附帶解決鍵盤遮擋終極方法

慣例先來看效果圖: 最近產品同學的需求,要求定製一個可拖拽可編輯的文字,原本覺得還挺簡單,不就是寫個EditText處理一下touch事件麼,後來做了發現還有些小坑,記錄一下,順便給大家做個參考。 試錯 首先我嘗試自定義一個EditText,重寫o

解決鍵盤遮擋輸入框的問題

根據前人經驗總結普通Activity(不帶WebView),直接使用adjustpan或者adjustResize如果帶WebView:a) 如果非全屏模式,可以使用adjustResizeb) 如果是全屏模式,則使用AndroidBug5497Workaround進行處理。

js解決鍵盤遮擋輸入框問題

經驗須知 彈出軟鍵盤時: ios端$(‘body’).scrollTop()會改變android端$(window).height()會改變拉起鍵盤不是一瞬間,而是有一個緩動過程 問題重現 ios端,經常會出現輸入法遮擋輸入框的問題(特別是那種有一個白色頂部的輸入法,如:

Android編寫一個登入介面,利用資料庫實現記住密碼,註冊賬號,強制下線,以及類似QQ的下拉列表登入功能

        首先呢,看到這麼長的標題,是不是感覺這些功能有點難以實現呢,哈哈,其實並沒有想象中的那麼複雜,下面就跟著筆者來一起學習一下這些功能是怎麼實現的吧!         1.建立一個所有活動的父類,繼承自A

Android鍵盤遮擋的四種解決方案

問題概述 在編輯框輸入內容時會彈出軟鍵盤,而手機螢幕區域有限往往會遮住輸入介面,我們先看一下問題效果圖: 輸入使用者名稱和密碼時,系統會彈出鍵盤,造成系統鍵盤會擋住文字框的問題,如圖所示: 輸入密碼時輸入框被系統鍵盤遮擋了,大大降低了使用者操作體驗,這就是開發中非常常見的軟鍵盤遮擋的問題,

Android解決鍵盤遮擋的EditText問題

1,在xml中Activity新增配置 android:windowSoftInputMode="stateVisible|adjustResize" 我先試的是這個,不能解決問題 2,在onCr

Android中EditText被輸入法鍵盤遮擋的完美解決方案(非全屏模式下)

1、不要給EditText的背景設定為@null 清單檔案中為activity設定屬性 程式碼中設定顯示輸入法 android:windowSoftInputMode=”stateVisible

Android 鍵盤遮擋PopupWindow解決辦法

專案需要實現評論的功能,因此我使用了popupWindow作為彈出框,其中包含了一個edittext。但是發現軟鍵盤會遮擋一部分popupWindow,而實際上得到的效果應該是軟鍵盤將 整個popupWindow頂上去,後來通過查詢api,發現通過: //設定彈出窗體需要

js-移動端android瀏覽器中input框被鍵盤遮住的問題解決方案

前提: 關於input框被瀏覽器軟鍵盤遮擋住的問題,主要是安卓瀏覽器,下面出一個解決方案: 解決方案原理: 安卓瀏覽器在軟鍵盤彈出後不會像ios瀏覽器那樣重新計算window的高度,所以導致安卓瀏覽器window的高度在軟鍵盤彈出的時候為“軟鍵盤的高度+(windo

Android鍵盤遮擋問題解決

在開發登入介面時,在點選某個EditText準備輸入時,彈出的軟鍵盤遮擋了按鈕或者下面的輸入框,在完成這個文字框的輸入後,想要繼續下面的操作,需要先隱藏軟鍵盤。這會影響使用者操作的流暢感,所以需要解決。在嘗試了網上的幾種處理方法後,最終選擇了一種比較滿意的方式。

Android-UI-關於View-一種toolbar和ScrollView同時存在且鍵盤遮擋ScrollView中的Edittext的解決辦法

問題描述 前段時間在忙工作室的招新app的時候遇到了一種難纏的情況,描述一下出問題的佈局: <RelativeLayout ...> <ImageView.../> <!--這三個控制元件可以可以看成一個toolbar

android鍵盤遮擋WebView中input的解決方案

現象 在做hybrid應用時,我們用WebView來載入html頁面,經常會出現軟體盤彈出,遮擋了html中輸入控制元件(如input)的問題。 無論你是用系統的原生WebView(從4.0-7.0),還是Crosswalk的XWalkView,都有這個問題

android app從登入介面進入主頁,按home鍵回桌面再進入app,重新彈出登入介面的問題解決

在登入介面onCreate方法中,新增以下判斷程式碼即可: @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);

Android 模仿QQ,微信聊天介面長按提示框

效果圖,有點糙 最近要在專案中實現一個長按提示 “複製” 的功能,本來想偷懶在網上找個開源的專案用,但是看了好幾個都不是很滿意,所以就打算按照自己的思路來實現一個。 如何使用 翠花,上程式碼 PromptViewHelper pvHelper = new Pro

Android WebView 鍵盤遮擋輸入框問題的解決方法

1. 在java程式碼中設定 getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); 2. 在

Android - 隱藏EditText彈出的鍵盤輸入(SoftInput)

resize visible nbsp ont mil windows andro car src 隱藏EditText彈出的軟鍵盤輸入(SoftInput)本文地址: http://blog.csdn.net/caroline_wendy保持界面的整潔, 能夠選擇在進入

關於Android鍵盤遮擋的問題

在開發登入介面時,點選某個EditText準備輸入,彈出的軟鍵盤遮擋了按鈕或者下面的輸入框,在完成這個文字框的輸入後,想要繼續下面的操作,需要先隱藏軟鍵盤。這會影響使用者操作的流暢感,所以需要解決。 問題如下: image.png 解決方法 監聽佈局變化,當軟鍵盤彈出時,滾

運用HTML與CSS -------模仿QQ音樂介面

程式碼如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>QQ音樂</title> <st

Android使edittext彈出的鍵盤位於輸入框下面而不是覆蓋輸入框

提供三個方法: 1:在你的activity中的oncreate中setContentView之前寫上這個程式碼 getWindow().setSoftInputMode(WindowManager.La