Ẩn/Hiện thanh toolbar khi scroll trên recycle view
Để control được việc ẩn / hiện của toolbar hoặc bất kì một view nào trong quá trình scroll recycleview thì việc đầu tiên chúng ta cần làm là tạo một recycle view và một thanh toolbar đơn giản. Đầu tiên là việc import thư viện: ..... dataBinding { enabled = true } ..... ...
Để control được việc ẩn / hiện của toolbar hoặc bất kì một view nào trong quá trình scroll recycleview thì việc đầu tiên chúng ta cần làm là tạo một recycle view và một thanh toolbar đơn giản. Đầu tiên là việc import thư viện:
..... dataBinding { enabled = true } .....
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) compile 'com.android.support:appcompat-v7:25.2.0' compile 'com.android.support:recyclerview-v7:25.1.1' compile 'com.android.support:cardview-v7:25.2.0' testCompile 'junit:junit:4.12' }
Tạo adapter cho recycleview Adapter.java
public class Adapter extends RecyclerView.Adapter<Adapter.ViewHolder> { private String[] mItems; private LayoutInflater mLayoutInflater; public Adapter(String[] items) { mItems = items; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (mLayoutInflater == null) mLayoutInflater = LayoutInflater.from(parent.getContext()); ItemRecycleViewBinding binding = ItemRecycleViewBinding.inflate(mLayoutInflater, parent, false); return new Adapter.ViewHolder(binding); } @Override public void onBindViewHolder(ViewHolder holder, int position) { holder.bind(position); } @Override public int getItemCount() { return mItems == null ? 0 : mItems.length; } public class ViewHolder extends RecyclerView.ViewHolder { private ItemRecycleViewBinding mBinding; public ViewHolder(ItemRecycleViewBinding binding) { super(binding.getRoot()); mBinding = binding; } private void bind(int pos) { mBinding.setText(mItems[pos]); mBinding.executePendingBindings(); } } }
Custom việc init Recycleview bằng databinding BindingUtil.java
public class BindingUtil { @BindingAdapter({"adapter", "context"}) public static void initRecycleview(RecyclerView recyclerView, Adapter adapter, AppCompatActivity activity) { if (recyclerView == null || adapter == null) return; recyclerView.setLayoutManager(new LinearLayoutManager(activity)); recyclerView.setAdapter(adapter); } }
Tạo layout cho MainActivity.java activity_main.xml
<layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:bind="http://schemas.android.com/apk/res-auto"> <data> <variable name="activity" type="beemusic.framgia.com.controlscrollrecycleview.MainActivity"/> </data> <FrameLayout android:layout_awidth="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.RecyclerView android:id="@+id/recyclerView" android:layout_awidth="match_parent" android:layout_height="match_parent" bind:adapter="@{activity.adapter}" bind:context="@{activity}"/> <android.support.v7.widget.Toolbar android:layout_awidth="match_parent" android:layout_height="?attr/actionBarSize" android:background="@color/colorPrimary" android:title="@string/app_name"/> </FrameLayout> </layout>
Tạo layout item_recycle_view.xml
<layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <data> <variable name="text" type="String"/> </data> <android.support.v7.widget.CardView android:layout_awidth="match_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_margin="8dp" app:cardCornerRadius="4dp" app:cardElevation="@dimen/dp_2"> <TextView android:layout_awidth="match_parent" android:layout_height="?attr/listPreferredItemHeight" android:gravity="center" android:text="@{text}"/> </android.support.v7.widget.CardView> </layout>
Để control được việc ẩn hiện thanh toolbar, ta viết lại lớp RecyclerView.OnScrollListener ControlScrollListener.java
public abstract class ControlScrollListener extends RecyclerView.OnScrollListener { private static final int HIDE_THRESHOLD = 20; private int mScrolledDistance = 0; private boolean mVisible = true; @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 (!mVisible) { onShow(); mVisible = true; } } else { if (mScrolledDistance > HIDE_THRESHOLD && mVisible) { onHide(); mVisible = false; mScrolledDistance = 0; } else if (mScrolledDistance < -HIDE_THRESHOLD && !mVisible) { onShow(); mVisible = true; mScrolledDistance = 0; } } if ((mVisible && dy > 0) || (!mVisible && dy < 0)) { mScrolledDistance += dy; } } public abstract void onHide(); public abstract void onShow(); }
Bây giờ, trong file BindingUtil.java, chúng ta sẽ tạo callback để control bằng việc khởi tạo một đối tượng ControlScrollListener thực sự cho recycleview.
@BindingAdapter({"adapter", "context", "toolbar"}) public static void initRecycleview(RecyclerView recyclerView, Adapter adapter, AppCompatActivity activity, final Toolbar toolbar) { if (recyclerView == null || adapter == null) return; recyclerView.setLayoutManager(new LinearLayoutManager(activity)); recyclerView.setAdapter(adapter); recyclerView.setOnScrollListener(new ControlScrollListener() { @Override public void onHide() { toolbar.animate().translationY(-toolbar.getHeight()) .setInterpolator(new AccelerateInterpolator(2)); } @Override public void onShow() { toolbar.animate().translationY(0).setInterpolator(new DecelerateInterpolator(2)); } }); }
Vậy là chúng ta đã hoàn tất project. Các bạn có thể tham khảo source code tại đây