This repository has been archived by the owner. It is now read-only.

Odd ActionBar Behavior for ICS and setActionView #425

Closed
thanksmister opened this Issue Apr 4, 2012 · 5 comments

Comments

Projects
None yet
2 participants
@thanksmister

thanksmister commented Apr 4, 2012

On ICS if you have a couple menu items showing in the ActionBar ( android:showAsAction="ifRoom") and you want to set one to an animation or different icon using "MenuItem.setActionView()" when pressed. The menu item next to the changed the pressed item immediately shows a blue highlight as if selected. It's like the pressed one loses the up highlight but it's transfered to the menu item next to it instead.

private View mRefreshIndeterminateProgressView; // save inflated layout for reference
private MenuItem refreshItem; // reference to actionbar menu item we want to swap

if (mRefreshIndeterminateProgressView == null) {
   LayoutInflater inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
   mRefreshIndeterminateProgressView = inflater.inflate(R.layout.actionbar_indeterminate_progress, null);
}
refreshItem.setActionView(mRefreshIndeterminateProgressView); // replace actionbar menu item with progress

Here is what the actionbar_indeterminate_progress.xml looks like:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:gravity="center"> 
<ProgressBar android:layout_width="16dp" 
    android:layout_height="16dp" 
    android:layout_marginLeft="12dp" 
    android:layout_marginRight="12dp" 
    android:layout_gravity="center" 
    style="?android:attr/indeterminateProgressStyle"/> 
</FrameLayout> 

Here is your mainmenu.xml:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

<item android:id="@+id/detail_menu_refresh" 
    android:title="Refresh" 
    android:icon="@drawable/ic_action_refresh" 
    android:showAsAction="ifRoom"/> 

 <item android:id="@+id/main_menu_share" 
    android:title="Share" 
    android:icon="@drawable/ic_action_share"
    android:showAsAction="ifRoom"/>

 <item android:id="@+id/main_menu_about" 
    android:title="About" 
    android:icon="@drawable/ic_action_about"
    android:showAsAction="never"/>

 </menu>
@JakeWharton

This comment has been minimized.

Show comment
Hide comment
@JakeWharton

JakeWharton Apr 4, 2012

Owner

This is the native action bar so anything you see is beyond this library.

The action bar re-uses action item views in an effort to speed up invalidation. When you change a view to use a custom layout it reuses the existing view for the next non-custom action item. Since it will still be in the fade state of its selector it will still appear blue. They should be calling .jumpToCurrentState() (an internal method) but they do not so you see this artifact.

Owner

JakeWharton commented Apr 4, 2012

This is the native action bar so anything you see is beyond this library.

The action bar re-uses action item views in an effort to speed up invalidation. When you change a view to use a custom layout it reuses the existing view for the next non-custom action item. Since it will still be in the fade state of its selector it will still appear blue. They should be calling .jumpToCurrentState() (an internal method) but they do not so you see this artifact.

@JakeWharton JakeWharton closed this Apr 4, 2012

@thanksmister

This comment has been minimized.

Show comment
Hide comment
@thanksmister

thanksmister Apr 4, 2012

I noticed that on Honeycomb the ActionBar does not show this behavior. I was trying to duplicate the refresh animation used in the Google+ application. The Google team seems to have figured it out a workaround. Thanks for the quick response.

thanksmister commented Apr 4, 2012

I noticed that on Honeycomb the ActionBar does not show this behavior. I was trying to duplicate the refresh animation used in the Google+ application. The Google team seems to have figured it out a workaround. Thanks for the quick response.

@JakeWharton

This comment has been minimized.

Show comment
Hide comment
@JakeWharton

JakeWharton Apr 4, 2012

Owner

Looks like they're using a custom selector for the action item background which has no fade duration specified so it returns to its default state instantly.

Owner

JakeWharton commented Apr 4, 2012

Looks like they're using a custom selector for the action item background which has no fade duration specified so it returns to its default state instantly.

@thanksmister

This comment has been minimized.

