Android - Show/Hide ActionBar when scrolling ListView, ScrollView,...

    With first appearance at Android 3.0, ActionBar is a window feature that identifies the user location, and provides user actions and navigation modes. Using the action bar offers your users a familiar interface across applications that the system gracefully adapts for different screen configurations. Developer can make many animations with ActionBar but may be most popular is show/hide it when user scroll screen, application like in fullscreen mode.
    In this post, I would like to introduce a powerful external libary to make this effect, called Android-ObservableScrollView. With it, we can auto show/hide ActionBar quite easily and smoothly, please see this DEMO VIDEO first:

Import libary

    Start a new Android project, in this example, I use min-sdk is 15. Afer that, in order to use this libary, open local build.gradle file (often locate in 'app' module) and add this dependency:
compile 'com.github.ksoichiro:android-observablescrollview:1.6.0'

Declaring layouts

    Libary provides us a lot of subclass of ListView, ScrollView, WebView. So, to making this trick, use these offered classes (ObservableListView, ObservableScrollView, ObservableWebView,...) in our layouts:

Programmatically Code

    Each of these activities must implement ObservableScrollViewCallbacks interface. We set show/hide ActionBar when scrolling in onUpOrCancelMotionEvent() method:
    @Override
    public void onUpOrCancelMotionEvent(ScrollState scrollState) {
        ActionBar ab = getSupportActionBar();
        if (ab == null) {
            return;
        }
        if (scrollState == ScrollState.UP) {
            if (ab.isShowing()) {
                ab.hide();
            }
        } else if (scrollState == ScrollState.DOWN) {
            if (!ab.isShowing()) {
                ab.show();
            }
        }
    }
    In activity which contain a ListView, I read a text file from Assets and save strings to ArrayList to make it's data. Full code for this activity is below (onDownMotionEvent(), onScrollChanged() are also belong to ObservableScrollViewCallbacks interface):
package devexchanges.info.autohideactionbar;

import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
import android.widget.AbsListView;
import android.widget.ArrayAdapter;

import com.github.ksoichiro.android.observablescrollview.ObservableListView;
import com.github.ksoichiro.android.observablescrollview.ObservableScrollViewCallbacks;
import com.github.ksoichiro.android.observablescrollview.ScrollState;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;

public class ListViewActivity extends AppCompatActivity implements ObservableScrollViewCallbacks {

    private ObservableListView listView;
    private ArrayList<String> friends;
    private ArrayAdapter<String> adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_listview);

        friends = new ArrayList<>();
        listView = (ObservableListView) findViewById(R.id.list);
        listView.setScrollViewCallbacks(this);

        readAssets();
        setListViewAdapter();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    private void readAssets() {
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(
                    new InputStreamReader(getAssets().open("friendslist.txt"), "UTF-8"));

            // do reading, usually loop until end of file reading
            String mLine = reader.readLine();
            while (mLine != null) {
                mLine = reader.readLine();
                friends.add(mLine);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void setListViewAdapter() {
        adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, friends);
        listView.setAdapter(adapter);
    }

    @Override
    public void onScrollChanged(int scrollY, boolean firstScroll, boolean dragging) {
    }

    @Override
    public void onDownMotionEvent() {
    }

    @Override
    public void onUpOrCancelMotionEvent(ScrollState scrollState) {
        ActionBar ab = getSupportActionBar();
        if (ab == null) {
            return;
        }
        if (scrollState == ScrollState.UP) {
            if (ab.isShowing()) {
                ab.hide();
            }
        } else if (scrollState == ScrollState.DOWN) {
            if (!ab.isShowing()) {
                ab.show();
            }
        }
    }
}
    After running, this screen will be like this output:

    With similar steps above, we create a activity with a ScrollView with this effect:
package devexchanges.info.autohideactionbar;

import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;

