fitsSystemWindows="true" не работает после вызова setContentView()
Для приложения, которое я разрабатываю, я хотел перезагрузить пользовательский интерфейс после ввода данных пользователем (по сути, полностью сбрасывая его после того, как в него были внесены изменения). Я хотел бы попытаться избежать уничтожения / воссоздания деятельности и использования setContentView()
вместо этого, потому что это намного быстрее.
Однако, когда я делаю это, у меня возникает проблема: вновь созданный пользовательский интерфейс не уважает fitsSystemWindows="true"
и часть этого заканчивается позади строки состояния андроида.
Мне удалось свести это к тому примеру кода, чтобы проверить это:
layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:id="@+id/mainContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical">
<Button
android:text="Button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/button" />
</LinearLayout>
MainActivity.java
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
reloadUI();
}
});
}
public void reloadUI() {
setContentView(R.layout.layout);
}
}
Когда я загружаю приложение, я получаю ожидаемый макет, то есть простую кнопку в верхней части экрана, прямо под строкой состояния:
Однако, как только я нажимаю кнопку, которая вызывает setContentView
во второй раз (показывая тот же XML), кнопка оказывается за строкой состояния:
призвание mainContainer.getMeasuredHeight()
проверка того, что происходит, дает мне 1848 пикселей при первом запуске приложения (на экране высотой 1920 пикселей, поэтому его высота на 72 пикселя меньше, чем на весь экран, 72 пикселя - это высота строки состояния), но как только я снова вызываю setContentView mainContainer.getMeasuredHeight()
дает мне 1920px.
Я что-то здесь упускаю? Я мог бы заставить mainContainer придерживаться высоты 1848px с верхним отступом 72px, но я бы предпочел избежать такого уродливого хака, как этот.
2 ответа
Итак, вы хотите попросить структуру отправить еще раз WindowInsets
в ваш корневой вид. Это именно то, что ViewCompat.requestApplyInsets(View)
Сделаю:
Спросите, что новая отправка
View.onApplyWindowInsets(WindowInsets)
быть выполненным. Это возвращается кView.requestFitSystemWindows()
где доступно.
Применение только одной строки должно решить все ваши проблемы:
public void reloadUI() {
setContentView(R.layout.layout);
// `R.id.mainContainer` is the id of the root view in `R.layout.layout`
ViewCompat.requestApplyInsets(findViewById(R.id.mainContainer));
}
У меня такая же проблема. Мое решение состоит в том, чтобы изменить rootView
marginTop
или же paddingTop
адаптироваться к View
вручную.