如何根据新的配置更改re-adjust views?

How to re-adjust views according to new configuration change?

背景

我有一个应用程序 (here),里面有 Admob 横幅,我不喜欢这样的事实,即每次我改变方向时横幅都会 re-loaded,所以很长一段时间一次我对此有相同的解决方法,以避免 Activity 的 re-creation,因此避免 Admob 视图的 re-creation :

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

问题

这很好用,但它不是真正好的解决方案,也不推荐。只是因为这个问题我不得不使用的解决方法(写了关于它 )。

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

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

纵向->横向示例:

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

横向->纵向示例:

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

布局基本上是这样的:

<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

通过声明 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();
    }
}

您可以使用简单的刷新按钮来刷新您的任何视图控件。 将刷新按钮作为简单的按钮,如下所示,您可以根据需要更改按钮的属性。

<Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Refresh"
        android:onClick="btnrefresh"/>

现在您可以在点击事件中简单地编写代码。

public void btnrefresh(View view)
{
 //Do your task here to change any View Control(including Layout Changes).
}

它将在您编码时对 UI 进行更改。

而不是 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>  

我从那里得到了这个答案。看看

参考: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();
}