在配置更改时重新膨胀片段布局

时间:2017-07-11 19:10:39

标签: android android-layout android-fragments android-configchanges

我的Android应用正在手动处理配置更改(出于无法更改的原因),需要根据方向为不同的行和列重新充气GridLayout。我的解决方案在Nexus 5仿真器上运行良好,但在我的Galaxy S6手机上经常出现故障。

来自模拟器的截图:

Portrait screenshot Landscape screenshot

这有时适用于我的手机,但大约一半的时间是从横向旋转到肖像后发生的情况:

Portrait screenshot with bad layout

似乎正在使用旧的布局填充和边距值,而不是在重新夸大布局时创建的新值。此外,这似乎是一个时间问题(请参阅我的问题末尾的Hack)。

代码

以下是使用GridLayout的片段布局,其中columnCountrowCount根据方向发生变化:

fragment_my.xml

<android.support.v7.widget.GridLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:grid="http://schemas.android.com/apk/res-auto"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   grid:columnCount="@integer/col_count"
   grid:rowCount="@integer/row_count"
   grid:orientation="horizontal">

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="80sp"
    grid:layout_gravity="center"
    grid:layout_columnWeight="1"
    grid:layout_rowWeight="1"
    android:text="A"/>

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="80sp"
    grid:layout_gravity="center"
    grid:layout_columnWeight="1"
    grid:layout_rowWeight="1"
    android:text="B"/>

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="80sp"
    grid:layout_gravity="center"
    grid:layout_columnWeight="1"
    grid:layout_rowWeight="1"
    android:text="C"/>

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="80sp"
    grid:layout_gravity="center"
    grid:layout_columnWeight="1"
    grid:layout_rowWeight="1"
    android:text="D"/>

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="80sp"
    grid:layout_gravity="center"
    grid:layout_columnWeight="1"
    grid:layout_rowWeight="1"
    android:text="E"/>

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="80sp"
    grid:layout_gravity="center"
    grid:layout_columnWeight="1"
    grid:layout_rowWeight="1"
    android:text="F"/>

</android.support.v7.widget.GridLayout>

RES /值/ ints.xml

<resources>
   <integer name="row_count">3</integer>
   <integer name="col_count">2</integer>
</resources>

RES /值-脊/ ints.xml

<resources>
   <integer name="row_count">2</integer>
   <integer name="col_count">3</integer>
</resources>

这里是我的片段的相关部分,它为父视图创建FrameLayout,并在方向更改时重新加载fragment_my.xml。

private FrameLayout mFrameLayout;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState)
{
    mFrameLayout = new FrameLayout(getContext());

    // Inflate the layout for this fragment
    return inflater.inflate(R.layout.fragment_my, mFrameLayout, true);
}

@Override
public void onConfigurationChanged(Configuration newConfig)
{
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE ||
        newConfig.orientation == Configuration.ORIENTATION_PORTRAIT)
    {
        // Get rid of previous GridLayout
        mFrameLayout.removeAllViews();

        // Reload GridLayout with new row/col values
        LayoutInflater inflator = LayoutInflater.from(getContext());
        inflator.inflate(R.layout.fragment_my, mFrameLayout, true);
    }

    super.onConfigurationChanged(newConfig);
}

哈克

这是我可以用来修复&#34;我手机上的问题:在充气前延迟100毫秒:

Handler handler = new Handler();
handler.postDelayed(new Runnable() {
    public void run() {
        mFrameLayout.removeAllViews();
        LayoutInflater inflator = LayoutInflater.from(getContext());
        inflator.inflate(R.layout.fragment_my, mFrameLayout, true);
    }
}, 100);

这显然不太理想,因为它依赖于某些时间问题,可能因手机而异。似乎我需要在重新充气之前通知一些内部配置,但我似乎找不到任何回调来执行此操作。

非常感谢任何帮助。

更新

我认为问题是GridLayout中的一个错误。您可以看到我在其他地方询问的related question处理GridLayout的大小调整,导致类似的问题。我用ConstraintLayout替换了我的GridLayout并没有问题。

2 个答案:

答案 0 :(得分:0)

为什么不使用不同的布局,横向和纵向。为横向布局创建布局 - 用于纵向布局的布局 - 端口。我希望它能帮助你解决问题:)

答案 1 :(得分:0)

有几种方法可以等到视图布局。 我最喜欢的是使用view.post(Runnable)

尝试使用

mFrameLayout.post(new Runnable() {
    public void run() {
        mFrameLayout.removeAllViews();
        LayoutInflater inflator = LayoutInflater.from(getContext());
        inflator.inflate(R.layout.fragment_my, mFrameLayout, true);
   }
});

如果这没有帮助,您可以尝试使用ViewTreeObserver。在其上设置OnGlobalLayoutListener,它将在布局视图时触发。