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
compile 'com.github.ksoichiro:android-observablescrollview:1.6.0'
Declaring layouts
Programmatically Code
@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
- Libary project on @Github: https://github.com/ksoichiro/Android-ObservableScrollView
- If you can read Japanese, visit author blog to get more information! :)