FragmentActivity - options menu not respecting Fragment lifecycle #272

Closed
jgilfelt opened this Issue Feb 15, 2012 · 24 comments

Comments

Projects
None yet
8 participants
Contributor

jgilfelt commented Feb 15, 2012

When using the support lib plugin FragmentActivity with a Fragment based ViewPager, I get weird behavior when the fragments provide their options menu to the hosting Activity's action bar:

  • The initial menu actions for the 1st fragment loaded into the ViewPager work fine.
  • As soon as a 2nd fragment is paged into the UI, the menu actions become unresponsive.
  • As soon as a 3rd fragment is paged into the UI, the actions that I tried to press for fragment #2 will fire, and so on.
  • Orientation change yields similar results to fragment paging.
  • There is a subtle visible artifact when a 2nd fragment is loaded, as if the new action items are being drawn over previous ones.

I am using a standard FragmentPagerAdapter pattern in my code. I have created a simple example project demonstrating this issue from the Google SupportDemos sample. It works flawlessly on my Galaxy Nexus with the native action bar, on anything else I get have the issues described above. I am using the ABS 4 RC1 library & support lib.

http://dl.dropbox.com/u/3982805/SherlockFragmentActivityMenuDemo.zip

Owner

JakeWharton commented Feb 15, 2012

I'll have to go through the (crazy) callbacks of menu invalidation once more since there is obviously something out of place. Thanks for the sample. I'll try to get it done ASAP.

Owner

JakeWharton commented Feb 16, 2012

Ok. After far too much debugging of the invalidation callback lifecycle I've found that this bug is in a totally separate area.

In order to support dividers between tabs and action items I backported ICS's version of LinearLayout which now supports dividers between children natively. Due to not being in the android.widget package and not being able to access methods marked with @hide, some things were omitted and a lot was stripped so that the only added functionality was the dividers. It would seem that these two factors has led to a few bugs in layout and touch interaction which cause both this and the touch problem you reported earlier.

I'm going to try to adapt the IcsLinearLayout class to extend from LinearLayout (rather than just ViewGroup) and have its implementation only control drawing the dividers.

If you want a stop-gap solution replace IcsLinearLayout with LinearLayout in ActionMenuView.java and comment out anything about dividers. Or perhaps a brutal (semi-untested) hack might work:

@Override
public void invalidateOptionsMenu() {
    super.invalidateOptionsMenu();
    getWindow().getDecorView().requestLayout();
}
Contributor

jgilfelt commented Feb 16, 2012

Thanks Jake!

I patched ActionMenuView.java just as you suggested and my dynamic fragment menu actions are now working as expected, plus you're right, that overflow item layout quirk on the WVGA854 device is gone. The subtle loss in rendering of dividers I can live with.

Thanks again for your tireless efforts.

Owner

JakeWharton commented Feb 23, 2012

@jgilfelt Please try: http://dl.dropbox.com/u/6602046/ActionBarSherlock-Bug-FragmentStatePager.apk and let me know how that works for you.

Here's the zip which requires bleeding edge from 4.0-wip: http://dl.dropbox.com/u/6602046/SherlockFragmentActivityMenuDemo.zip

Contributor

jgilfelt commented Feb 23, 2012

