软件世界网 购物 网址 三丰软件 | 小说 美女秀 图库大全 游戏 笑话 | 下载 开发知识库 新闻 开发 图片素材
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
移动开发 架构设计 编程语言 Web前端 互联网
开发杂谈 系统运维 研发管理 数据库 云计算 Android开发资料
  软件世界网 -> 移动开发 -> 如何做好横屏全屏化交互体验以及其中遇到的坑 -> 正文阅读

[移动开发]如何做好横屏全屏化交互体验以及其中遇到的坑


前言


最近公司刚起了一个直播项目,我被抽过去参与,负责其中的直播页,在写直播页的过程中,尤其是横屏状态下,用户的交互出现了很大的问题。
问题是:当用户点击EditText控件时,输入法键盘挡住了部分EditText控件。
在解决的过程中,翻阅的大量的文章:
Android 5.0及以上如何在Translucent模式下防止键盘挡住EditText
Android 5.0 如何实现将布局的内容延伸到状态栏实?
关于透明状态栏的使用以及与软键盘冲突的解决办法
android 动态控制状态栏显示和隐藏的方法实例
动态显示和隐藏状态栏
StatusBarUtil
JKeyboardPanelSwitch
虽然,翻阅了这么多文章,但是然并卵,问题并没有得到解决。最后还是在谷歌官方的例子中找到启发。

这篇文章会带你了解的东西


1 让你知道,你到底需要哪种全屏模式。
2 解决全屏模式下(添加透明状态栏情况下),EditText被挡住的问题。
[img]http://img.blog.csdn.net/20160403104315803

先解决问题(不涉及沉浸式状态栏)


对于视频类项目来说,横屏代表着用户的参与度更高,那么也相应的需要更好的交互体验,一般来说横屏状态下,存在两个View:一个是用于视频播放的View,另一个是用于控制视频状态的控制器View。想要做到完善的交互,对于布局文件来说,还是有一定的格式要求的,请看:
<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"
   >

    <!-- 用于全屏化的View,你可以替代成VideoView, SurfaceView,TextureView等 -->
    <TextView
        android:id="@+id/fullscreen_content"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:background="#ff00ff"
        android:gravity="center"
        android:keepScreenOn="true"
        android:text="@string/dummy_content"
        android:textColor="#33b5e5"
        android:textSize="50sp"
        android:textStyle="bold" />

    <!-- 这里是控制器的布局。对于FrameLayout来说,让其使用    android:fitsSystemWindows=true的属性,可以适应系统UI,以保证App的View不被系统UI遮挡。 -->
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true">

        <LinearLayout
            android:id="@+id/fullscreen_content_controls"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"           
            android:gravity="bottom"
            android:orientation="vertical">

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:imeOptions="actionDone|flagNoExtractUi" />
        </LinearLayout>
    </FrameLayout>
</FrameLayout>

剩下的就需要代码处理了,既然需要横屏全屏化,你往往会添加如下或者与之类似的代码,以达到全屏化的目的:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

但是,千万不要这么做。这个全屏化和我们理想中的全屏化是有差异的,具体差异稍后再说。
为了达到全屏化的目的,我们会监听屏幕旋转事件,当进入横屏模式时, 重新修改需要全屏化View的布局参数(VideoView等),让其宽高等于屏幕的宽高,然后在处理真正的用于全屏化的逻辑。
  @Override
   public void onConfigurationChanged(Configuration newConfig) {
       super.onConfigurationChanged(newConfig);
       if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
           hideSystemBar();
           showSystemBarDelay();
           setTranslucentState();
           float height = DensityUtil.getWidthInPx(this);
           float width = DensityUtil.getHeightInPx(this);
           video_player.getLayoutParams().height = (int) height;
           video_player.getLayoutParams().width = (int) width;
       } else if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
           showPortraitStateSystemBar();
           clearTranslucentState();
           float width = DensityUtil.getWidthInPx(this);
           float height = getResources().getDimension(R.dimen.super_video_default_height);
           video_player.getLayoutParams().height = (int) height;
           video_player.getLayoutParams().width = (int) width;
       }
   }

其中最核心的代码为:
public void hideSystemBar() {
    int systemUiVisibility = View.SYSTEM_UI_FLAG_LOW_PROFILE | View.SYSTEM_UI_FLAG_FULLSCREEN
            | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
            | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) {
        systemUiVisibility |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
    }
    video_player.setSystemUiVisibility(systemUiVisibility);

    RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) video_player.getLayoutParams();
    layoutParams.topMargin = 0;
    video_player.setLayoutParams(layoutParams);
}

public void showSystemBar() {
    video_player.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
}

只要你按照这种方式处理完,那么横屏状态下EditText控件被遮挡的问题也就随之解决了,即使你加上了透明状态栏想关的代码,EditText也会正常显示。
有兴趣的朋友,可以去在AS上新建一个工程,选择FullScreen的模板,然后自己研究研究。

