关于获取焦点后、软盘弹出后布局不能上顶起来的问题

一、一般情况下给Activity设置如下属性,软盘弹出后布局自定上顶起来

android:windowSoftInputMode="adjustPan|stateHidden"
android:screenOrientation="portrait"
二、但也在一些布局中,给EditText设置输入类型,EditText获取焦点后,再次点击时,布局不能正常顶起,这时我们需要通过计算键盘的高度,键盘弹出时,布局往上移。

需要注意的是,xml布局最外层必须是相对布局RelativeLayout。

第一步:获取状态栏的高度,如果没有的话,就不需要了

/**
 * 获取状态栏高度
 * @param context
 * @return
 */
public static int getStatusBarHeight(Context context) {
    try {
        Class<?> c = Class.forName("com.android.internal.R$dimen");
        Object obj = c.newInstance();
        Field field = c.getField("status_bar_height");
        int x = Integer.parseInt(field.get(obj).toString());
        int height = context.getResources().getDimensionPixelSize(x);
        return height;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return 0;
}
第二步:给EditText设置焦点监听

main_edt.setOnFocusChangeListener(new View.OnFocusChangeListener() {
    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        hasFocusOfEdtPhone = hasFocus;
    }
});
第三步:给键盘设置全局监听

public  void setKeyBoardOnShowedListener(Activity activity) {
    final View decorView = activity.getWindow().getDecorView();
    decorView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {

            Rect rect = new Rect();
            parent_layout.getWindowVisibleDisplayFrame(rect);
            // 屏幕高度。这个高度不含虚拟按键的高度
            int screenHeight = parent_layout.getRootView().getHeight();
            //设置默认值 为屏幕的三分之一
            keyboardHeight = screenHeight / 3;
            // 在不显示软键盘时,heightDiff等于状态栏的高度
            // 在显示软键盘时,heightDiff会变大,等于软键盘加状态栏的高度。
            // 所以heightDiff大于状态栏高度时表示软键盘出现了,
            int heightDiff = screenHeight - (rect.bottom - rect.top);
            /**
             * 如果有状态栏就要添加这句话
             */
            statusBarHeight = getStatusBarHeight(MainActivity.this);
            // 这时可算出软键盘的高度,即heightDiff减去状态栏的高度
            if (keyboardHeight < heightDiff && heightDiff > statusBarHeight) {
                keyboardHeight = heightDiff - statusBarHeight;
            }

            //计算键盘开合
            Rect rect2 = new Rect();
            decorView.getWindowVisibleDisplayFrame(rect2);
            int displayHeight = rect2.bottom - rect2.top;
            int height = decorView.getHeight();
            boolean isShowed = (double) displayHeight / height < 0.8;
            if (isShowed && hasFocusOfEdtPhone) {//键盘弹出且EditText获取焦点
                parent_layout.setY(-(keyboardHeight));
            } else {
                parent_layout.setY(0);
            }
        }
    });
}
三、核心代码:

package testslideswitch.testedittext;

import android.app.Activity;
import android.content.Context;
import android.graphics.Rect;
import android.os.Bundle;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.EditText;
import android.widget.RelativeLayout;

import java.lang.reflect.Field;

public class MainActivity extends Activity {
    private RelativeLayout parent_layout;
    private EditText main_edt;
    /** 软键盘的高度*/
    private int keyboardHeight;
    /** 状态栏的高度*/
    private int statusBarHeight;
    /** 判断输入框是否获取焦点(这个如果有多个输入框时会用到)*/
    private boolean hasFocusOfEdtPhone;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        setWidgetListener();
    }
    /**
     * 初始化View
     */
    private void initView() {
        parent_layout = (RelativeLayout) findViewById(R.id.main_parent_layout);
        main_edt = (EditText) findViewById(R.id.main_edt);
    }
    /**
     * 设置监听
     */
    private void setWidgetListener() {
        main_edt.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                hasFocusOfEdtPhone = hasFocus;
            }
        });
        setKeyBoardOnShowedListener(this);
    }


    /**
     *
     * 监听软键盘全局监听
     * <h3>Version</h3> 1.0
     * <h3>CreateTime</h3> 2016/3/30,23:47
     * <h3>UpdateTime</h3> 2016/3/30,23:47
     * <h3>CreateAuthor</h3> luzhenbang
     * <h3>UpdateAuthor</h3>
     * <h3>UpdateInfo</h3> (此处输入修改内容,若无修改可不写.)
     * @param activity
     */
    public  void setKeyBoardOnShowedListener(Activity activity) {
        final View decorView = activity.getWindow().getDecorView();
        decorView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                Rect rect = new Rect();
                parent_layout.getWindowVisibleDisplayFrame(rect);
                // 屏幕高度。这个高度不含虚拟按键的高度
                int screenHeight = parent_layout.getRootView().getHeight();
                //设置默认值 为屏幕的三分之一
                keyboardHeight = screenHeight / 3;
                // 在不显示软键盘时,heightDiff等于状态栏的高度
                // 在显示软键盘时,heightDiff会变大,等于软键盘加状态栏的高度。
                // 所以heightDiff大于状态栏高度时表示软键盘出现了,
                int heightDiff = screenHeight - (rect.bottom - rect.top);
                /**
                 * 如果有状态栏就要添加这句话
                 */
                statusBarHeight = getStatusBarHeight(MainActivity.this);
                // 这时可算出软键盘的高度,即heightDiff减去状态栏的高度
                if (keyboardHeight < heightDiff && heightDiff > statusBarHeight) {
                    keyboardHeight = heightDiff - statusBarHeight;
                }

                //计算键盘开合
                Rect rect2 = new Rect();
                decorView.getWindowVisibleDisplayFrame(rect2);
                int displayHeight = rect2.bottom - rect2.top;
                int height = decorView.getHeight();
                boolean isShowed = (double) displayHeight / height < 0.8;
                if (isShowed && hasFocusOfEdtPhone) {//键盘弹出且EditText获取焦点
                    parent_layout.setY(-(keyboardHeight));
                } else {
                    parent_layout.setY(0);
                }
            }
        });
    }


    /**
     * 获取状态栏高度
     * @param context
     * @return
     */
    public static int getStatusBarHeight(Context context) {
        try {
            Class<?> c = Class.forName("com.android.internal.R$dimen");
            Object obj = c.newInstance();
            Field field = c.getField("status_bar_height");
            int x = Integer.parseInt(field.get(obj).toString());
            int height = context.getResources().getDimensionPixelSize(x);
            return height;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

}
xml文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main_parent_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <TextView
            android:text="Hello World!"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:layout_weight="1"/>
        <EditText
            android:id="@+id/main_edt"
            android:hint="请输入内容"
            android:inputType="text"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </LinearLayout>

</RelativeLayout>
四、效果图

软盘弹出前:


软盘弹出后:


参考文献:

http://www.csjwang.com/jishu/jiantingruanjianpan-442/






















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值