Thanks. I've tested this pretty thoroughly and the Fragment actions now behave as expected, with a couple of minor exceptions:

  • On Android 2.1, after the hosting Activity is created the initial Fragment's action items do not appear in the action bar. Once a new Fragment is paged in, the action bar items appear correctly. Reproducible in the project/APK you provided.
  • The combination of WVGA854/landscape/always|withText and my Sony Ericsson Xperia X10 still causes that weird measurement issue for the right-most action item (#264). Still can't reproduce this on the emulator. The only reason I mention it is that it was temporarily fixed by reverting to LinearLayout in ActionMenuView http://dl.dropbox.com/u/3982805/device-2012-02-23-095443.png

On a side note, there's currently a bunch of references to DisplayMetrics.DENSITY_TV in 4.0-wip bleeding edge that cause runtime crashes on anything less than 3.2.

Owner

JakeWharton commented Feb 23, 2012

Alright thanks for testing. I'm going to have to take a different approach to fixing this then.

Also, I'm surprised you're seeing issues with the latest. That property is a static final constant which means its value should be inlined in the code. I was able to run on two 2.3.3 phones and a 3.0 emulator without incident. I'll have a look.

JakeWharton reopened this Feb 23, 2012

Contributor

jgilfelt commented Feb 23, 2012

I dont think the 2.1 problem is regression from the IcsLinearLayout work you've done here. It seems to be present even in 4.0 beta 6, therefore it might be a separate issue entirely.

Owner

JakeWharton commented Feb 23, 2012

That measurement problem should be fixed. Please test if you get a chance.

In other news, I have no idea what's going on with your demo. The fragment menu invalidation fires fine and all the views are assembled properly but they don't show up on the screen. You can even see them in the hierarchy viewer looking correctly rendered but not displayed.

Contributor

jgilfelt commented Feb 23, 2012

Cool, measurement issue on WVGA854 is sorted. Thanks!

Owner

JakeWharton commented Feb 27, 2012

@jgilfelt Give 'er a try!

Contributor

jgilfelt commented Feb 27, 2012

Thanks, it is now working consistently in 2.1 and above, though we seem to have lost the action item dividers at some point:

previous 4.0-wip (4 days ago):
previous 4.0-wip

latest 4.0-wip:
current 4.0-wip

Owner

JakeWharton commented Feb 27, 2012

Good catch. Fixed as well.

I've met the same issue with ABS 4.0.2 on Android 2.3.3.
My ActionBar with tabs uses ViewPager and FragmentPagerAdapter. Each fragment has its own options menu. After the configuration change the whole ActionBar becomes unresponsive.

Owner

JakeWharton commented May 14, 2012

@aytereschenko Using ViewPager and action items has its own bugs unrelated to this. See #351 and http://b.android.com/29472

@jgilfelt jgilfelt added a commit to jgilfelt/ActionBarSherlock that referenced this issue May 20, 2012

@jgilfelt jgilfelt added known-bugs test case for #272 1b76baf

@JakeWharton JakeWharton added a commit that referenced this issue May 20, 2012

@JakeWharton JakeWharton Merge pull request #485 from jgilfelt/272testcase
added known-bugs test case for #272
d44741e
Contributor

jgilfelt commented May 21, 2012

Modifying com.actionbarsherlock.internal.view.menu.ActionMenuView to inherit from LinearLayout instead of IcsLinearLayout as proposed earlier in this thread seems to be a valid workaround for this issue in 4.1.0, side effect being that dividers will not display between action items.

No. After changing to LinearLayout the issue is still present. ActionBar becomes unresponsive after configuration change. Tested on Android Emulator with SDK 2.3.3 and ABS 4.1.0.

Jake, does your known-bugs test case reproduce this reliably? I'm willing to make a minimal working example that illustrates the problems I'm having with the options menu.

The work-around suggested by jgilfelt appears to work for an SGS2 running 2.3.6 and LG Optimus 2X (CM7) 2.3.7 that were exhibiting the problem.

Hi,

I'm having the exact same problem (a FragmentActivity with tabs and when the second tab is selected, the actions in the action bar are not responsive).
Has this been solved in a release yet?

I tried the proposed trick (replace IcsLinearLayout by LinearLayout in ActionMenuView.java), it solves this problem but the action mode does not work anymore..

I get a crash and the following stacktrace :

08-29 22:52:49.189: E/AndroidRuntime(15365): FATAL EXCEPTION: main
08-29 22:52:49.189: E/AndroidRuntime(15365): java.lang.NullPointerException
08-29 22:52:49.189: E/AndroidRuntime(15365): at com.actionbarsherlock.internal.nineoldandroids.animation.PropertyValuesHolder.setupSetterAndGetter(PropertyValuesHolder.java:515)

Has anyone ever got that same issue?

I'm using ABS 4.1.0 on Android 2.3.5.

roee88 commented Sep 8, 2012

@guillaume-tgl I got the same issue with the dev branch.
My workaround:
Remove view.setAnimation(this); from the constructor of AnimatorProxy
Remove setAnimation(mProxy); from NineLinearLayout.setVisibility (and possibly other Nine* views).
You won't lose animations thanks to the setAnimation call in invalidateAfterUpdate but I barely tested it.

@roee88 Thanks for sharing your solution.
My workaround was to handle the options menu by the activity and not the fragments (the onCreateOptionsMenu and onOptionItemSelected methods).
It's a bit more complex to handle but it's doable and solves the problem of inactive menu options.

@guillaume-tgl You're absolutely right. It can be reproduced by "modifying com.actionbarsherlock.internal.view.menu.ActionMenuView to inherit from LinearLayout instead of IcsLinearLayout" as proposed earlier in the thread and calling startActionMode().

The root cause is that no property map exists for LinearLayout. The secondary cause is that an animation is attempted to be performed using setAlpha(), which doesn't exist for LinearLayout. It seems that the workaround might still work with some more tinkering, but it's certainly not straight-forward.

This issue is still present in 4.2.0, so I spent a little more time trying to find a workaround that retains functionality in Honeycomb and higher, but applies @roee88 fix for older versions. The simplest solution was to throw in a constant WORKAROUND_FOR_ISSUE_272 in ActionMenuView:

public static final boolean WORKAROUND_FOR_ISSUE_272 = 
        Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB;

Check on this constant in each overridden function in IcsLinearLayout to make it only execute the code from LinearLayout. For instance:

@Override
public int getShowDividers() {
    if (!ActionMenuView.WORKAROUND_FOR_ISSUE_272) {
        return mShowDividers;
    }
    return super.getShowDividers();
}

Also disable any additional logic in the IcsLinearLayout constructor and add the following function to the class:

@Override
public void setAnimation(Animation animation) {
    if (!ActionMenuView.WORKAROUND_FOR_ISSUE_272) {
        super.setAnimation(animation);
    }
}

I've done some testing between various devices, especially around the action mode, and it appears to have resolved all problems I had encountered earlier. Note that this does break the dividers and illustrated by @JakeWharton earlier in this issue.

@Anndressa Anndressa pushed a commit to Anndressa/ActionBarSherlock that referenced this issue Apr 19, 2013

Anndressa Kettellym Moraes de Arruda #272 5fdcf66
Contributor

androidmoney commented Dec 8, 2013

Not too sure why this issue is closed, but this is still a problem on a Nexus One running official Gingerbread. The action buttons don't respond on initial start. The "IcsLinearLayout -> LinearLayout in ActionMenuView" workaround fixes the issue.

suomi35 commented Mar 6, 2014

I am experiencing the issue with action buttons as well. I am not having any luck with the "IcsLinearLayout -> LinearLayout in ActionMenuView" workaround, however.

@registe registe pushed a commit to iHavee/HDStar that referenced this issue Mar 22, 2014

@sgwhp sgwhp 修复abs导致的bug 19930c4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment