2

I need to have the progress indicator on the ActionBar to take up space even if it is not visible.

I am using:

requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setProgressBarIndeterminateVisibility(true);

And then:

setProgressBarIndeterminateVisibility(false);

This seems to set the progress bar visibility to GONE and not INVISIBLE, which makes my dynamic amount of tabs on the action bar to move and removing my apps title temporarily until the progress is done.

Thinking about adding an empty action on the action bar which I can remove before indicating progress and add again when finished. Is there another less messy way to do it?

Robert F
  • 451
  • 3
  • 13

1 Answers1

0

The best answer I could come up with to my own question (a workaround).

First off I need to know if my ActionBar is split or not, following this example. This is to determine whether use the default progress bar when the ActionBar or not. When the ActionBar is split my custom progress bar would end up on the bottom part of the ActionBar, which is not desired.

/values/bools.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <bool name="split_action_bar">false</bool>
</resources>

/values-port/bools.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <bool name="split_action_bar">true</bool>
</resources>

/values-large/bools.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <bool name="split_action_bar">false</bool>
</resources>

In my activity, fetching the value with:

private boolean isActionBarSplitted() {
    return getResources().getBoolean(R.bool.split_action_bar);
}

I have my option menu set up with my custom progress indicator MenuItem to use when my app is on large devices or in landscape mode on narrow devices.

/menu/options_menu.xml:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
    <item 
        android:id="@+id/custom_progress_indicator"
        android:showAsAction="always"/>
    <item
        android:id="@+id/another_menu_item"
        android:icon="@android:drawable/btn_default"
        android:showAsAction="ifRoom"/>
    <item
        android:id="@+id/yet_another_menu_item"
        android:icon="@android:drawable/btn_default"
        android:showAsAction="ifRoom"/>
</menu>

In my Activity I fetch the MenuItem and disable it so it will truly be invisible, but not GONE.

@Override
public boolean onPrepareOptionsMenu(Menu menu) {
    mCustomProgressIndicator = menu.findItem(R.id.custom_progress_indicator);
    mCustomProgressIndicator.setEnabled(false);
    return super.onPrepareOptionsMenu(menu);
}

Layout for the custom progress indicator:

/layout/custom_progress_bar.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ProgressBar android:id="@+id/progress"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

I have the two functions for start and stop indicating progress:

/**
 * Indicates progress on the action bar
 */
private void startIndicatingProgress() {
    mIndicatingProgress = true;
    if (isActionBarSplitted()) {
        // if we have a split action bar, use the default progress indicator
        setProgressBarIndeterminateVisibility(true);
    } else {
        if (mCustomProgressIndicator != null) {
            // this function may get called during onResume where
            // mCustomProgressIndicator is not set

            LayoutInflater inflater = (LayoutInflater)
                    getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            View progressBarLayoutView = inflater.inflate(
                    R.layout.custom_progress_bar, null);
            View progressBar = progressBarLayoutView
                    .findViewById(R.id.progress);
            LayoutParams layoutParams = progressBar.getLayoutParams();

            // well now, not sure what the width of MenuItems is (since it
            // seems impossible to find out)
            // so adjusting the height of the ActionBar with 8, better than
            // to hardcode a value I guess
            layoutParams.width = actionBar.getHeight() + 8;
            mCustomProgressIndicator.setActionView(progressBarLayoutView);
        }
    }
}

/**
 * Returns true if the ActionBar is currently split
 * 
 * @return
 */
private boolean isActionBarSplitted() {
    return getResources().getBoolean(R.bool.split_action_bar);
}

/**
 * Stops indicating progress
 */
private void stopIndicatingProgress() {
    mIndicatingProgress = false;
    // always stop default progress indicator
    setProgressBarIndeterminateVisibility(false);
    // this function may get called in onResume where
    // mCustomProgressIndicator is not set
    if (mCustomProgressIndicator != null) {
        mCustomProgressIndicator.setActionView(null);
    }
}

You'd think this would be ok, but no, when changing orientation my custom ProgressBar gets shrinked, so I need to detect orientation changes and reset the custom progress bar. This is anyways a good idea for me, since on small devices I need to switch between default progress bar and custom since my activity is android:uiOptions="splitActionBarWhenNarrow":

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE
            || newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
        if (mIndicatingProgress) {
            // restart indicating progress to avoid feature of shrinking
            // custom progress
            // bar and switch between custom and default if needed
            stopIndicatingProgress();
            startIndicatingProgress();
        }

        // also remove custom progress indicator if split action bar
        // so it won't take up space on the action bar when using
        // default progress indicator
        if (isActionBarSplitted()) {
            // this seems to be the equivalent of View.setVisibility(View.GONE)
            mCustomProgressIndicator.setVisible(false);
        } else {
            mCustomProgressIndicator.setVisible(true);
        }
    }
}
Community
  • 1
  • 1
Robert F
  • 451
  • 3
  • 13