如何根据新的配置更改重新调整视图?

时间:2018-07-22 20:48:07

标签: android onconfigurationchanged

背景

我有一个应用(here)中带有Admob横幅,我不喜欢每次更改方向后都会重新加载横幅的事实,所以很长一段时间以来,同样的解决方法,以避免重新创建活动,从而避免重新创建Admob视图:

<activity ... android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" android:screenOrientation="fullUser" ...>

问题

这很好用,但是它并不是一个好的解决方案,也不推荐使用。由于这个问题,我不得不使用一种变通方法(对此here表示敬意)。

问题在于某些UI元素(例如工具栏)没有根据新的方向进行更改。

这导致工具栏与应用程序启动时保持相同的高度和相同的字体大小。

纵向->风景示例:

enter image description here

如您所见,横向的高度保持较大,字体大小也保持较大。

关于风景->肖像的示例:

enter image description here

在这里您看到相反的情况。高度保持较小,字体大小也保持较小。

布局基本上是这样的:

<RelativeLayout
    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">

    <androidx.drawerlayout.widget.DrawerLayout
        android:id="@+id/activity_app_list__drawerLayout" android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:layout_width="match_parent" android:layout_height="match_parent"
            android:orientation="vertical">

            <FrameLayout
                android:layout_width="match_parent" android:layout_height="?attr/actionBarSize"
                android:background="?attr/colorPrimary">

                <androidx.appcompat.widget.Toolbar
                    android:id="@+id/activity_main__toolbar" android:layout_width="match_parent"
                    android:layout_height="?attr/actionBarSize" android:background="@null"
                    android:theme="?attr/actionBarTheme" tools:ignore="UnusedAttribute"/>
            </FrameLayout>

            <RelativeLayout
                android:layout_width="match_parent" android:layout_height="match_parent">
                <FrameLayout
                    android:id="@+id/activity_app_list__fragmentContainer"
                    android:layout_width="match_parent" android:layout_height="match_parent"
                    android:layout_above="@+id/activity_app_list__adContainer"/>

                <ImageView
                  android:layout_width="match_parent" android:layout_height="wrap_content"
                    android:src="@drawable/msl__action_bar_shadow"
                    tools:ignore="ContentDescription"/>

                <FrameLayout
                    android:id="@+id/activity_app_list__adContainer"
                    android:layout_width="match_parent" android:layout_height="wrap_content"
                    android:layout_alignParentBottom="true"/>
            </RelativeLayout>
        </LinearLayout>

        <ScrollView
            android:id="@+id/activity_app_list__drawerView" android:layout_width="240dp"
            android:layout_height="match_parent" android:layout_gravity="start"
            android:background="?android:attr/windowBackground">

            <LinearLayout
                android:layout_width="match_parent" android:layout_height="wrap_content"
                android:orientation="vertical">

                <androidx.appcompat.widget.LinearLayoutCompat
                    android:id="@+id/activity_app_list__appToolsContainer"
                    android:layout_width="match_parent" android:layout_height="wrap_content"
                    android:divider="?attr/gridded_listview__divider" android:orientation="vertical"
                    android:showDividers="middle"
                    tools:ignore="MissingRegistered,UnusedAttribute"/>

                <View
                    android:layout_width="match_parent" android:layout_height="1dp"
                    android:layout_marginBottom="8dp" android:layout_marginTop="8dp"
                    android:background="?attr/activity_app_list__drawer_lisview_divider"/>

                <androidx.appcompat.widget.LinearLayoutCompat
                    android:id="@+id/activity_app_list__usefulShortcutsContainer"
                    android:layout_width="match_parent" android:layout_height="wrap_content"
                    android:divider="?attr/gridded_listview__divider" android:orientation="vertical"
                    android:showDividers="middle"
                    tools:ignore="MissingRegistered,UnusedAttribute"/>

                <View
                    android:layout_width="match_parent" android:layout_height="1dp"
                    android:layout_marginBottom="8dp" android:layout_marginTop="8dp"
                    android:background="?attr/activity_app_list__drawer_lisview_divider"/>

                <androidx.appcompat.widget.LinearLayoutCompat
                    android:id="@+id/activity_app_list__appOtherContainer"
                    android:layout_width="match_parent" android:layout_height="wrap_content"
                    android:divider="?attr/gridded_listview__divider" android:orientation="vertical"
                    android:showDividers="middle"
                    tools:ignore="MissingRegistered,UnusedAttribute"/>
            </LinearLayout>
        </ScrollView>
    </androidx.drawerlayout.widget.DrawerLayout>

