赞
踩
前两天实验了一个效果,demo是速卖通app AliExpress 商品详情页面,上滑覆盖顶部ViewPager。
不过在实现的效果略有不同,我设定的是ViewPager是固定页面顶部的,没有不同步滑动的效果。
如果想实现不同步滑动的效果,可以设置viewpager的滑动速度是原来速度的1/3或者其他。
第一步,重写ScrollView,实现三个构造方法,重写onScrollChanged()这个方法。
第二步,创建接口OnScrolledListener:
- public interface OnScrolledListener {
-
- /**
- * ScrollView的滑动事件的回调监听
- * @param y ScrollView的滑动纵坐标
- */
- void scroll(int y);
- }
第三步,在重写的ScrollView中初始化OnScrolledListener接口:
- private OnScrolledListener listener = new OnScrolledListener() {
- @Override
- public void scroll(int y) {
-
- }
- };
- @Override
- protected void onScrollChanged(int l, int t, int oldl, int oldt) {
- listener.scroll(getScrollY());
- super.onScrollChanged(l, t, oldl, oldt);
- }
- public void setListener(OnScrolledListener listener){
- this.listener = listener;
- }
- <com.ximoon.corveredtitlescrollview.MyScrollView
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- xmlns:tools="http://schemas.android.com/tools"
- android:id="@+id/msv"
- xmlns:android="http://schemas.android.com/apk/res/android">
-
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
-
- <android.support.v4.view.ViewPager
- android:id="@+id/vp"
- android:layout_width="match_parent"
- android:layout_height="200dp"></android.support.v4.view.ViewPager>
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="我是标题"
- android:textSize="20sp"
- android:layout_alignParentLeft="true"
- android:layout_marginLeft="20dp"
- android:layout_alignBottom="@id/vp"/>
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="700dp"
- android:layout_below="@id/vp"
- android:background="@android:color/holo_red_dark"></LinearLayout>
-
- </RelativeLayout>
-
- </com.ximoon.corveredtitlescrollview.MyScrollView>
MyScrollView是刚刚重写的ScrollView,里面包含一个子控件RelativeLayout
(ScrollView的特性,最多含有一个子控件)。
RelativeLayout里面包含三部分,一个就是顶部的ViewPager。
还有一个是TextView,随着滑动,在ViewPager上显示,最后是LinearLayout,是整个滑动区域。
第七步,在Activity内找到控件,并设置回调监听对象,重写滑动事件:
- private MyScrollView myScrollView = null;
- private ViewPager mViewPager = null;
- /** 屏幕宽度*/
- public static int DISPLAYW = 0;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- // 测量屏幕的宽度
- DISPLAYW = getResources().getDisplayMetrics().widthPixels;
-
- setContentView(R.layout.activity_main);
-
- myScrollView = (MyScrollView) findViewById(R.id.msv);
- mViewPager = (ViewPager) findViewById(R.id.vp);
-
- // 设置viewpager的宽高一致,为屏幕的宽度(因为嵌套在scrollview中,所以必须重新设置高度)
- mViewPager.setLayoutParams(new RelativeLayout.LayoutParams(DISPLAYW,DISPLAYW));
-
- myScrollView.setListener(new OnScrolledListener() {
- @Override
- public void scroll(int y) {
- // 若滑动坐标的绝对值即滑动距离不超过viewpager的高度的时候,设置viewpager回滚位置(相当于viewpager滑动的距离是ScrollView滑动距离的相反值,以保持viewpager固定)
- // if ((y < 0 && -y <= DISPLAYW) || (y > 0 && y <= DISPLAYW)) {
- // 因为viewpager是可横向滚动的控件,所以需要按屏计算它的目前滚动宽度,滚动纵坐标即ScrollView的滚动纵坐标的相反值
- mViewPager.scrollTo(mViewPager.getCurrentItem() * DISPLAYW, -y); // 此处存在一个问题 滑屏到中间位置的时候再滑动viewpager,会导致图片位置出错,可重写viewpager的滑动纠错
- // }
-
- }
- });
- mViewPager.setAdapter(new ImageAdapter());
- mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
- @Override
- public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
- // 当viewpager滑动的时候解决viewpager恢复相对于scrollview的坐标造成的显示失误
- myScrollView.scrollTo(0,0);
- }
-
- @Override
- public void onPageSelected(int position) {
-
- }
-
- @Override
- public void onPageScrollStateChanged(int state) {
-
- }
- });
- }
而这句代码:
mViewPager.scrollTo(mViewPager.getCurrentItem() * DISPLAYW, -y);
正常情况下,myScrollView滑动多少距离,myScrollView 内部的控件也应该随之滑动多少距离。
但是由于在ScrollView内,所以获得的相对滑动坐标即getScrollY()为0。
这个时候,我们需要手动设置mViewPager相对myScrollView的相对滑动纵坐标。
意思表示,当myScrollView向上或者向下滑动到y坐标的时候,mViewPager则向相反方向滑动相同的距离。
所以滑动纵坐标为-y。参数y是通过myScrollView.getScrollY()获得的mScrollY返回过来,
所以通过scrollTo()方法就可以滑动到坐标指示位置。
横坐标就更简单了,因为mViewPager相当于一个横向的ScrollView,
所以它也有一个滑动坐标,但是是横向的,每一屏都对应着不同的横坐标。
当myScrollView滑动的时候,如果设置滑动横坐标为0。
即mViewPager.scrollTo(0,-y),那么造成的后果就是当mViewPager不在position=0的位置的时候,
myScrollView的滑动会促使mViewPager回到position为0的位置。
添加mViewPager滑动的监听事件,并在onPageScrolled()方法中设置myScrollView的滑动事件。
此方法可另类解决当myScrollView滑动到mViewPager的中间位置时再滑动myScrollView,
造成mViewPager的相对滑动纵坐标出现问题,
导致mViewPager的底部出现在可滑动区域的上方,而mViewPager只显示下半部分的错误。
github地址:点击打开链接
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。