安卓手把手教你實現RecycleView橫向和ViewPage的級聯滑動
之前做過一個horizontalScrollView+viewpage的級聯滑動,總結如下:
- 既然我們有了recycleView為何不用?
- recycleview可以在horizontalScrollView的基礎上增加多行,實現更多變更多定製化的效果。
我們都知道recycleview有三種效果:
- inearLayoutManager 線形管理器,支援橫向、縱向。
- GridLayoutManager 網格佈局管理器
- StaggeredGridLayoutManager 瀑布流式佈局管理器
- 監聽recycleview的item點選事件
- 監聽Viewpage的變化
- recycleview實現橫向的gridview
- 根據螢幕的寬度固定每個item的寬度
- 滑動viewpage,recycleview跟著滑動到對應item
點選recycleview的對應item,Viewpage跟著滑動到對應頁
開始之前我們看一下效果:
看一下activity的佈局:
<com.example.recycleviewtest.PercentLinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v4.view.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="200dp"/>
<com.example.recycleviewtest .PercentLinearLayout
android:id="@+id/linearLayout"
android:layout_width="500dp"
android:layout_height="200dp"
app:layout_heightPercent="30%h"
app:layout_widthPercent="100%w">
<android.support.v7.widget.RecyclerView
android:id="@+id/id_recyclerview"
android:divider="#ffff0000"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</com.example.recycleviewtest.PercentLinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<ImageView
android:id="@+id/imageview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher"
android:onClick="imageclick"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher"
android:tint="#ffcdd2"/>
</LinearLayout>
</com.example.recycleviewtest.PercentLinearLayout>
這兒用到了百分比佈局,花2分鐘看我上一篇文章就秒懂。
看一下oncreate的程式碼
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView=(ImageView)findViewById(R.id.imageview);
viewPager = (ViewPager) findViewById(R.id.viewPager);
initData();
mRecyclerView = (RecyclerView) findViewById(R.id.id_recyclerview);
// 採用瀑布流並設定4行水平滾動
StaggeredGridLayoutManager mStaggeredLayoutManager= new StaggeredGridLayoutManager(4,
StaggeredGridLayoutManager.HORIZONTAL);
mRecyclerView.setLayoutManager(mStaggeredLayoutManager);
mRecyclerView.setAdapter(mAdapter = new HomeAdapter(MainActivity.this,mDatas));
mRecyclerView.addItemDecoration(new DividerGridItemDecoration(this));//每一列新增分割線
getDispaly(mRecyclerView);//獲取螢幕尺寸,目的是為了等分螢幕寬度
mmAdapter = new MyPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(mmAdapter);
viewPager.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageSelected(int arg0) {
mRecyclerView.smoothScrollToPosition(arg0*4+3);
}
/** 此方法在滑動ViewPager的時候一直被呼叫,頁面在滑動過程中不停觸發該方法:position”按照api的解釋是“目前顯示在螢幕上的第一個頁面,只要positionOffset不為0,那麼他後面的頁面同樣是可見的
第一頁~第二頁
position = 0
positionOffset 0.0 ~ 1.0
第二頁~第一頁
position = 0
positionOffset 1.0 ~ 0.0
通過上面的結果,由於position的值在切換第一頁和第二頁的時候沒有變化,就可以同過position+1得到右邊的view,通過position拿到左邊的view 不論是滑動還是靜止,他表示的都是螢幕左邊的頁
positionOffset 移量的百分比
positionOffsetPixels 偏移量的數值*/
@Override
public void onPageScrolled(int position, float offest, int offestPixes) {
}
/**當頁面的滑動狀態改變時該方法會被觸發,頁面的滑動狀態有3個:0表示什麼都不做,1表示開始滑動,2表示結束滑動*/
@Override
public void onPageScrollStateChanged(int arg0) {
}
});
mAdapter.setOnItemClickerListener(new OnItemClickerListener() {
@Override
public void OnItemClicker(View view, int position) {
// TODO Auto-generated method stub
//只能去點選第一行的item,即4的倍數
if(position%4==0){
viewPager.setCurrentItem(position/4, true); //item從0-31,對應著viewpage的0-7頁,所以說一列item對應一頁
Toast.makeText(MainActivity.this, "你點選了"+position, Toast.LENGTH_SHORT).show();
}
else{return;}
}
});
}
- viewPager.setCurrentItem(position/4, true); 改變viewpage顯示頁面。
計算偏移量這兒我用了一個小的投機取巧的方式( mRecyclerView.smoothScrollToPosition(arg0*4+3),我沒有使用計算得出的偏移量來設定滾動,而是根據這個方法的特性顯示出下一列的最後一個數字(本應該是第一個),這樣下一列就完全顯示出來從而達到可操控的滾動
注:特性是指scrolltoposition這個方法會把你想要移動的item放到你能看見的地方,但是它不會管放到哪個位置,能讓你看見就行,一般在末尾。
:下面我舉例子解釋一下:
比如我滑到了第六頁,準備顯示第六行,也即為數字為20的item,因為ScrollToPosition這個方法只會把20顯示出來,但是不管位置,所以它顯示出來的效果是這樣的:20跑到了19的下面,本應該是在17的右邊的。
OK,那麼我的方法就是把23顯示到目前20的位置,這樣20就被頂到17的位置了,在視覺上就實現了列的左平移。
- 第二:smoothScrollToPosition是從ScrollToPosition方法切換過來的,(如果不採用smoothScrollToPosition這個方法的話)不平滑滾動的話會出現兩個問題:
一是檢視無法滾動到最左邊,二是當手動去滾動至最左邊的時候item的位置出現錯亂(雖然會自動恢復,但是有明顯的視覺延遲)見下圖樣式:
可以看見,檢視亂了,但是鬆手的話它會自動恢復。
資料就是36個數字
protected void initData()
{
mDatas = new ArrayList<String>();
for (int i = 0; i < 36; i++)
{
mDatas.add("" + i);
}
}
- OK,我們再看一下recycleview的Adapter中bindviewholder的程式碼:
public void onBindViewHolder(final MyViewHolder holder, int position)
{
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
(int)(Constant.displayWidth*0.2),
(int)(Constant.recycleviewHeight*0.25));
holder.itemView.setLayoutParams(params);
holder.tv.setText(mDatas.get(position));
if(onItemClickerListener!=null){
//提供給activity的點選回撥
holder.itemView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
int p=holder.getLayoutPosition();
onItemClickerListener.OnItemClicker(holder.itemView, p);
}
});
}
}
Constant.displayWidth*0.2即為螢幕寬度的1/5,依據螢幕寬度每行5個item。
現在我們梳理一下文章都有哪些內容:
第一:從佈局中我們看出有一個viewpage和一個瀑布流的recycleview。
第二:設定為可滾動的recycleview。並限定每行5個item。
第三:在viewpage的onPageSelected方法裡面計算recycleview的滑動距離。
第四:在recycleview的item點選事件裡面設定viewpage的切換。
基本和我們前面確定的內容一致,寫到這兒只是讓大家瞭解一下基本思路就行了,知道聯動該怎麼去實現,對應什麼方法,歡迎多多交流。下面給出原始碼(eclipse版本的):
csdn下載地址:http://download.csdn.net/detail/u012534831/9539449
git地址:https://github.com/qht1003077897/recycleview-viewpage—-Scroll.git