安卓手把手教你实现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

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!
以下是 Android 中结合 ViewPager 和 RecyclerView 实现横向翻页无限循环的代码示例: 1. 在布局文件中定义 ViewPager 和 RecyclerView: ```xml <androidx.viewpager.widget.ViewPager android:id="@+id/view_pager" android:layout_width="match_parent" android:layout_height="200dp" /> <androidx.recyclerview.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="wrap_content" /> ``` 2. 在 Activity 或 Fragment 中初始化 ViewPager 和 RecyclerView: ```java private ViewPager mViewPager; private MyPagerAdapter mPagerAdapter; private RecyclerView mRecyclerView; private LinearLayoutManager mLinearLayoutManager; private List<MyData> mDataList; private MyAdapter mAdapter; private int mCurrentPosition = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mViewPager = findViewById(R.id.view_pager); mRecyclerView = findViewById(R.id.recycler_view); // 设置 ViewPager 适配器 mPagerAdapter = new MyPagerAdapter(this); mViewPager.setAdapter(mPagerAdapter); // 初始化数据 mDataList = new ArrayList<>(); for (int i = 0; i < 20; i++) { mDataList.add(new MyData("Item " + i)); } // 初始化适配器 mAdapter = new MyAdapter(this, mDataList); // 初始化布局管理器 mLinearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false); mRecyclerView.setLayoutManager(mLinearLayoutManager); // 设置适配器 mRecyclerView.setAdapter(mAdapter); // 监听 RecyclerView 滚动事件 mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); // 计算当前显示在 ViewPager 中的位置 int position = mLinearLayoutManager.findFirstCompletelyVisibleItemPosition(); if (position != RecyclerView.NO_POSITION && position != mCurrentPosition) { mCurrentPosition = position; mViewPager.setCurrentItem(mCurrentPosition, false); } } }); // 监听 ViewPager 页面切换事件 mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { // 设置 RecyclerView 滚动到对应位置 mRecyclerView.smoothScrollToPosition(position); mCurrentPosition = position; } @Override public void onPageScrollStateChanged(int state) { } }); // 初始化第一个页面 mViewPager.setCurrentItem(mCurrentPosition); mRecyclerView.scrollToPosition(mCurrentPosition); } ``` 3. 编写 ViewPager 和 RecyclerView 的适配器和数据类: ```java public class MyPagerAdapter extends PagerAdapter { private Context mContext; public MyPagerAdapter(Context context) { mContext = context; } @Override public int getCount() { return 20; } @Override public boolean isViewFromObject(View view, Object object) { return view == object; } @Override public Object instantiateItem(ViewGroup container, int position) { View view = LayoutInflater.from(mContext).inflate(R.layout.item_my_pager, container, false); TextView textView = view.findViewById(R.id.tv_text); textView.setText("Page " + position); container.addView(view); return view; } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View) object); } } public class MyAdapter extends RecyclerView.Adapter<MyViewHolder> { private Context mContext; private List<MyData> mDataList; public MyAdapter(Context context, List<MyData> dataList) { mContext = context; mDataList = dataList; } @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(mContext).inflate(R.layout.item_my_data, parent, false); return new MyViewHolder(view); } @Override public void onBindViewHolder(MyViewHolder holder, int position) { MyData data = mDataList.get(position); holder.mTextView.setText(data.getText()); } @Override public int getItemCount() { return mDataList.size(); } } public class MyViewHolder extends RecyclerView.ViewHolder { public TextView mTextView; public MyViewHolder(View itemView) { super(itemView); mTextView = itemView.findViewById(R.id.tv_text); } } public class MyData { private String mText; public MyData(String text) { mText = text; } public String getText() { return mText; } } ``` 在这个示例中,当用户滑动 RecyclerView 时,会自动滑动到对应的 ViewPager 页面,当用户滑动 ViewPager 页面时,会自动滑动到对应的 RecyclerView 列表项,实现横向翻页无限循环的效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

q2nAmor

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值