如何做好全屏化的交互体验(解决EditText导致的界面上移、挡住等问题)

EditText导致的问题

在使用EditText并且将其放在屏幕底部的时候,往往会使用例如:

android:windowSoftInputMode="adjustResize|stateHidden"
   
   
  • 1

等这样的参数,但是它有着很大的缺点,会导致界面上移、EditText被挡住的问题一些问题。

简单思考EditText键盘弹出后为什么导致界面上移呢?

不从代码层次上考虑,当键盘弹出后,键盘本身占据一定空间会致使EditText随之上移,EditText上移也会导致同一布局层次的其他控件发生位移状况,这就是我们常常碰到的情况,也是非常头痛。

那么,如果将EditText放在一个独立层次的控件中,并且让其上部(因为往往EditText都会放在底部)有一个自动控制其大小宽高的控件,是不是就会解决这个问题呢?

答案是肯定的!

将EditText放入独立的层次布局中,并辅以可自动收缩的控件。

类似于这样:

 <RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <EditText
        android:id="@+id/send_edt"
        android:layout_width="match_parent"
        android:layout_height="55dp"
        android:layout_alignParentBottom="true"
        android:gravity="center_vertical|left"
        android:imeOptions="actionSend|flagNoExtractUi"
        android:lines="1"
        android:minHeight="38dp"
        android:padding="5dp"
        android:textColor="#222222"
        android:textColorHint="#b4b4b4"
        android:textSize="13sp"
        android:visibility="visible" />
    <!--也可以是RecyclerView或ListView,但是不能是LinearLayout或RelativeLayout等布局-->
    <ScrollView
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_above="@id/send_edt" />
</RelativeLayout>
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

你可以直接将这段代码放入到你的Demo中,就会惊人的发现EditText会如你所愿的弹出。

但是问题真正结束了么?当然没有。

在全屏化的体验中,我们的背景往往是一个VideoViewSurfaceView等类似的播放控件。

如果仅仅按照我们如上所示的做,你会发现VideoViewSurfaceView这样的控件,在播放时播放内容会被自动缩小,这也是我们不可接受的。

此时,我的布局如下:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#0099cc"
    tools:context="com.bzh.FullscreenActivity">

    <!-- The primary full-screen view. This can be replaced with whatever view
         is needed to present your content, e.g. VideoView, SurfaceView,
         TextureView, etc. -->
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#CCFF00FF"
        android:padding="30dp">

        <VideoView
            android:layout_centerInParent="true"
            android:id="@+id/fullscreen_content"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#55ff00ff"
            />
    </RelativeLayout>

    <!-- This FrameLayout insets its children based on system windows using
         android:fitsSystemWindows. -->
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <EditText
                android:id="@+id/send_edt"
                android:layout_width="match_parent"
                android:layout_height="55dp"
                android:layout_alignParentBottom="true"
                android:gravity="center_vertical|left"
                android:imeOptions="actionSend|flagNoExtractUi"
                android:lines="1"
                android:minHeight="38dp"
                android:padding="5dp"
                android:textColor="#222222"
                android:textColorHint="#b4b4b4"
                android:textSize="13sp"
                android:visibility="visible" />
            <!--也可以是RecyclerView或ListView,但是不能是LinearLayout或RelativeLayout等布局-->
            <ScrollView
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_above="@id/send_edt" />
        </RelativeLayout>
    </FrameLayout>
</FrameLayout>
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58

那么如何解决这个问题? 我在Google的全屏化Demo中找到了灵感。

借助View.setSystemUiVisibility()方法来达到真正的全屏化目的

很多同学查阅Android如何全屏化的时候,往往都会得到如下的结果:

getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
   
   
  • 1

使用Window的flag来达到目的,但是千万不要这么作,如果你的全屏化状态带有和用户交互的行为,你就应该选择另一种全屏化代码:

setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
   
   
  • 1

具体详细的例子可以看Google的官方例子:

AndroidStudio -> NewProject -> 项目名 -> 选择模板(FullScreen)
   
   
  • 1

当我们加上如上代码时键盘弹出就不会导致VideoView控件播放内容被挤压了。

但是,问题还没有结束,你会发现EditText的输入框不见了。

Why?这是因为EditText并没有随着View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN生效后自动调整。

这个问题的解决办法Google的FullScreen例子也给出了解决办法,加入android:fitsSystemWindows.

<!-- This FrameLayout insets its children based on system windows using
     android:fitsSystemWindows. -->
<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

至此,EditText所引发的问题就得到解决了。

