返回 登录
0

安卓手把手教你实现RecycleView横向和ViewPage的级联滑动

之前做过一个horizontalScrollView+viewpage的级联滑动,总结如下:

  1. 既然我们有了recycleView为何不用?
  2. recycleview可以在horizontalScrollView的基础上增加多行,实现更多变更多定制化的效果。

我们都知道recycleview有三种效果:

  1. inearLayoutManager 线形管理器,支持横向、纵向。
  2. GridLayoutManager 网格布局管理器
  3. StaggeredGridLayoutManager 瀑布流式布局管理器

(还不会recycleview基本使用的自行补粮:
http://blog.csdn.net/lmj623565791/article/details/45059587),
首先看一下我们要做什么事情:

  • 监听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分钟看我上一篇文章就秒懂。

http://blog.csdn.net/u012534831/article/details/51511240

看一下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


QQ:1003077897
github:https://github.com/qht1003077897

评论