Fragment、Activity 和 DrawerLayout 的 fitsSystemWindows 结合使用问题

4

问题

活动布局有一个DrawerLayout,其中包含一个FrameLayout作为内容用于Fragment,以及一个LinearLayout可以通过抽屉打开和关闭。在内容中使用的片段有一个带有fitsSystemWindows标志和一个ToolbarFrameLayout

如果我在onCreate()中插入片段,则所有内容都符合预期,FrameLayout从0位置开始,Toolbar从状态栏下方开始。但是在onCreate()之外使用相同的代码会失败,fitsSystemWindows不适用于FrameLayout

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

如何获得与onCreate()时相同的行为?

代码

主要活动

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>

碎片

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);
    }

}

片段布局:

<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为绿色,工具栏为蓝色,青色视图始终在工作,需要从y位置0开始。预期结果是第一次绿色和蓝色都可见,但第二次只能看到蓝色。

enter image description here


你解决了吗? - Paul Woitaschek
很不幸,@PaulWoitaschek,不行。我做了一个变通处理,获取状态栏高度并将其设置为工具栏的顶部边距。 - ademar111190
1个回答

5
因此,问题在于当内容被更改时,系统将不再将这些插入物分派到视图层次结构中。
这可以通过 ViewCompat.requestApplyInsets(View) API 轻松解决。这将强制系统再次分派 WindowInsets

要求执行 View.onApplyWindowInsets(WindowInsets) 的新分派。如果可用,则会回退到 View.requestFitSystemWindows()

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

    private void replaceFragment() {
      getSupportFragmentManager().beginTransaction()
          .replace(R.id.content, new MainFragment())
          // 注意,我们正在执行 `commitNow()` 而不是普通的 `commit()`,
          // 因为我们希望此提交同步/立即发生
          .commitNow();
// 要求框架再次将窗口插入物分派到您的视图层次结构的根节点 ViewCompat.requestApplyInsets(findViewById(R.id.drawer)); }

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接