androidonconfigurationchanged

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


Background

I have an app (here) that has Admob banners in it, and I don't like the fact that the banners get re-loaded every time I change orientation, so for a long time I had the same workaround for this, to avoid re-creation of the Activity, and therefore avoid re-creation of the Admob view :

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

The problem

This works nice, but it's not really a good solution or recommended. Just a workaround that I had to use because of this issue (wrote about it here).

The problem is that some UI elements, such as the toolbar, don't get change according to the new orientation.

This causes a behavior that the toolbar stays on the same height and same font size as it was when the app started.

Example on portrait->landscape :

enter image description here

As you can see, the height stayed large for landscape, and the font size stayed large too.

Example on landscape->portrait :

enter image description here

Here you see the opposite. The height stayed small, and the font size stayed small too.

The layout is basically something as such:

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

What I've tried

I tried to reset the height of the toolbar to the height it's supposed to have using the attribute, but it didn't work. Also tried to set the text appearance of the title of the toolbar to get to the new orientation, and it didn't help.

I also tried to call requestLayout, but it didn't work either.

The question

How can I tell various UI elements, such as the toolbar, that it should change based on the new configuration change?

As an alternative, is it possible to apply the style and height of the Toolbar to be based on the new configuration, even though I use configChanges ?


Solution

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

    pointed out you should save and restore the instance state instead of handling configuration changes yourself if possible. If you have good reason not to do that you can try to update the toolbar's height and text appearance after the configuration change.

    The following code should work for the support library version of Toolbar. The attributes actionBarSize, titleTextAppearance and subtitleTextAppearance are provided by the support library.

    The code assumes that you have a custom attribute appToolbarStyle declared in attrs.xml. If you don't need that you can adapt the code to use R.style.Widget_AppCompat_Toolbar directly instead.

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