android - fitsSystemWindows on Fragment、Activity 和 DrawerLayout 组合

标签 android android-layout android-fragments navigation-drawer windowinsets

问题

Activity 布局有一个 DrawerLayout,一个 FrameLayout 作为 Fragment 的内容,还有一个要打开的 LinearLayout并由抽屉关闭。内容上使用的 fragment 有一个带有 fitsSystemWindows 标志的 FrameLayout 和一个 Toolbar

如果我在 onCreate() 插入 fragment ,一切都按预期发生,FrameLayout 从位置 0 开始,Toolbar 从下面开始状态栏。但在 onCreate() 之外,相同的代码失败了,fitsSystemWindows 不适用于 FrameLayout

重要的一点,我需要 Fragment 而不是 Activity 上的 ToolbarfitsSystemWindows 标志。

如何在 onCreate() 时刻看到相同的行为?

代码

主要 Activity

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Window window = getWindow();
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
            window.setStatusBarColor(Color.TRANSPARENT);
        }

        setContentView(R.layout.activity);

        findViewById(R.id.item).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // Out of onCreate fails
                replaceFragment();
            }
        });

        // With onCreate all OK
        replaceFragment();
    }

    private void replaceFragment() {
        getSupportFragmentManager().beginTransaction()
                .replace(R.id.content, new MainFragment())
                .commit();
    }

}

主要布局

<android.support.v4.widget.DrawerLayout
    android:id="@+id/drawer"
    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">

    <FrameLayout
        android:id="@+id/content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <LinearLayout
        android:layout_width="256dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:background="#ff0000"
        android:orientation="vertical"
        tools:layout_gravity="">

        <View
            android:layout_width="match_parent"
            android:layout_height="168dp"
            android:layout_marginBottom="16dp"
            android:background="#00ffff"/>

        <TextView
            android:id="@+id/item"
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:background="#ff00ff"
            android:gravity="center"
            android:text="Click me"/>

    </LinearLayout>

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

fragment

public class MainFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, 
                                                @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment, container, false);
    }

}

fragment 布局:

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#00ff00"
        android:fitsSystemWindows="true">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="56dp"
            android:background="#0000ff"/>

    </FrameLayout>

</RelativeLayout>

例子

要打开的LinearLayout是红色的。带有 fitsSystemWindows 标志的 FrameLayout 是绿色的,工具栏是蓝色的,青色 View 一直在工作,它需要从 y 位置 0 开始。预期是绿色和蓝色像第一次,但第二次看到的是蓝色。

enter image description here

最佳答案

所以,问题是,当内容被更改时,系统将不再将这些插图分派(dispatch)到 View 层次结构。

这可以通过 ViewCompat.requestApplyInsets(View) 轻松解决。应用程序接口(interface)。这将迫使系统再次调度 WindowInsets

Ask that a new dispatch of View.onApplyWindowInsets(WindowInsets) be performed. This falls back to View.requestFitSystemWindows() where available.

因此,在您的示例中执行此更改会导致预期的行为:


    private void replaceFragment() {
      getSupportFragmentManager().beginTransaction()
          .replace(R.id.content, new MainFragment())
          // NOTE, we are performing `commitNow()` instead of ordinary `commit()`,
          // Because we want this commit to happen sychronously/immediately
          .commitNow();

      // Ask the framework to dispatch window insets once more to the root of your view hierarchy
      ViewCompat.requestApplyInsets(findViewById(R.id.drawer));
    }

enter image description here

关于android - fitsSystemWindows on Fragment、Activity 和 DrawerLayout 组合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35799876/

相关文章:

java - Android:如何查找选项卡布局中哪个选项卡处于 Activity 状态?

Android Compose setupWithNavController

javascript - 如何单击信息窗口打开特定布局? - 谷歌地图 API 2

Android 自动启动 Activity (应用启动两次)

android - Android 设置/应用程序中未安装的应用程序

android - 我想把按钮( subview )放在android的前面

android - 我可以始终使用 lint 忽略 NewApi 而不是不同的 styles.xml 文件吗?

android - 如何将 ConstraintLayout 的子项放置在屏幕外(以便稍后可以将它们翻译到屏幕上)?

android - 如何访问不同 Activity 中 fragment 的 contentResolver?

android - 从 BroadcastReceiver 更新适配器