安卓软件盘弹出问题汇总

安卓软件盘弹出问题汇总

前言

  这段时间,给公司的App修改了一下UI,作为一个一年级菜鸟,自然是有应用上的经验需要总结总结,总结之后,下次才可以做的更好。其实这些跟技术都没多大关系,属于设置性的问题,但,这些也可以让人变的更好。

1.1 常见软件盘弹出设置

  平时有EditText控件的地方基本上就或多或少的有界面挤压,拉伸等问题,但实际上这些问题,我们只需要对应添加一些设置就行了。而添加设置的方式有两种,一种是代码设置,一种是在AndroidManifest.xml 项目清单文件中设置,方式都很简单,我们先了解一下有哪些可以设置的值。

    <!-- Defines the default soft input state that this window would
             like when it is displayed.  Corresponds
             to {@link android.view.WindowManager.LayoutParams#softInputMode}. -->
        <attr name="windowSoftInputMode">
            <!-- Not specified, use what the system thinks is best.  This
                 is the default. -->
             <!--没有指定,使用系统认为最好的。这是默认的。 -->
            <flag name="stateUnspecified" value="0" />
            
            <!-- Leave the soft input window as-is, in whatever state it
                 last was. -->
            <!-- 让软输入窗口保持原样,不管它最后是处于什么状态。-->
            <flag name="stateUnchanged" value="1" />
            
            <!-- Make the soft input area hidden when normally appropriate
                 (when the user is navigating forward to your window). -->
             <!--在正常情况下,隐藏软输入区域(当用户正在导航前往你的窗口时)。-->
            <flag name="stateHidden" value="2" />
            
            <!-- Always make the soft input area hidden when this window
                 has input focus. -->
            <!-- 总是使软输入区隐藏,当这个窗口有输入焦点时。-->
            <flag name="stateAlwaysHidden" value="3" />
            
            <!-- Make the soft input area visible when normally appropriate
                 (when the user is navigating forward to your window). -->
             <!-- 在正常情况下,使软输入区域可见(当用户正在导航前往你的窗口时)。 -->
            <flag name="stateVisible" value="4" />
            
            <!-- Always make the soft input area visible when this window
                 has input focus. -->
            <!-- 始终使软输入区域可见,当此窗口时有输入焦点。 -->
            <flag name="stateAlwaysVisible" value="5" />

            <!-- The window resize/pan adjustment has not been specified,
                 the system will automatically select between resize and pan
                 modes, depending
                 on whether the content of the window has any layout views
                 that can scroll their contents.  If there is such a view,
                 then the window will be resized, with the assumption being
                 that the resizeable area can be reduced to make room for
                 the input UI. -->
            <!-- 没有指定窗口大小/平移调整,系统将自动选择调整大小和平移模式,
				 根据关于窗口的内容是否具有布局视图可以滚动它们的内容。如果有这样的视图,
				 然后,在假设存在的情况下,将调整窗口的大小可调整大小的区域可以缩小以腾出空间
				 输入UI。 -->
            <flag name="adjustUnspecified" value="0x00" />
            
            <!-- Always resize the window: the content area of the window is
                 reduced to make room for the soft input area. -->
             <!-- 总是调整窗口的大小:窗口的内容区域是减少为软输入区域腾出空间。 -->
            <flag name="adjustResize" value="0x10" />
            
            <!-- Don't resize the window to make room for the soft input area;
                 instead pan the contents of the window as focus moves inside
                 of it so that the user can see what they are typing.  This is
                 generally less desireable than panning because the user may
                 need to close the input area to get at and interact with
                parts of the window. -->
            <!-- 不要为了给软输入区域腾出空间而调整窗口的大小;
				相反,当焦点移动到窗口内部时,平移窗口的内容
				这样用户就可以看到他们输入的内容。这是
				通常比平移更不受欢迎,因为用户可能会
				需要关闭输入区域以获取和交互窗户的一部分。-->
            <flag name="adjustPan" value="0x20" />
            
            <!-- Don't resize <em>or</em> pan the window to make room for the
                 soft input area; the window is never adjusted for it. -->
            <!-- 不要调整<em>或</em>窗口的大小来为软输入区;窗户从来没有调整过。 -->
            <flag name="adjustNothing" value="0x30" />
        </attr>

  这些都是安卓源码里面的,我一直在想,如何得到官方正宗的资料,Now I get it。讷讷,怎么去设置它呢?

1.1.1 通过代码设置

  在activity中的oncreate方法中setContentView之前,添加如下设置代码。

getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
1.1.2 通过AndroidManifest.xml 项目清单文件设置

  很简单,只要你知道设置值的意义,你很轻松就能掌握它。

  ps:我们可以用 | 符号同时设置多个值

<activity
    android:name=".ui.activity.RegisterActivity"
    android:windowSoftInputMode="adjustPan|stateHidden" />
1.1.3 其他情况

  你知道,有时候EditText在底部的时候,软键盘会把标题栏顶飞,此时,我们也许可以试试添加ScrollView。然后,避免ScrollView和adjustPan同时设置,因为这仍然会使标题栏顶飞,当界面有滚动时,防止标题栏被顶飞,windowSoftInputMode正确的值应该adjustResize。?如果你注意到了的话,源码中,有提及这里。总的来说,要处理好这些,需要更多的经验。
  ? ?
    ? ?

1.2 沉浸模式下软件盘弹出问题

  正常情况下,安卓的软件盘弹出是没那么多事的,甚至不用做过多设置,上面的常规设置足以,但要是沉浸模式下,那就扯着蛋了。
  我们先看一下正常设置沉浸模式,windowSoftInputMode 为默认值
  标题设置 android:fitsSystemWindows = “true” 系统设置标题栏的上边距。

//设置沉浸模式(透明状态栏)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Window win = getWindow();
            win.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
            win.setStatusBarColor(Color.TRANSPARENT);
        }

  结果如下
