This tutorial describes how to show effect when list is scrolling up and down. Hiding Toolbar and any other views when list is scrolling down and showing it again when its scrolling up.
In this tutorial we are using RecyclerView and Tollbar to achieve this effect as we see in Google play. We will add list header on top of the list.
To complete this task follow below points.
1) - First of all we will create a new project in Android studio and add some necessary libraries.
compile "com.android.support:recyclerview-v7:21.0.0"
compile 'com.android.support:cardview-v7:21.0.3'
2)- We will define styles.xml so that our app can use Material Theme .
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
</style>
3)- Next create a activity_main.xml for our MainActivity class.
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"/>
<LinearLayout
android:id="@+id/toolbarContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"/>
<include layout="@layout/tabs_layout"/>
</LinearLayout>
<ImageButton
android:id="@+id/fabButton"
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_gravity="bottom|right"
android:layout_marginBottom="16dp"
android:layout_marginRight="16dp"
android:visibility="invisible"
android:background="@drawable/fab_background"
android:src="@mipmap/ic_favorite_outline_white_24dp"
/>
</FrameLayout>
- Its very simple layout with RecyclerView, Toolbar and include tab_layout .We put them in a FrameLayout therefore Toolbar needs to be overlayed on RecyclerView. If we don't do this,there will be an empty space above the list when hide the toolbar.
4) Now create MainActivity class code.
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.widget.LinearLayout;
import java.util.ArrayList;
import java.util.List;
/**
* Created by arvindkumar on 5/6/15.
*/
public class MainActivity extends ActionBarActivity {
private LinearLayout mToolbarContainer;
private int mToolbarHeight;
@Override
protected void onCreate(Bundle savedInstanceState) {
setTheme(R.style.AppTheme);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mToolbarContainer = (LinearLayout) findViewById(R.id.toolbarContainer);
initToolbar();
initRecyclerView();
}
private void initToolbar() {
Toolbar mToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
setTitle(getString(R.string.app_name));
mToolbar.setTitleTextColor(getResources().getColor(android.R.color.white));
mToolbarHeight = Utils.getToolbarHeight(this);
}
private void initRecyclerView() {
final RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
int paddingTop = Utils.getToolbarHeight(MainActivity.this) + Utils.getTabsHeight(MainActivity.this);
recyclerView.setPadding(recyclerView.getPaddingLeft(), paddingTop, recyclerView.getPaddingRight(), recyclerView.getPaddingBottom());
recyclerView.setLayoutManager(new LinearLayoutManager(this));
ViewAdapter recyclerAdapter = new ViewAdapter(createItemList());
recyclerView.setAdapter(recyclerAdapter);
recyclerView.setOnScrollListener(new ListScrollListener(this) {
public void onMoved(int distance) {
mToolbarContainer.setTranslationY(-distance);
}
@Override
public void onShow() {
mToolbarContainer.animate().translationY(0).setInterpolator(new DecelerateInterpolator(2)).start();
}
@Override
public void onHide() {
mToolbarContainer.animate().translationY(-mToolbarHeight).setInterpolator(new AccelerateInterpolator(2)).start();
}
});
}
private List<String> createItemList() {
List<String> itemList = new ArrayList<>();
for(int i=0;i<20;i++) {
itemList.add("Item "+i);
}
return itemList;
}
}
5)- we have to add a recycler_item.xml. layout for our list items .
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layou_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="8dp"
card_view:cardCornerRadius="4dp">
<TextView
android:id="@+id/itemTextView"
android:layout_width="match_parent"
android:layout_height="?attr/listPreferredItemHeight"
android:gravity="center_vertical"
android:padding="8dp"
android:text="djfdksjfdsfj"
style="@style/Base.TextAppearance.AppCompat.Body2"/>
</android.support.v7.widget.CardView>
6)- Now we will create a ViewHolder class which hold the view what have defined in recycle_item.xml file.Our
list using only text so its very easy.
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.TextView;
/**
* Created by arvindkumar on 5/6/15.
*/
public class RecyclerItemViewHolder extends RecyclerView.ViewHolder {
private final TextView mItemTextView;
public RecyclerItemViewHolder(final View parent, TextView itemTextView) {
super(parent);
mItemTextView = itemTextView;
}
public static RecyclerItemViewHolder newInstance(View parent) {
TextView itemTextView = (TextView) parent.findViewById(R.id.itemTextView);
return new RecyclerItemViewHolder(parent, itemTextView);
}
public void setItemText(CharSequence text) {
mItemTextView.setText(text);
}
}
7)- We will create a ViewAdapter class ViewAdapter.
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.List;
/**
* Created by arvindkumar on 5/6/15.
*/
public class ViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
//added view types
private static final int TYPE_HEADER = 2;
private static final int TYPE_ITEM = 1;
private List<String> mItemList;
public ViewAdapter(List<String> itemList) {
mItemList = itemList;
}
//modified creating viewholder, so it creates appropriate holder for a given viewType
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Context context = parent.getContext();
if (viewType == TYPE_ITEM) {
final View view = LayoutInflater.from(context).inflate(R.layout.recycler_item, parent, false);
return RecyclerItemViewHolder.newInstance(view);
} else if (viewType == TYPE_HEADER) {
final View view = LayoutInflater.from(context).inflate(R.layout.recycler_header, parent, false);
return new RecyclerViewHolder(view);
}
throw new RuntimeException("There is no type that matches the type " + viewType + " + make sure your using types correctly");
}
//modifed ViewHolder binding so it binds a correct View for the Adapter
@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
if (!isPositionHeader(position)) {
RecyclerItemViewHolder holder = (RecyclerItemViewHolder) viewHolder;
String itemText = mItemList.get(position - 1); // we are taking header in to account so all of our items are correctly positioned
holder.setItemText(itemText);
}
}
//our old getItemCount()
public int getBasicItemCount() {
return mItemList == null ? 0 : mItemList.size();
}
//our new getItemCount() that includes header View
@Override
public int getItemCount() {
return getBasicItemCount() + 1; // header
}
//added a method that returns viewType for a given position
@Override
public int getItemViewType(int position) {
if (isPositionHeader(position)) {
return TYPE_HEADER;
}
return TYPE_ITEM;
}
//added a method to check if given position is a header
private boolean isPositionHeader(int position) {
return position == 0;
}
}
8)- Now lets create a layout and ViewHolder for the header view.
<?xml version="1.0" encoding="utf-8"?>
<View xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"/>
9)- Create RecyclerHeaderViewHolder class- RecyclerViewHolder
import android.support.v7.widget.RecyclerView;
import android.view.View;
/**
* Created by arvindkumar on 5/6/15.
*/
public class RecyclerViewHolder extends RecyclerView.ViewHolder {
public RecyclerViewHolder(View itemView) {
super(itemView);
}
}
10)- Showing/hiding views when list is scrolling.
To achieve this we will create only one more class- ListScrollListener for RecyclerView.
import android.content.Context;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
/**
* Created by arvindkumar on 5/6/15.
*/
public abstract class ListScrollListener extends RecyclerView.OnScrollListener {
private int scrolledDistance = 0;
private boolean controlsVisible = true;
private static final float HIDE_THRESHOLD = 10;
private static final float SHOW_THRESHOLD = 70;
private int mToolbarOffset = 0;
private boolean mControlsVisible = true;
private int mToolbarHeight;
private int mTotalScrolledDistance;
public ListScrollListener(Context context) {
mToolbarHeight = Utils.getToolbarHeight(context);
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int firstVisibleItem = ((LinearLayoutManager) recyclerView.getLayoutManager()).findFirstVisibleItemPosition();
//show views if first item is first visible position and views are hidden
if (firstVisibleItem == 0) {
if(!controlsVisible) {
onShow();
controlsVisible = true;
}
} else {
if (scrolledDistance > HIDE_THRESHOLD && controlsVisible) {
onHide();
controlsVisible = false;
scrolledDistance = 0;
} else if (scrolledDistance < -HIDE_THRESHOLD && !controlsVisible) {
onShow();
controlsVisible = true;
scrolledDistance = 0;
}
}
if((controlsVisible && dy>0) || (!controlsVisible && dy<0)) {
scrolledDistance += dy;
}
mTotalScrolledDistance += dy;
}
public abstract void onHide();
public abstract void onShow();
}
11)- Create one more class Utils that return height of toolBar and tabsHeight .
import android.content.Context;
import android.content.res.TypedArray;
/**
* Created by arvindkumar on 5/6/15.
*/
public class Utils {
public static int getToolbarHeight(Context context) {
final TypedArray styledAttributes = context.getTheme().obtainStyledAttributes(
new int[]{R.attr.actionBarSize});
int toolbarHeight = (int) styledAttributes.getDimension(0, 0);
styledAttributes.recycle();
return toolbarHeight;
}
public static int getTabsHeight(Context context) {
return (int) context.getResources().getDimension(R.dimen.tabsHeight);
}
}
Note- In AndroidManifest.xml file we have defined to MainActivity as launcher Activity
0 Comment(s)