HorizontalScrollView 实现 ViewPager 可滑动翻页的tab

ViewPager 有很好的翻页效果,长用于图片浏览。今天产品设计了一个 奇葩的需求 ,翻页里边放tab ,并保留点击后的效果。
先看看要实现的效果, 一个两个页面的翻页效果。
这里写图片描述

实现好的效果
这里写图片描述
常用的ViewPager当然可以实现 ,但是 ViewPager 有个弊端,就是有缓存 ,使用起来也是比较麻烦。于是就想到了 scrollView。

想法: HorizontalScrollView,我们改写它的滑动事件。检测 滑动方向和距离。 当设定一个滑动距离,超过这个距离就表示翻页,没有这表示不翻页。翻页距离为一个屏幕宽度。

重点方法:

   @Override
    public boolean onTouchEvent(MotionEvent ev) {
        int action = ev.getAction();
        switch (action) {
            case MotionEvent.ACTION_UP:
                int scrollX = getBaseScrollX();
                //左滑,大于指定距离,移到下一页
                if (scrollX > mScrollX) {

                    baseSmoothScrollTo(mScreenWidth);
                    mBaseScrollX += mScreenWidth;
                    positionSun++;
                    listener.OnClickmoveItem(positionSun);

                    // listener.OnClickmoveItem(1);
                }
                //左滑,不到指定距离,返回原位
                else if (scrollX > 0) {
                     baseSmoothScrollTo(0);
                }
                //右滑,不到指定距离,返回原位
                else if (scrollX > -mScrollX) {
                    baseSmoothScrollTo(0);
                }
                //右滑,大于指定距离,移到下一页
                else {
                    baseSmoothScrollTo(-mScreenWidth);
                    mBaseScrollX -= mScreenWidth;
                    positionSun--;
                    // listener.OnClickmoveItem(0);
                    listener.OnClickmoveItem(positionSun);
                }
                return true;
        }
        return super.onTouchEvent(ev);
    }

完整代码代码



import android.content.Context;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;


/**
 * 滑动翻页效果
 */
public class PageView extends HorizontalScrollView {
    private int mBaseScrollX;//滑动基线。也就是点击并滑动之前的x值,以此值计算相对滑动距离。
    private int mScreenWidth;
    private int mScreenHeight;

    private LinearLayout mContainer;
    private boolean flag;
    private int mPageCount;//页面数量
    private int positionSun = 0;  //  记录当前位置
    private int mScrollX = 100;//滑动多长距离翻页


    public PageView(Context context, AttributeSet attrs) {
        super(context, attrs);

        DisplayMetrics dm = context.getApplicationContext().getResources()
                .getDisplayMetrics();
        mScreenWidth = dm.widthPixels;
        mScreenHeight = dm.heightPixels;
    }

    /**
     * 添加一个页面到最后。
     *
     * @param page
     */
    public void addPage(View page) {
        addPage(page, -1);
    }

    /**
     * 添加一个页面。
     *
     * @param page
     */
    public void addPage(View page, int index) {
        if (!flag) {
            mContainer = (LinearLayout) getChildAt(0);
            flag = true;
        }
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(mScreenWidth, mScreenHeight);
        if (index == -1) {
            mContainer.addView(page, params);
        } else {
            mContainer.addView(page, index, params);
        }

        mPageCount++;
    }

    /**
     * 移除一个页面。
     *
     * @param index
     */
    public void removePage(int index) {
        if (mPageCount < 1) {
            return;
        }
        if (index < 0 || index > mPageCount - 1) {
            return;
        }
        mContainer.removeViewAt(index);
        mPageCount--;
    }


    /**
     * 设置移动距离触发滑动 默认为100
     *
     * @param distance 水平移动的距离
     */
    public void setHorizontalMovingDistance(int distance) {

        if (distance != 0) {
            mScrollX = distance;
        }
    }


    /**
     * 移除所有的页面
     */
    public void removeAllPages() {
        if (mPageCount > 0) {
            mContainer.removeAllViews();
        }
    }

    /**
     * 获取页面数量
     *
     * @return
     */
    public int getPageCount() {
        return mPageCount;
    }

    /**
     * 获取相对滑动位置。由右向左滑动,返回正值;由左向右滑动,返回负值。
     *
     * @return
     */
    private int getBaseScrollX() {
        return getScrollX() - mBaseScrollX;
    }




    /**
     * 使相对于基线移动x距离。
     *
     * @param x x为正值时右移;为负值时左移。
     */
    private void baseSmoothScrollTo(int x) {
        smoothScrollTo(x + mBaseScrollX, 0);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        int action = ev.getAction();
        switch (action) {
            case MotionEvent.ACTION_UP:
                int scrollX = getBaseScrollX();
                //左滑,大于指定距离,移到下一页
                if (scrollX > mScrollX) {

                    baseSmoothScrollTo(mScreenWidth);
                    mBaseScrollX += mScreenWidth;
                    positionSun++;
                    listener.OnClickmoveItem(positionSun);

                    // listener.OnClickmoveItem(1);
                }
                //左滑,不到指定距离,返回原位
                else if (scrollX > 0) {
                     baseSmoothScrollTo(0);
                }
                //右滑,不到指定距离,返回原位
                else if (scrollX > -mScrollX) {
                    baseSmoothScrollTo(0);
                }
                //右滑,大于指定距离,移到下一页
                else {
                    baseSmoothScrollTo(-mScreenWidth);
                    mBaseScrollX -= mScreenWidth;
                    positionSun--;
                    // listener.OnClickmoveItem(0);
                    listener.OnClickmoveItem(positionSun);
                }
                return true;
        }
        return super.onTouchEvent(ev);
    }


    private OnClickMove listener;

    public interface OnClickMove {
    // 滑动的当前位置
        void OnClickmoveItem(int position);
    }
     // 滑动监听
    public void setMoveListener(OnClickMove listener) {
        this.listener = listener;
    }

}

使用

//注意 里边* 必需嵌套一个子控件* ,scrollView里边只有一子空间


            <com.yude.demo.views.view.PageView
                android:id="@+id/pageview"
                android:layout_width="wrap_content"
                android:layout_height="90dp"
                android:background="@color/_ffffff_bg"
                android:scrollbars="none">

                <LinearLayout
                    android:layout_width="wrap_content"
                    android:layout_height="fill_parent"
                    android:orientation="horizontal">

                </LinearLayout>
            </com.yude.views.views.view.PageView>

activity 或 Fragment

 mPageView = (PageView) rootView.findViewById(R.id.pageview);
        //这里就是个普通的xml布局文件 作为第一页第二页的布局

        LinearLayout view = (LinearLayout) inflater.inflate(R.layout.fragment_page1, null);
        mPageView.addPage(view);
        LinearLayout view2 = (LinearLayout) inflater.inflate(R.layout.fragment_page2, null);
        mPageView.addPage(view2);

        mPageView. setHorizontalMovingDistance(100); //设置移动距离触发滑动


        mPageView.setMoveListener(new PageView.OnClickMove() {
            @Override
            public void OnClickmoveItem(int position) {

             //设置原点视图更改 这里只有两页 
                Log.d("OnClickmoveItem", "当前位置" + position);
                if (position == 0) {
                    view_0.setImageResource(dowImage[0]);
                    view_1.setImageResource(dowImage[1]);
                } else {
                    view_0.setImageResource(dowImage[1]);
                    view_1.setImageResource(dowImage[0]);
                }
            }
        });

实现起来还是比较简单 , 可以更具自己需要调整 。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值