显示/隐藏系统栏上的 Android 屏幕闪烁

Posted

技术标签:

【中文标题】显示/隐藏系统栏上的 Android 屏幕闪烁【英文标题】:Android Screen Blinking on show/hide System Bars 【发布时间】:2017-12-07 04:21:28 【问题描述】:

问题

我想在用户向上滚动 RecyclerView 时显示系统栏,并在用户向下滚动时隐藏系统栏。但是,使用我的方法它可以工作,但是在显示/隐藏过程中内容会奇怪地移动和闪烁。你在这里上传了一个视频:https://drive.google.com/open?id=0B_b9EpRt-zyHVW54dkQzcXdUTXM

我的方法

基本上我有这两种方法:

   private void hideSystemUI() 
        getActivity().getWindow().getDecorView().setSystemUiVisibility(
                View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
                        View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                        | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
                        | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
                        | View.SYSTEM_UI_FLAG_IMMERSIVE);

    


    private void showSystemUI() 
        getActivity().getWindow().getDecorView().setSystemUiVisibility(
                View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                        | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
    

我将这个 onScrollListener 设置为 RecyclerView 以根据滚动隐藏和显示状态栏:

   mFragmentListBinding.fragListRvMovies.addOnScrollListener(new RecyclerView.OnScrollListener() 
                @Override
                public void onScrolled(RecyclerView recyclerView, int dx, int dy) 
                    super.onScrolled(recyclerView, dx, dy);

                    if (dy > 5) 
                        //   hideSystemUI();
                        //     SystemUIHelper.hide(getActivity());
                        hideSystemUI();

                     else if (dy < -5) 
                        showSystemUI();
                        //    showSystemUI();
                        //       SystemUIHelper.show(getActivity());
                    
                    if (pageToDownload < TOTAL_PAGES && layoutManager.findLastVisibleItemPosition() == adapter.movieList.size() - 1 && !isLoadingLocked && !isLoading) 
                        downloadMoviesList();
                    


                
            );

这是布局:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <android.support.v4.widget.DrawerLayout
        android:id="@+id/frag_drawer_layout"
        android:layout_
        android:layout_>

        <android.support.design.widget.CoordinatorLayout
            android:id="@+id/frag_drawer_coordinator"
            android:layout_
            android:layout_
            android:fitsSystemWindows="false">


            <android.support.design.widget.AppBarLayout
                android:id="@+id/frag_drawer_appbar"
                android:layout_
                android:layout_
                android:theme="@style/AppTheme.AppBarOverlay"
                android:transitionGroup="false"
                tools:targetApi="lollipop">

                <android.support.v7.widget.Toolbar
                    android:id="@+id/frag_drawer_tb"
                    android:layout_
                    android:layout_

                    android:background="?attr/colorPrimary"
                    app:layout_scrollFlags="scroll|enterAlways"
                    app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                    app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />

            </android.support.design.widget.AppBarLayout>

            <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:id="@+id/frag_drawer_content"
                android:layout_
                android:layout_
                android:fitsSystemWindows="false"
                app:layout_behavior="@string/appbar_scrolling_view_behavior" />

            <android.support.design.widget.FloatingActionButton
                android:id="@+id/frag_drawer_fab_add"
                android:layout_
                android:layout_
                android:layout_gravity="end|bottom"
                android:layout_margin="@dimen/material_component_floating_action_button_margin"
                android:src="@drawable/ic_add_white_24dp"
                android:visibility="gone"
                android:fitsSystemWindows="false"
                app:backgroundTint="@color/accent"
                app:elevation="@dimen/elevation_fab_resting"
                app:fabSize="normal" />


            <android.support.design.widget.FloatingActionButton
                android:id="@+id/frag_drawer_fab_filter"
                android:layout_
                android:layout_
                android:layout_gravity="end|bottom"
                android:layout_margin="@dimen/material_component_floating_action_button_margin"
                android:fitsSystemWindows="false"
                android:src="@drawable/ic_filter"
                android:visibility="visible"
                app:backgroundTint="@color/accent"
                app:elevation="@dimen/elevation_fab_resting"
                app:fabSize="normal" />
        </android.support.design.widget.CoordinatorLayout>


        <android.support.design.widget.NavigationView
            android:id="@+id/frag_drawer_nav"
            android:layout_
            android:layout_
            android:layout_gravity="start"
            app:elevation="@dimen/elevation_nav_drawer"
            app:headerLayout="@layout/layout_nv_header"
            app:itemIconTint="@color/nav_icon_tint"
            app:itemTextColor="@color/nav_text"
            app:menu="@menu/menu_drawer" />

    </android.support.v4.widget.DrawerLayout>
</layout>

我的问题

如何更流畅地显示和隐藏状态栏和导航视图?

【问题讨论】:

android 负责管理显示和隐藏状态栏(顶部)和导航栏(底部)的动画。我们无法控制它 您是否尝试将 animateLayoutChanges="true" 添加到 RecyclerView 或其父容器? 是的,我试过了,但没有任何改变 【参考方案1】:

您看到的是 Layout 调整大小。防止这种情况的唯一方法是将Layout 分层在系统视图下,因此它不受影响。 检查以下标志,这可能有助于防止调整大小:

FLAG_LAYOUT_IN_SCREEN
FLAG_LAYOUT_INSET_DECOR

但是,请记住,您的内容的顶部将位于系统 UI 之后,您需要将其抵消。

【讨论】:

这实际上让我找到了解决方案,谢谢!【参考方案2】:

//隐藏状态栏

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

// 显示状态栏

getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

【讨论】:

【参考方案3】:

您是否尝试过在 Android 的 UI 线程上运行您的方法?例如

runOnUiThread(new Runnable() 
    public void run() 
        // execute your hiding/presenting the bar here
    
);

有几个选项可以使用 Android UI 线程……看看this question

【讨论】:

以上是关于显示/隐藏系统栏上的 Android 屏幕闪烁的主要内容,如果未能解决你的问题,请参考以下文章

隐藏标签栏上的覆盖按钮

Android如何在屏幕上显示通知

Android4.2.2 动态显示隐藏屏幕底部的导航栏(对系统源码进行修改)

如何在android中显示本地推送通知(在主屏幕上的应用程序图标上,如i-phone)

为啥屏幕会出现闪屏

如何更改操作栏上的文本