Android 自定义ViewPager嵌套滚动兼容

本文介绍了一种优化后的ViewPager组件,解决了嵌套滚动、单击事件及子View缩放等问题,并提供了点击监听接口。通过自定义触摸事件处理,实现更平滑的过渡效果和用户体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


**
 * 1、嵌套滚动兼容
 * 2、单击事件
 * 3、子View缩放兼容
 *
 * @author chrisZou
 * @blog http://blog.youkuaiyun.com/mcy478643968/article/details/19609407
 * @blog http://blog.youkuaiyun.com/leewenjin/article/details/21011841
 * @from http://blog.youkuaiyun.com/fy993912_chris/article/details/75006138
 * @email chrisSpringSmell@gmail.com
 */
public class CustomCompatViewPager extends ViewPager {

    public static final int CLICKED_DISTANCE = 10;
    OnItemClickListener onItemClickListener;

    float curX = 0f;
    float curY = 0f;

    float downX = 0f;
    float downY = 0f;

    private int realSize = 0;

    public CustomCompatViewPager(Context context) {
        super(context);
    }

    public CustomCompatViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void setRealSize(int realSize) {
        this.realSize = realSize;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        int curIndex = getCurrentItem();
        curX = ev.getX();
        curY = ev.getY();
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downX = curX;
                downY = curY;
                break;
            case MotionEvent.ACTION_UP:
                if (Math.abs(downX - curX) <= CLICKED_DISTANCE && Math.abs(downY - curY) <= CLICKED_DISTANCE) {
                    onItemClick(getAdapter(), curIndex, getChildAt(curIndex));
                    return true;
                }
            case MotionEvent.ACTION_MOVE:
                if (Math.abs(curX - downX) > Math.abs(curY - downY))
                    getParent().requestDisallowInterceptTouchEvent(true);//true为拦截
                else {
                    getParent().requestDisallowInterceptTouchEvent(false);
                }
                break;
        }

        return super.onTouchEvent(ev);
    }

    /**
     * 解决viewpager嵌套ImageScaleView的问题
     *
     * @param ev
     * @return
     */
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        try {
            return super.onInterceptTouchEvent(ev);
        } catch (IllegalArgumentException ex) {
            ex.printStackTrace();
        }
        return false;
    }

    /**
     * 单击
     */
    private void onItemClick(PagerAdapter adapter, int currentItem, View itemView) {
        if (onItemClickListener != null) {
            if (realSize == 0)
                realSize = adapter.getCount();
            onItemClickListener.onItemClick(adapter, currentItem % realSize, itemView);
        }
    }

    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
    }

    public static class DepthPageTransformer implements ViewPager.PageTransformer {
        private static final float MIN_SCALE = 0.75f;

        public void transformPage(View view, float position) {
            int pageWidth = view.getWidth();

            if (position < -1) { // [-Infinity,-1)
                // This page is way off-screen to the left.
                view.setAlpha(0);

            } else if (position <= 0) { // [-1,0]
                // Use the default slide transition when moving to the left page
                view.setAlpha(1);
                view.setTranslationX(0);
                view.setScaleX(1);
                view.setScaleY(1);

            } else if (position <= 1) { // (0,1]
                // Fade the page out.
                view.setAlpha(1 - position);

                // Counteract the default slide transition
                view.setTranslationX(pageWidth * -position);

                // Scale the page down (between MIN_SCALE and 1)
                float scaleFactor = MIN_SCALE
                        + (1 - MIN_SCALE) * (1 - Math.abs(position));
                view.setScaleX(scaleFactor);
                view.setScaleY(scaleFactor);

            } else { // (1,+Infinity]
                // This page is way off-screen to the right.
                view.setAlpha(0);
            }
        }
    }

    public static class ZoomOutPageTransformer implements ViewPager.PageTransformer {
        private static final float MIN_SCALE = 0.85f;
        private static final float MIN_ALPHA = 0.5f;

        @SuppressLint("NewApi")
        public void transformPage(View view, float position) {
            int pageWidth = view.getWidth();
            int pageHeight = view.getHeight();

            Log.e("TAG", view + " , " + position + "");

            if (position < -1) { // [-Infinity,-1)
                // This page is way off-screen to the left.
                view.setAlpha(0);

            } else if (position <= 1) //a页滑动至b页 ; a页从 0.0 -1 ;b页从1 ~ 0.0
            { // [-1,1]
                // Modify the default slide transition to shrink the page as well
                float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));
                float vertMargin = pageHeight * (1 - scaleFactor) / 2;
                float horzMargin = pageWidth * (1 - scaleFactor) / 2;
                if (position < 0) {
                    view.setTranslationX(horzMargin - vertMargin / 2);
                } else {
                    view.setTranslationX(-horzMargin + vertMargin / 2);
                }

                // Scale the page down (between MIN_SCALE and 1)
                view.setScaleX(scaleFactor);
                view.setScaleY(scaleFactor);

                // Fade the page relative to its size.
                view.setAlpha(MIN_ALPHA + (scaleFactor - MIN_SCALE)
                        / (1 - MIN_SCALE) * (1 - MIN_ALPHA));

            } else { // (1,+Infinity]
                // This page is way off-screen to the right.
                view.setAlpha(0);
            }
        }
    }

    public static class FlagPageTransformer implements ViewPager.PageTransformer {
        private static final float MIN_SCALE = 0.85f;
        private static final float MIN_ALPHA = 0.5f;

        @SuppressLint("NewApi")
        public void transformPage(View view, float position) {
            int pageWidth = view.getWidth();
            int pageHeight = view.getHeight();

            Log.e("TAG", view + " , " + position + "");

            if (position < -1) { // [-Infinity,-1)
                // This page is way off-screen to the left.
                view.setAlpha(0);

            } else if (position <= 1) //a页滑动至b页 ; a页从 0.0 -1 ;b页从1 ~ 0.0
            { // [-1,1]
                // Modify the default slide transition to shrink the page as well
                float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));
                float vertMargin = pageHeight * (1 - scaleFactor) / 2;
                float horzMargin = pageWidth * (1 - scaleFactor) / 2;
                if (position < 0) {
                    view.setTranslationX(horzMargin - vertMargin / 2);
                } else {
                    view.setTranslationX(-horzMargin + vertMargin / 2);
                }

                // Scale the page down (between MIN_SCALE and 1)
                view.setScaleX(scaleFactor);
                view.setScaleY(scaleFactor);

                // Fade the page relative to its size.
                view.setAlpha(MIN_ALPHA + (scaleFactor - MIN_SCALE)
                        / (1 - MIN_SCALE) * (1 - MIN_ALPHA));

            } else { // (1,+Infinity]
                // This page is way off-screen to the right.
                view.setAlpha(0);
            }
        }
    }

    public interface OnItemClickListener {
        void onItemClick(PagerAdapter adapter, int currentItem, View itemView);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值