Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ActionBar in PreferenceFragment not recalculating height and font size

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

}
like image 855
jyoonPro Avatar asked Nov 02 '14 22:11

jyoonPro


2 Answers

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

like image 73
jyoonPro Avatar answered Oct 19 '22 06:10

jyoonPro


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.

like image 41
Fukurou Mishiranu Avatar answered Oct 19 '22 05:10

Fukurou Mishiranu