在这里插入图片描述
这里有两个问题:

  1. 标题栏拉伸
  2. 输入框没被软件盘顶起来。

之前,我是这样做的 ↓: 但输入框是上来了,标题栏走了 ? ,所有这其实是个错误的解决办法。

        <activity
            android:name=".AndroidBug5497.AndroidBug5479Activity"
            android:windowSoftInputMode="stateHidden|adjustPan" />

在这里插入图片描述
我当然不可能无师自通:so,我找到了一些资料,原来如此,我如是说道。

OK,细的,你们可以看下上面的文章,我简单回顾一下咱遇到的问题:

  1. 标题栏拉伸
      android:fitsSystemWindows = “true” 这个设置,会使系统在软键盘弹出时为其设置一个 paddingBottom,所以标题栏下拉了,因为 android:fitsSystemWindows = “true”是用来处理状态栏的,自动设置一个 paddingTop 的值,不好处理,所以我们要解决一下 paddingBottom 。
  2. 输入框没被软件盘顶起来。
      这说是谷歌的一个 bug AndroidBug5497Workaround,沉浸模式下,adjustRelise 无法使输入框正确顶起。一位大神解决了这个 bug。

问题一、自定义一个view替代原来的view,设置 paddingBottom 为 0

/**
 * Created by Administrator on 2019/5/14.
 * TODO 解决adjustResize和  android:fitsSystemWindows="true"冲突问题
 */

public class ImmerseGroup extends FrameLayout {
    public ImmerseGroup(Context context) {
        super(context);
    }

    public ImmerseGroup(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public ImmerseGroup(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), 0);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

问题二、复制好大神的代码

public class AndroidBug5497Workaround {

    // For more information, see https://code.google.com/p/android/issues/detail?id=5497
    // To use this class, simply invoke assistActivity() on an Activity that already has its content view set.

    public static void assistActivity (Activity activity) {
        new AndroidBug5497Workaround(activity);
    }

    private View mChildOfContent;
    private int usableHeightPrevious;
    private FrameLayout.LayoutParams frameLayoutParams;

    private AndroidBug5497Workaround(Activity activity) {
        FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content);
        mChildOfContent = content.getChildAt(0);
        mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            public void onGlobalLayout() {
                possiblyResizeChildOfContent();
            }
        });
        frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams();
    }

    private void possiblyResizeChildOfContent() {
        int usableHeightNow = computeUsableHeight();
        if (usableHeightNow != usableHeightPrevious) {
            int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight();
            int heightDifference = usableHeightSansKeyboard - usableHeightNow;
            if (heightDifference > (usableHeightSansKeyboard/4)) {
                // keyboard probably just became visible
                frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;
            } else {
                // keyboard probably just became hidden
                frameLayoutParams.height = usableHeightNow;
            }
            mChildOfContent.requestLayout();
            usableHeightPrevious = usableHeightNow;
        }
    }

    private int computeUsableHeight() {
        Rect r = new Rect();
        mChildOfContent.getWindowVisibleDisplayFrame(r);
        return (r.bottom - r.top);
    }
}

在 onCreate 中添加这一句就好了

 AndroidBug5497Workaround.assistActivity(this);

在这里插入图片描述
ok,完美解决。源码查看.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值