10

Using the latest AppCompat-v21 library, I used ActionBarActivity to create and populate the PreferenceFragment. However, the ActionBar does not seem to change height and the text size when the orientation or screen size is altered. Testing this on other activities as well, this behavior only seems to be happening in PreferenceActivity (opposed to this question asked here: ActionBar capacity/overflow not changing on orientation change ).

First of all, to handle orientation changes, I added android:configChanges="keyboard|keyboardHidden|orientation|screenSize" to the Manifest. I suspect that this is the main reason for this problem, but as I mentioned earlier, this works on other Activitys.

Here are some screenshots that explain the issue:

Launched PreferenceActivity in Portrait mode:

Portrait start

Rotated to Landscape from Portrait:

rotate to landscape

Launched PreferenceActivity in Landscape mode:

landscape

Rotated to Portrait from Landscape:

rotate to portrait

Additional Information

Here is the PreferenceActivity class:

import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;

public class PrefsActivity extends ActionBarActivity {

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

        getFragmentManager().beginTransaction().replace(android.R.id.content, new PrefsFragment()).commit();
    }

}

Is this behavior a bug? If not, is there a workaround or a fix?


EDIT I

I tried using the new ToolBar widget, but no luck.

import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.Toolbar;

public class PrefsActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_preference);

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar_pref);
        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        getFragmentManager().beginTransaction().replace(R.id.pref_frame, new PrefsFragment()).commit();
    }

}
Community
  • 1
  • 1
jyoonPro
  • 1,661
  • 1
  • 16
  • 41
  • Same problem here. But in my case the font size is simply too small in landscape, no matter how it is started... – Zordid Nov 07 '14 at 17:31
  • Have you tried to define `textSize` in styles.xml ? Sometimes, android will got a bug when you are not define a determined value. You can read this: http://stackoverflow.com/q/16189877/3922207 and http://stackoverflow.com/a/12899367/3922207 – Anggrayudi H Dec 11 '14 at 12:29

3 Answers3

3

android:configChanges is not recommended because orientation, keyboard are not the only causes of Activity recreation.

So, the better approach is to remove this from the Manifest, and set setRetainInstance(true); on the Fragment class. This will bypass this destroy-and-recreate cycle of the Fragment, while refreshing the Activity.

Since the Toolbar is included in the Activity and not the Fragment, this will refresh the Toolbar while keeping the Fragment.

In case of Dialogs, the usage of the Fragment Lifecycle to close/reopen them will work.

Source: http://developer.android.com/guide/topics/resources/runtime-changes.html

jyoonPro
  • 1,661
  • 1
  • 16
  • 41
3

I can offer this solution.

Works with system ActionBar, with Lollipop Toolbar and AppCompat Toolbar.

public static void fixActionBar(Activity activity, View toolbar)
{
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
    {
        if (toolbar == null)
        {
            int id = activity.getResources().getIdentifier("action_bar", "id", "android");
            if (id != 0) toolbar = (Toolbar) activity.findViewById(id);
        }
        if (toolbar != null)
        {
            Context context = toolbar.getContext();
            TypedArray typedArray = context.obtainStyledAttributes(new int[]
                    {android.R.attr.actionBarStyle, android.R.attr.actionBarSize});
            int actionStyle = typedArray.getResourceId(0, 0);
            int actionHeight = typedArray.getDimensionPixelSize(1, 0);
            typedArray.recycle();
            try
            {
                View container = (View) toolbar.getParent();
                Field field = container.getClass().getDeclaredField("mHeight");
                field.setAccessible(true);
                field.setInt(container, actionHeight);
                View overlay = (View) container.getParent();
                field = overlay.getClass().getDeclaredField("mActionBarHeight");
                field.setAccessible(true);
                field.setInt(overlay, actionHeight);
            }
            catch (Exception e)
            {

            }
            toolbar.getLayoutParams().height = actionHeight;
            toolbar.setMinimumHeight(actionHeight);
            typedArray = context.obtainStyledAttributes(actionStyle, new int []
                    {android.R.attr.titleTextStyle});
            ((Toolbar) toolbar).setTitleTextAppearance(context, typedArray.getResourceId(0, 0));
            typedArray.recycle();
        }
    }
}

Call this method from onConfigurationChanged of your Activity.

0

Do the other activities you tested with also have android:configChanges declared on the manifest?

As you said, the problem is that

android:configChanges="keyboard|keyboardHidden|orientation|screenSize"

doesn't handle the rotation. It actually stops the activity and views from being recreated, causing the views not to read the correspondent values after a config change.

Considering the fact that you are using fragments, I would remove the android:configChanges attribute and have the PrefsFragment retain it's instance.

Robert Estivill
  • 12,369
  • 8
  • 43
  • 64