那么,为什么会这样呢?


首先,我们注意到,在两个关键方法中,都是对被全屏化的View调用了其setSystemUiVisibility(int visibility)方法,通过改变参数,来达到隐藏和显示状态栏的目的。
具体看看这个方法的说明:
public void setSystemUiVisibility(int visibility)
  1. 改变状态栏或者屏幕其他系统UI的可见性。
  2. 允许你App的内容放置在系统操作栏(状态栏)之下,通过平滑的过度效果来隐藏和显示系统UI。
  3. 使用这个方法让用户集中更多的注意力在你应用的内容上。
  4. 典型的使用到这个方法的场景是:杂志阅读器/视频播放器

总结来说:如果你做的是视频播放器,使用这个方法来达到全屏化的目的,比单纯调用getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);这块代码来达到全屏化,得到的交互效果会更加流畅和丝滑。
接下来,我们具体看看这些参数到底什么意思。
在查找资料的过程中,翻看到这篇文章:android 动态控制状态栏显示和隐藏的方法实例
其中博主提到,它使用的方法1没有实现效果的原因在于。调用setSystemUiVisibility()的View不对,并不是随便一个View来调用都能达到全屏化的效果的,必须是被全屏化的那个View来调用才行。
接下来,我们就挨个看看这些常量都是什么意思。
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


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

View.SYSTEM_UI_FLAG_FULLSCREEN


请求进入全屏模式,但同时仍然允许用户与系统UI进行交互,这与WindowManager.LayoutParams.FLAG_FULLSCREEN具有相同的视觉效果,一些非关键画面UI(如状态栏)将被隐藏。
但是,WindowManager.LayoutParams.FLAG_FULLSCREEN更强调让用户一直处于一个连续的状态,比如玩游戏。而这个标记则更强调一种沉浸状态,用户可以迅速的退出这种状态。
举个例子,我们看小说的时候,很多时间会专心与小说本身,但是当用户想看一下时间时,点击屏幕,我们可以迅速友好显示系统UI和一些操作控制UI。

View.SYSTEM_UI_FLAG_LAYOUT_STABLE


简单来说,就是防止隐藏和显示系统UI时,控件发生抖动。
如果加上这个设置,无论怎么显示和隐藏系统UI,我们都回到得到一个平滑的过渡效果。
假如你设置了WindowManager.FLAG_FULLSCREEN标记而不是View.SYSTEM_UI_FLAG_FULLSCREE,那么你将得到一直处于隐藏状态的状态栏。注意,改变或清除WindowManager.FLAG_FULLSCREEN不会得到一个平滑的过渡效果。

View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY


其效果是增强显示和隐藏系统UI时的交互体验。
如果不设置的话,那么任何与系统UI的交互,都会导致退出全屏状态。如果设置的话,那么系统UI会短暂的覆盖应用的内容,而且还有一定程度的透明度,并且短暂时间后自动隐藏,并不会退出全屏化。
看一下效果图会更明显一些。
这是全屏化状态
[img]http://img.blog.csdn.net/20160403130811421
这是设置后的效果。
[img]http://img.blog.csdn.net/20160403130822484
这是未设置的效果,与系统UI交互直接退出全屏状态。
[img]http://img.blog.csdn.net/20160403130831297

View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN

View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION


如果窗口有被设置为SYSTEM_UI_FLAG_FULLSCREEN的需求,那么请设置这两个标记,这样可以避免切换系统UI显示与隐藏时,AppUI被覆盖。
如果不设置就会出现下面的情况。
[img]http://img.blog.csdn.net/20160403131804910

View.SYSTEM_UI_FLAG_HIDE_NAVIGATION


隐藏导航栏
以上都是被全屏化的View所需要进行的处理。对于控制器来说,如果不在布局中设置android:fitsSystemWindows=true属性,那么控制器的UI就会跑到状态栏的下面。
[img]http://img.blog.csdn.net/20160403132937273
为了避免以上的情况,就不得不解释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不会被输入法遮挡,都是由于执行了这个方法。
......显示全文...
    点击查看全文


上一篇文章      下一篇文章      查看所有文章
2016-04-03 20:41:06  
移动开发 最新文章
深入了解android中的消息机制Handler
Android
Libgdx之BitmapFont字体
AndroidApp发布到应用市场的流程
Android开发找工作之前先看看这些知识点吧
View的事件分发机制解析
简单介绍了解白鹭引擎Egret
Cocos2d
android获取本地图片(二)
动画特效七:碰撞动画
360图书馆 软件开发资料 文字转语音 购物精选 软件下载 美食菜谱 新闻资讯 电影视频 小游戏 Chinese Culture 股票 租车
生肖星座 三丰软件 视频 开发 短信 中国文化 网文精选 搜图网 美图 阅读网 多播 租车 短信 看图 日历 万年历 2018年1日历
2018-1-16 21:22:23
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  软件世界网 --