Demo地址 [https://github.com/biezhihua/FullScreenDemo]

View.setSystemUiVisibility介绍

public void setSystemUiVisibility(int visibility)
   
   
  • 1

达到交互式全屏化是调用了上述方法,并通过改变参数来达到隐藏和显示状态栏的目的,其方法简介如下:

  1. 改变状态栏或者屏幕其他系统UI的可见性。
  2. 允许你App的内容放置在系统操作栏(状态栏)之下,通过平滑的过度效果来隐藏和显示系统UI。
  3. 使用这个方法让用户集中更多的注意力在你应用的内容上。
  4. 典型的使用到这个方法的场景是:杂志阅读器/视频播放器

总结来说,如果你做的是视频播放器,使用这个方法来达到全屏化的目的,比单纯调用下面的方法来达到全屏化,得到的交互效果会更加流畅和丝滑。

getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
   
   
  • 1

Flags参数到底是什么意思?

接下来,我们就挨个看看这些常量都是什么意思。

View.SYSTEM_UI_FLAG_LOW_PROFILE
View.SYSTEM_UI_FLAG_FULLSCREEN
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
View.SYSTEM_UI_FLAG_LOW_PROFILE
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

请求系统UI进入一个“低调”的模式。在游戏,阅读器,视频播放器等需要“沉浸式”体验的应用中,系统UI常常会让用户分心。在这种模式下,状态栏和导航栏会变暗。

View.SYSTEM_UI_FLAG_FULLSCREEN
   
   
  • 1

请求进入全屏模式,但同时仍然允许用户与系统UI进行交互,这与WindowManager.LayoutParams.FLAG_FULLSCREEN具有相同的视觉效果,一些非关键画面UI(如状态栏)将被隐藏。

但是,WindowManager.LayoutParams.FLAG_FULLSCREEN更强调让用户一直处于一个连续的状态,比如玩游戏。而这个标记则更强调一种沉浸状态,用户可以迅速的退出这种状态。

举个例子,我们看小说的时候,很多时间会专心与小说本身,但是当用户想看一下时间时,点击屏幕,我们可以迅速友好显示系统UI和一些操作控制UI。

View.SYSTEM_UI_FLAG_LAYOUT_STABLE
   
   
  • 1

简单来说,就是防止隐藏和显示系统UI时,控件发生抖动。

如果加上这个设置,无论怎么显示和隐藏系统UI,我们都回到得到一个平滑的过渡效果。

假如你设置了WindowManager.FLAG_FULLSCREEN标记而不是View.SYSTEM_UI_FLAG_FULLSCREE,那么你将得到一直处于隐藏状态的状态栏。

注意,改变或清除WindowManager.FLAG_FULLSCREEN不会得到一个平滑的过渡效果。

View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
   
   
  • 1

效果是增强显示和隐藏系统UI时的交互体验。

如果不设置的话,那么任何与系统UI的交互,都会导致退出全屏状态。如果设置的话,那么系统UI会短暂的覆盖应用的内容,而且还有一定程度的透明度,并且短暂时间后自动隐藏,并不会退出全屏化。

看一下效果图会更明显一些。

这是全屏化状态
这里写图片描述

这是设置后的效果。
这里写图片描述

这是未设置的效果,与系统UI交互直接退出全屏状态。
这里写图片描述

View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 
   
   
  • 1
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
   
   
  • 1

如果窗口有被设置为SYSTEM_UI_FLAG_FULLSCREEN的需求,那么请设置这两个标记,这样可以避免切换系统UI显示与隐藏时,AppUI被覆盖。

如果不设置就会出现下面的情况。
这里写图片描述

 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
   
   
  • 1

隐藏导航栏

以上都是被全屏化的View所需要进行的处理。对于控制器来说,如果不在布局中设置android:fitsSystemWindows=true属性,那么控制器的UI就会跑到状态栏的下面。

这里写图片描述

为了避免以上的情况,就不得不解释setFitsSystemWindows(boolean)fitSystemWindows(rect)方法了。

setFitsSystemWindows()方法是设置此视图是否应该考虑系统UI,例如状态栏。并为其留出空间。如果参数为true,代表会为系统UI留出空间,那么fitSystemWindows(rect)会被执行。

fitSystemWindows(rect)方法是,当Window内容的边距发生改变时(进入全屏化),允许调用该方法调正我们App的UI,以适应Window的变化。

正常情况下,系统UI会入侵到AppUI的一些空间(状态栏,输入法,导航栏等),也就是我们App的UI不会出现在系统UI之下。

不过万一你使用了SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION ,你的内容可能会被系统UI覆盖。此时,你能调用这个方法,来确保你的UI不会被系统的UI覆盖。

这个方法的简单实现是使用padding来做到的,并且这个方法默认是不执行的。

其实,在横屏全屏状态下,之所以EditText不会被输入法遮挡,都是由于执行了这个方法。

http://blog.csdn.net/biezhihua/article/details/51049689

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值