import com.github.ksoichiro.android.observablescrollview.ObservableScrollView;
import com.github.ksoichiro.android.observablescrollview.ObservableScrollViewCallbacks;
import com.github.ksoichiro.android.observablescrollview.ScrollState;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class ScrollViewActivity extends AppCompatActivity implements ObservableScrollViewCallbacks {

    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_scroll);

        ObservableScrollView scrollView = (ObservableScrollView) findViewById(R.id.scroll);
        textView = (TextView)findViewById(R.id.text);

        scrollView.setScrollViewCallbacks(this);
        textView.setText(readAssets());

    }

    private String readAssets() {
        String loremString = "";
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(
                    new InputStreamReader(getAssets().open("loremipsum.txt"), "UTF-8"));

            String mLine = reader.readLine();
            while (mLine != null) {
                mLine = reader.readLine();
                loremString += mLine;
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return loremString;
    }

    @Override
    public void onScrollChanged(int scrollY, boolean firstScroll, boolean dragging) {
    }

    @Override
    public void onDownMotionEvent() {
    }

    @Override
    public void onUpOrCancelMotionEvent(ScrollState scrollState) {
        ActionBar ab = getSupportActionBar();
        if (ab == null) {
            return;
        }
        if (scrollState == ScrollState.UP) {
            if (ab.isShowing()) {
                ab.hide();
            }
        } else if (scrollState == ScrollState.DOWN) {
            if (!ab.isShowing()) {
                ab.show();
            }
        }
    }
}
     And a WebViewActivity, in this, customizing an own WebViewClient to make WebView more "friendly":
package devexchanges.info.autohideactionbar;

import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ProgressBar;

import com.github.ksoichiro.android.observablescrollview.ObservableScrollViewCallbacks;
import com.github.ksoichiro.android.observablescrollview.ObservableWebView;
import com.github.ksoichiro.android.observablescrollview.ScrollState;

/**
 */
public class WebViewActivity extends AppCompatActivity implements ObservableScrollViewCallbacks {

    private ObservableWebView webView;
    private ProgressBar progressBar;

    @SuppressLint("SetJavaScriptEnabled")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_web);

        webView = (ObservableWebView) findViewById(R.id.web);
        progressBar = (ProgressBar) findViewById(R.id.loading);
        webView.setScrollViewCallbacks(this);

        webView.getSettings().setJavaScriptEnabled(true); // enable javascript
        webView.setWebViewClient(new MyWebViewClient());
        webView.loadUrl("http://www.devexchanges.info/");
    }

    @Override
    public void onScrollChanged(int scrollY, boolean firstScroll, boolean dragging) {
    }

    @Override
    public void onDownMotionEvent() {
    }

    @Override
    public void onUpOrCancelMotionEvent(ScrollState scrollState) {
        ActionBar ab = getSupportActionBar();
        if (ab == null) {
            return;
        }
        if (scrollState == ScrollState.UP) {
            if (ab.isShowing()) {
                ab.hide();
            }
        } else if (scrollState == ScrollState.DOWN) {
            if (!ab.isShowing()) {
                ab.show();
            }
        }
    }

    private class MyWebViewClient extends WebViewClient {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            view.loadUrl(url);
            return true;
        }

        @Override
        public void onPageFinished(WebView view, String url) {
            progressBar.setVisibility(View.GONE);
            WebViewActivity.this.progressBar.setProgress(100);
            super.onPageFinished(view, url);
        }

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            WebViewActivity.this.progressBar.setProgress(0);
            super.onPageStarted(view, url, favicon);
        }
    }
}
    Over here, our project have almost complete. Final step is provide an activity to redirect to each screen, it will launch when app start, code for this main activity is so simple like this:
package devexchanges.info.autohideactionbar;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        View textListView = findViewById(R.id.txt_list);
        View textWebView = findViewById(R.id.txt_web);
        View textScrollView = findViewById(R.id.txt_scroll);

        // set event handling for TextViews
        // go to other Activity when each item was clicked 
        textListView.setOnClickListener(onClickListener(ListViewActivity.class));
        textScrollView.setOnClickListener(onClickListener(ScrollViewActivity.class));
        textWebView.setOnClickListener(onClickListener(WebViewActivity.class));
    }

    private View.OnClickListener onClickListener(final Class c) {
        return new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                goToActivity(c);
            }
        };
    }

    private void goToActivity(Class c) {
        Intent intent = new Intent(this, c);
        startActivity(intent);
    }
}
    It's layout (only include 3 TextViews):
    This main screen when app run:

Conclusion & References

    In this post, I've present the simple way to show/hide ActionBar with animation by using an external libary. Moreover, this trick is only a small features of this huge/powerful library. At it's Github page, you can find out that many other useful features can apply to make your app more flexible (Sticky header ListView, ViewPager with Tabs, parallax ActionBar,...).
- Libary project on @Githubhttps://github.com/ksoichiro/Android-ObservableScrollView
- If you can read Japanese, visit author blog to get more information! :)


Share


Previous post
« Prev Post
Next post
Next Post »