之前做过一个horizontalScrollView+viewpage的级联滑动,总结如下:
- 既然我们有了recycleView为何不用?
- recycleview可以在horizontalScrollView的基础上增加多行,实现更多变更多定制化的效果。
我们都知道recycleview有三种效果:
- inearLayoutManager 线形管理器,支持横向、纵向。
- GridLayoutManager 网格布局管理器
- 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