fitsSystemWindows на комбинации Fragment, Activity и DrawerLayout

проблема

План действий имеет DrawerLayout с FrameLayout как содержание для Fragment и LinearLayout быть открытым и закрытым ящиком. Фрагмент, используемый для содержания, имеет FrameLayout с fitsSystemWindows флаг и Toolbar,

Если я вставлю фрагмент в onCreate() все происходит как положено, FrameLayout начинается с позиции 0 и Toolbar начинается ниже строки состояния. Но вне onCreate() тот же код не работает, fitsSystemWindows не работает с FrameLayout,

Важный момент, мне нужно Toolbar а также fitsSystemWindows флаг на Fragment и не на 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 быть открытым в красном. FrameLayout с fitsSystemWindows флажок зеленого цвета, а панель инструментов синего цвета, голубой вид работает все время, его нужно начинать с позиции y 0. Ожидается зеленый и синий цвета, как в первый раз, но во второй раз синий - это уникальный вид,

введите описание изображения здесь

1 ответ

Решение

Таким образом, проблема в том, что при изменении содержимого система больше не будет отправлять эти вставки в иерархию представлений.

Это может быть легко решено с ViewCompat.requestApplyInsets(View) API. Это заставит систему отправлять WindowInsets снова.

Спросите, что новая отправка View.onApplyWindowInsets(WindowInsets) быть выполненным. Это возвращается к View.requestFitSystemWindows() где доступно.

Итак, в вашем примере выполнение этих изменений приведет к ожидаемому поведению:


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

Другие вопросы по тегам