</RelativeLayout>

我尝试过的

我尝试使用该属性将工具栏的高度重置为它应该具有的高度,但是没有用。还尝试将工具栏标题的文本外观设置为新的方向,但这没有帮助。

我也尝试调用requestLayout,但是它也不起作用。

问题

如何告诉各种UI元素(例如工具栏),它应该根据新的配置更改而更改?

或者,即使我使用configChanges,也可以将工具栏的样式和高度设置为基于新配置吗?

3 个答案:

答案 0 :(得分:2)

Ref:Android - ActionBar not resizing with onConfigurationChanged ( AppCompat )

指出您应该保存并恢复实例状态,而不是尽可能自己处理配置更改。如果您有充分的理由不这样做,则可以在更改配置后尝试更新工具栏的高度和文本外观。

以下代码应适用于工具栏的支持库版本。支持库提供了actionBarSize,titleTextAppearance和subtitleTextAppearance属性。

代码假定您具有在attrs.xml中声明的自定义属性appToolbarStyle。如果不需要,可以修改代码以直接使用R.style.Widget_AppCompat_Toolbar。

import android.support.v7.widget.Toolbar;

...

private Toolbar toolbar;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.main_activity);

    toolbar = findViewById(R.id.toolbar);
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    updateToolbar();
}

private void updateToolbar() {
    if (toolbar == null)
        return;

    final Context context = toolbar.getContext();

    int[] attr = new int[] { R.attr.actionBarSize, R.attr.appToolbarStyle };
    int idxActionBarSize = 0;
    int idxAppToolbarStyle = 1;
    TypedArray a = context.obtainStyledAttributes(attr);
    int actionBarSize = a.getDimensionPixelSize(idxActionBarSize, 0);
    int appToolbarStyle = a.getResourceId(idxAppToolbarStyle, R.style.Widget_AppCompat_Toolbar);
    a.recycle();

    if (actionBarSize != 0) {
        ViewGroup.LayoutParams layoutParams = toolbar.getLayoutParams();
        if (layoutParams != null) {
            layoutParams.height = actionBarSize;
        }

        toolbar.setMinimumHeight(actionBarSize);
    }

    attr = new int[] { R.attr.titleTextAppearance, R.attr.subtitleTextAppearance };
    int idxTitleTextAppearance = 0;
    int idxSubtitleTextAppearance = 1;
    a = context.obtainStyledAttributes(appToolbarStyle, attr);
    int titleTextAppearance = a.getResourceId(idxTitleTextAppearance, 0);
    int subtitleTextAppearance = a.getResourceId(idxSubtitleTextAppearance, 0);
    a.recycle();

    if (titleTextAppearance != 0) {
        toolbar.setTitleTextAppearance(context, titleTextAppearance);
    }

    if (subtitleTextAppearance != 0) {
        toolbar.setSubtitleTextAppearance(context, subtitleTextAppearance);
    }

    toolbar.requestLayout();
}

答案 1 :(得分:0)

通过声明configChange,您确认自己将自行处理onConfigurationChanged()方法。 这是Android docs提供的示例:

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    // Checks the orientation of the screen
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
        Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
    }
}

答案 2 :(得分:0)

尝试使用android:titleTextAppearance代替app:titleTextAppearance

<android.support.v7.widget.Toolbar
    android:id="@+id/main_toolbar"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:background="?attr/colorPrimary"
    app:titleTextAppearance="@style/ToolbarTitle"
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
    app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />  

工具栏样式:

<style name="ToolbarTitle" parent="@style/TextAppearance.Widget.AppCompat.Toolbar.Title">
        <item name="android:textSize">20sp</item>
</style>  

我从here得到了这个答案。看看