Show comment
Hide comment
@thanksmister

thanksmister Apr 4, 2012

Thanks for the insight, I will try that route.

thanksmister commented Apr 4, 2012

Thanks for the insight, I will try that route.

@thanksmister

This comment has been minimized.

Show comment
Hide comment
@thanksmister

thanksmister Apr 4, 2012

Yep, if you set your own custom selector for the action item background you can remove the fade which fixes the issue. I grabbed the abs__item_background_holo_dark.xml from ActionBarSherlock > Library > res > drawable and the associated graphics to add to my project. I removed the following line from the nod in the xml which disables the fade:

 <!--   android:exitFadeDuration="@android:integer/config_mediumAnimTime" -->

Here is abs__item_background_holo_dark.xml:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- Even though these two point to the same resource, have two states so the drawable will invalidate itself when coming out of pressed state. -->
    <item android:state_focused="true"  android:state_enabled="false" android:state_pressed="true" android:drawable="@drawable/abs__list_selector_disabled_holo_dark" />
    <item android:state_focused="true"  android:state_enabled="false" android:drawable="@drawable/abs__list_selector_disabled_holo_dark" />
    <item android:state_focused="true"  android:state_pressed="true" android:drawable="@drawable/abs__list_selector_background_transition_holo_dark" />
    <item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/abs__list_selector_background_transition_holo_dark" />
    <item android:state_focused="true"  android:drawable="@drawable/abs__list_focused_holo" />
    <item  android:drawable="@android:color/transparent" />
</selector>

Here is how I set it up in my styles.xml

<style name="Dark" parent="Theme.Sherlock.Light.DarkActionBar">
    <item name="actionBarStyle">@style/Widget.Styled.ActionBar</item>
    <item name="android:actionBarStyle">@style/Widget.Styled.ActionBar</item>
    <item name="actionBarItemBackground">@drawable/abs__item_background_holo_dark</item>
    <item name="android:actionBarItemBackground">@drawable/abs__item_background_holo_dark</item>
</style>

<style name="Widget.Styled.ActionBar" parent="Widget.Sherlock.Light.ActionBar.Solid.Inverse"/>

thanksmister commented Apr 4, 2012

Yep, if you set your own custom selector for the action item background you can remove the fade which fixes the issue. I grabbed the abs__item_background_holo_dark.xml from ActionBarSherlock > Library > res > drawable and the associated graphics to add to my project. I removed the following line from the nod in the xml which disables the fade:

 <!--   android:exitFadeDuration="@android:integer/config_mediumAnimTime" -->

Here is abs__item_background_holo_dark.xml:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- Even though these two point to the same resource, have two states so the drawable will invalidate itself when coming out of pressed state. -->
    <item android:state_focused="true"  android:state_enabled="false" android:state_pressed="true" android:drawable="@drawable/abs__list_selector_disabled_holo_dark" />
    <item android:state_focused="true"  android:state_enabled="false" android:drawable="@drawable/abs__list_selector_disabled_holo_dark" />
    <item android:state_focused="true"  android:state_pressed="true" android:drawable="@drawable/abs__list_selector_background_transition_holo_dark" />
    <item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/abs__list_selector_background_transition_holo_dark" />
    <item android:state_focused="true"  android:drawable="@drawable/abs__list_focused_holo" />
    <item  android:drawable="@android:color/transparent" />
</selector>

Here is how I set it up in my styles.xml

<style name="Dark" parent="Theme.Sherlock.Light.DarkActionBar">
    <item name="actionBarStyle">@style/Widget.Styled.ActionBar</item>
    <item name="android:actionBarStyle">@style/Widget.Styled.ActionBar</item>
    <item name="actionBarItemBackground">@drawable/abs__item_background_holo_dark</item>
    <item name="android:actionBarItemBackground">@drawable/abs__item_background_holo_dark</item>
</style>

<style name="Widget.Styled.ActionBar" parent="Widget.Sherlock.Light.ActionBar.Solid.Inverse"/>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.