ProgressBar under Action Bar ProgressBar under Action Bar android android

ProgressBar under Action Bar


I wasn't fully satisfied with the accepted answer above, so I did some extra research myself.

The trick I believe they used is that they retrieved the top view in the view hierarchy called DecorView and added the progress bar in there. That way, the progress bar displays both over the action bar AND the content area. Note that the S.D.'s answer puts the progress bar into content area and 'steals' space from actual content, what can lead to unexpected results.

Sample screenshots of this implementation:

ProgressBar

ProgressBarIndeterminate

Code

Just put this code into onCreate method of some activity and it should work:

// create new ProgressBar and style itfinal ProgressBar progressBar = new ProgressBar(this, null, android.R.attr.progressBarStyleHorizontal);progressBar.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 24));progressBar.setProgress(65);// retrieve the top view of our applicationfinal FrameLayout decorView = (FrameLayout) getWindow().getDecorView();decorView.addView(progressBar);// Here we try to position the ProgressBar to the correct position by looking// at the position where content area starts. But during creating time, sizes // of the components are not set yet, so we have to wait until the components// has been laid out// Also note that doing progressBar.setY(136) will not work, because of different// screen densities and different sizes of actionBarViewTreeObserver observer = progressBar.getViewTreeObserver();observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {    @Override    public void onGlobalLayout() {        View contentView = decorView.findViewById(android.R.id.content);        progressBar.setY(contentView.getY() - 10);        ViewTreeObserver observer = progressBar.getViewTreeObserver();        observer.removeOnGlobalLayoutListener(this);    }});

You can play with LayoutParams' height argument to set the progressBar wider or narrower, but you might have to adjust the -10 offset.

Styling

Unfortunately, you can see the ugly gray background of the progress bar. To remove it, simply searching for the background by id and trying to hide it doesn't work. To remove the background, I had to create identical drawble of the system version and remove the background item.

TL;DR: Create file progress_horizontal_holo_no_background_light.xml and paste this drawable:

<?xml version="1.0" encoding="utf-8"?><layer-list xmlns:android="http://schemas.android.com/apk/res/android">    <item android:id="@android:id/secondaryProgress">        <scale android:scaleWidth="100%"               android:drawable="@drawable/progress_secondary_holo_light" />    </item>    <item android:id="@android:id/progress">        <scale android:scaleWidth="100%"               android:drawable="@drawable/progress_primary_holo_light" />    </item></layer-list>

Copy appropriate .png drawables from sdk/platforms/android-xx/data/res/drawable-xxx/ to your project and then in the code you can add:

progressBar.setProgressDrawable(getResources().getDrawable(R.drawable.progress_horizontal_holo_no_background_light));

Extra: Indeterminate Progress Bar

Pre-KitKat versions of indeterminate progress bars are pretty ugly and laggy.You can download new smooth progressBar called ButteryProgressBar. Just search for it on google (I cannot post any more links, because I am new here :[ ), add the class into your project and you can simply replace the previous ProgressBar with this code and have crispy indeterminate progress bar:

final ButteryProgressBar progressBar = new ButteryProgressBar(this);progressBar.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 24));

You might also need to simplify this code:

final TypedArray ta = c.obtainStyledAttributes(attrs, R.styleable.ButteryProgressBar);try {    mBarColor = ta.getColor(R.styleable.ButteryProgressBar_barColor,            c.getResources().getColor(android.R.color.holo_blue_light));    mSolidBarHeight = ta.getDimensionPixelSize(            R.styleable.ButteryProgressBar_barHeight,            Math.round(DEFAULT_BAR_HEIGHT_DP * mDensity));    mSolidBarDetentWidth = ta.getDimensionPixelSize(            R.styleable.ButteryProgressBar_detentWidth,            Math.round(DEFAULT_DETENT_WIDTH_DP * mDensity));} finally {    ta.recycle();}

to this code:

mBarColor = c.getResources().getColor(android.R.color.holo_blue_light);mSolidBarHeight = Math.round(DEFAULT_BAR_HEIGHT_DP * mDensity);mSolidBarDetentWidth = Math.round(DEFAULT_DETENT_WIDTH_DP * mDensity);

Hope I helped :)


Extend Activities from following class to have a ProgressBar at the top(below ActionBar) of each, and a getProgressBar() method:

Parent class:

public abstract class ProgressActivity extends Activity {    private ProgressBar mProgressBar;    @Override    public void setContentView(View view) {        init().addView(view);    }    @Override    public void setContentView(int layoutResID) {        getLayoutInflater().inflate(layoutResID,init(),true);    }    @Override    public void setContentView(View view, ViewGroup.LayoutParams params) {        init().addView(view,params);    }    private ViewGroup init(){        super.setContentView(R.layout.progress);        mProgressBar = (ProgressBar) findViewById(R.id.activity_bar);        return (ViewGroup) findViewById(R.id.activity_frame);    }    protected ProgressBar getProgressBar(){        return mProgressBar;    }}

Layout (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="match_parent"><ProgressBar android:id="@+id/activity_bar"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:layout_marginTop="-8dp"    style="@android:style/Widget.DeviceDefault.ProgressBar.Horizontal"    />  <FrameLayout android:id="@+id/activity_frame"      android:layout_width="match_parent"      android:layout_height="fill_parent"      /></LinearLayout>


This is now a native behavior that can be obtained using SwipeRefreshLayout.

You can wrap your scrollable view with a SwipeRefreshLayout and then you just need to listen to onRefresh events:

@Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    swipeLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_container);    swipeLayout.setOnRefreshListener(this);    swipeLayout.setColorScheme(android.R.color.holo_blue_bright,             android.R.color.holo_green_light,             android.R.color.holo_orange_light,             android.R.color.holo_red_light);}@Override public void onRefresh() {    new Handler().postDelayed(new Runnable() {        @Override public void run() {            swipeLayout.setRefreshing(false);        }    }, 5000);}

A nice and simple tutorial can be found in this blog.