ProgressBar in an ActionBar, like GMail app with Refresh

后端 未结 4 1823
情书的邮戳
情书的邮戳 2021-01-30 14:18

I would like to do the same thing than the GMail application on Honeycomb tablets. When you click on the Refresh button, the icon is replaced by a ProgressBar. How can I do this

相关标签:
4条回答
  • 2021-01-30 14:58

    Gmail does this using an action view for its "refresh in progress" state. Invoking a refresh is done using the standard action button/onMenuItemSelected path.

    When you enter your refreshing state, set the action view of the refresh MenuItem to a ProgressBar. (Create it programmatically, inflate it from a layout, use actionLayout in the menu xml as CommonsWare suggests, whatever you prefer.) When you exit your refreshing state, set the action view back to null while keeping a reference to it so you can set it back again the next time you refresh. You can hang onto a reference to the MenuItem after you inflate the menu and changes to it later will be reflected in the action bar.

    This approach has some advantages over using a full-time action view and managing other details of the state change yourself. An action view completely replaces the generated action button for a menu item, effectively blocking the user from being able to send the usual onMenuItemSelected events for refresh while a refresh is already in progress. One less thing to handle and the action view can stay completely non-interactive.

    You could probably do something clever with an ActionProvider in API 14+ to encapsulate the whole process a bit more but the above ends up being pretty simple.

    0 讨论(0)
  • 2021-01-30 15:01

    Ok, I tried what Cailean suggested but it didn't work for me. Every time I want to revert indeterminate progress to the original button it becomes unclickable, I used this layout for the progress

    (actionbar_refresh_progress.xml)

    <?xml version="1.0" encoding="utf-8"?>
    <ProgressBar xmlns:android="http://schemas.android.com/apk/res/android"
                 android:layout_width="32dp"
                 android:layout_height="32dp"
                 android:layout_gravity="center"/>
    

    and this one to revert to the button

    (actionbar_refresh_button.xml)

    <ImageView xmlns:android="http://schemas.android.com/apk/res/android"
               android:src="@drawable/ic_menu_refresh_holo_light"
               android:layout_height="wrap_content"
               android:layout_width="wrap_content"/>
    

    my code was:

    private void setRefreshing(boolean refreshing) {
            this.refreshing = refreshing;
            if(refreshMenuItem == null) return;
            View refreshView;
            LayoutInflater inflater = (LayoutInflater)getActionBar().getThemedContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    
            if(refreshing)
                refreshView = inflater.inflate(R.layout.actionbar_refresh_progress, null);
            else
                refreshView = inflater.inflate(R.layout.actionbar_refresh_button, null);
    
            refreshMenuItem.setActionView(refreshView);
        }
    

    After browsing the source of the Google IO app, especially this file: http://code.google.com/p/iosched/source/browse/android/src/com/google/android/apps/iosched/ui/HomeActivity.java i found another easier way.

    Now I need only the first layout with progress and the working method looks like this:

    private void setRefreshing(boolean refreshing) {
        this.refreshing = refreshing;
        if(refreshMenuItem == null) return;
    
        if(refreshing)
            refreshMenuItem.setActionView(R.layout.actionbar_refresh_progress);
        else
            refreshMenuItem.setActionView(null);
    }
    

    Menu item definition:

    <item android:id="@+id/mail_refresh"
          android:title="Refresh"
          android:icon="@drawable/ic_menu_refresh_holo_light"
          android:showAsAction="always"/>
    

    I hope someone finds this useful.

    0 讨论(0)
  • 2021-01-30 15:07

    Use the following layout as the action view for the action bar menu item.

    actionbar_refresh_progress.xml

    <FrameLayout
        android:layout_height="wrap_content"
        android:layout_width="@dimen/abc_action_button_min_width"
        android:minWidth="@dimen/abc_action_button_min_width">
        <ProgressBar
            android:layout_width="32dp"
            android:layout_height="32dp"
             android:layout_gravity="center"
             style="?indeterminateProgressStyle" />
    </FrameLayout>
    

    Then

    menuItem.setActionView(R.layout.actionbar_refresh_progress);
    

    Works across Gingerbread and the rest like a charm. Note that I have used dimension from support action bar for compatibility. You can use @dimen/action_button_min_width instead for ICS and up.

    Source: https://code.google.com/p/iosched/source/browse/android/res/layout/actionbar_indeterminate_progress.xml?r=f4fd7504d43b25a75cc23b58d6f844f3553b48c3

    0 讨论(0)
  • 2021-01-30 15:19

    Assuming that you already have your menu item setup, you'll need to start by creating two new layouts. One that contains the layout for the normal refresh button, and another that contains the progressbar.

    Once you have them, call the following piece of code to switch between the two layouts. It'll be up to you to decide exactly when it needs to be called a second time in order to switch it back to the refresh icon.

    private void doRefresh(Boolean refreshing, MenuItem menuItem)
    {
        View refreshView;
        LayoutInflater inflater = (LayoutInflater) getActionBar().getThemedContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    
        if(refreshing)
            refreshView = inflater.inflate(R.layout.actionbar_indeterminate_progress, null);
        else
            refreshView = inflater.inflate(R.layout.refresh_icon, null);
    
        menuItem.setActionView(refreshView);
    
    }
    
    0 讨论(0)
提交回复
热议问题