3

对于我正在开发的应用程序,我想在用户输入后重新加载 UI(基本上在他们对其进行更改后完全重置它)。我想尝试避免破坏/重新创建活动并改用setContentView()它,因为它要快得多。

但是,当我这样做时,我遇到了一个问题:新创建的 UI 不尊重它,fitsSystemWindows="true"并且它的一部分最终位于 android 的状态栏后面。

我设法将其归结为该代码示例以对其进行测试:

布局.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 顶部填充,但我更愿意避免像这样丑陋的 hack。

4

2 回答 2

5

所以,你想要的是让框架再次分派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));
    }


于 2017-06-02T06:30:23.823 回答
0

我有同样的问题。我的解决方案是手动更改rootView marginToppaddingTop适应。View

于 2017-06-02T06:14:39.310 回答