Skip to content

Handling ProgressBars

paridhikhaitan edited this page Jul 5, 2019 · 33 revisions

Overview

ProgressBar is used to display the progress of an activity while the user is waiting. You can display an indeterminate progress (spinning wheel) or result-based progress.

ProgressBars

Indeterminate

We can display an indeterminate progress bar which we show to indicate waiting:

<ProgressBar android:id="@+id/pbLoading" android:visibility="invisible" android:layout_width="wrap_content" android:layout_height="wrap_content" />

and then manage the visibility in the activity:

// on some click or some loading we need to wait for... ProgressBar pb = (ProgressBar) findViewById(R.id.pbLoading); pb.setVisibility(ProgressBar.VISIBLE); // run a background job and once complete pb.setVisibility(ProgressBar.INVISIBLE);

Typically you want to try to put the ProgressBar in the place where data is going to show (i.e. as a placeholder for an image). For a ListView, you put the ProgressBar in the header or footer, which lets you put an arbitrary layout outside of the adapter.

Result-based

ProgressBar can be used to report the progress of a long-running AsyncTask. In this case:

  • ProgressBar can report numerical results for a task.
  • Must specify horizontal style and result max value.
  • Must publishProgress(value) in your AsyncTask
<ProgressBar android:id="@+id/progressBar1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:visibility="invisible" style="?android:attr/progressBarStyleHorizontal" android:max="100" />

and then within the AsyncTask:

public class DelayTask extends AsyncTask<Void, Integer, String> { int count = 0; @Override protected void onPreExecute() { pb.setVisibility(ProgressBar.VISIBLE); } @Override protected String doInBackground(Void... params) { while (count < 5) { SystemClock.sleep(1000); count++; publishProgress(count * 20); } return "Complete"; } @Override protected void onProgressUpdate(Integer... values) { pb.setProgress(values[0]); } }

and using this pattern any background tasks can be reflected by an on-screen progress report.

Progress within ActionBar

We can add a ProgressBar into our ActionBar or Toolbar using a custom ActionView. First, let's define the progress action-view with a layout file in res/layout/action_view_progress.xml with a progress-bar:

<?xml version="1.0" encoding="utf-8"?> <ProgressBar xmlns:android="http://schemas.android.com/apk/res/android" style="?android:attr/progressBarStyleLarge" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/pbProgressAction" />

Next, we can add the ActionView to our ActionBar in the res/menu/activity_main.xml as an item:

<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity"> <item android:id="@+id/miActionProgress" android:title="Loading..." android:visible="false" android:orderInCategory="100" app:showAsAction="always" app:actionLayout="@layout/action_view_progress" /> </menu>

Note the use of android:orderInCategory to append the item at the end (other items should be less than 100), android:visible which hides the menu item and also app:actionLayout which specifies the layout for the action-view. Next, we can use the onPrepareOptionsMenu method to get a reference to the menu item and the associated view within the activity:

public class MainActivity extends AppCompatActivity { // Instance of the progress action-view MenuItem miActionProgressItem; @Override public boolean onPrepareOptionsMenu(Menu menu) { // Store instance of the menu item containing progress miActionProgressItem = menu.findItem(R.id.miActionProgress); // Return to finish return super.onPrepareOptionsMenu(menu); } }

Finally, we can toggle the visibility of the miActionProgressItem item to show and hide the progress-bar in the action-bar:

public class MainActivity extends AppCompatActivity { public void showProgressBar() { // Show progress item miActionProgressItem.setVisible(true); } public void hideProgressBar() { // Hide progress item miActionProgressItem.setVisible(false); } }

and the result:

Progress Action

Progress Within ListView Footer

Often the user is waiting for a list of items to be populated into a ListView. In these cases, we can display the progress bar at the bottom of the ListView using a footer. First, let's define the footer xml layout in res/layout/footer_progress.xml:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content"> <ProgressBar style="?android:attr/progressBarStyleLarge" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/pbFooterLoading" android:layout_gravity="center_horizontal" android:visibility="gone" /> </LinearLayout>

Note the use of a LinearLayout with the layout_height set to wrap_content as this is important for the footer to be properly hidden. Next, let's setup the footer within our ListView by inflating and inserting the header within the activity:

public class MainActivity extends AppCompatActivity { // ... // Store reference to the progress bar later ProgressBar progressBarFooter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // ... setupListWithFooter(); } // Adds footer to the list default hidden progress public void setupListWithFooter() { // Find the ListView ListView lvItems = (ListView) findViewById(R.id.lvItems); // Inflate the footer View footer = getLayoutInflater().inflate( R.layout.footer_progress, null); // Find the progressbar within footer progressBarFooter = (ProgressBar) footer.findViewById(R.id.pbFooterLoading); // Add footer to ListView before setting adapter lvItems.addFooterView(footer); // Set the adapter AFTER adding footer lvItems.setAdapter(myAdapter); } }

Now with the progressBarFooter progress-bar instance stored we can show and hide the footer with setVisibility:

public class MainActivity extends AppCompatActivity { // Show progress public void showProgressBar() { progressBarFooter.setVisibility(View.VISIBLE); } // Hide progress public void hideProgressBar() { progressBarFooter.setVisibility(View.GONE); } }

Now we can call these show and hide methods as needed to show the footer in the list:

progress in footer

Progress within Dialog

In certain scenarios, a simple solution for displaying a progress bar during a long-running operation is to display a modal progress dialog indicating a task is running:

[[|Using-DialogFragment#displaying-a-progressdialog]]

Note that this modal display prevents the user from interacting with the app until the task is completed. As a result, the progress indicators above generally provide a better user experience.

Third-party Libraries

See this list of third-party progress bars for alternate styles and animations.

NumberProgress

The NumberProgressBar is featured above for example.

References

Finding these guides helpful?

We need help from the broader community to improve these guides, add new topics and keep the topics up-to-date. See our contribution guidelines here and our topic issues list for great ways to help out.

Check these same guides through our standalone viewer for a better browsing experience and an improved search. Follow us on twitter @codepath for access to more useful Android development resources.

Clone this wiki locally