美文网首页Android 开发知识
使用scrollview必须知道的坑

使用scrollview必须知道的坑

作者: hahauha | 来源:发表于2019-05-28 18:21 被阅读0次

    1、问题:Cast from null to OnScrollChangeListener requires API level 23 (current min is 16)监听

    原因:scrollview的滑动,OnScrollChangeListener 在API23以后才有
    解决:自定义监听接口

    public class MyScrollView extends ScrollView {
    
        private OnScrollListener listener;
    
        public void setOnScrollListener(OnScrollListener listener) {
            this.listener = listener;
        }
    
        public MyScrollView(Context context) {
            super(context);
        }
    
        public MyScrollView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        //设置接口
        public interface OnScrollListener {
            void onScroll(int scrollY);
        }
    
        /**
         * 重写原生onScrollChanged方法,将参数传递给接口,由接口传递出去
         */
        @Override
        public void onScrollChanged(int l, int t, int oldl, int oldt) {
            super.onScrollChanged(l, t, oldl, oldt);
            if (listener != null) {
                //垂直滑动的距离
                listener.onScroll(t);
            }
        }
    }
    

    2、scrollview嵌套viewpage时

    问题
    (1):页面空白
    (2):每个viewpage中的fragment高度一样,导致页面内容短的fragment底部有大片空白区域
    (3):viewpage中的fragment中如果包含自带滚动的控制,如webview,recycleview等,在滑动切换viewpage时,会出现卡顿。
    解决:自定义viewpage,
    (1)重写onMeasure()方法计算viewpage高度,
    (2)在生成fragment页面时将view和position保存起来,定义resetHeight()方法,viewpage切换时改变viewpage高度。
    (3)自带卡顿的这边分控件会获得焦点,消耗touch事件,所以解决方法就是在viewpage中拦截touch事件。两处方法重写onTouchEvent(),onInterceptTouchEvent()。

    public class CustomViewPager extends ViewPager {
        private int current;
        private int height = 0;
        /**
         * 保存position与对于的View
         */
        private HashMap<Integer, View> mChildrenViews = new LinkedHashMap<Integer, View>();
    
        private boolean scrollble = true;
        private OnTouchListener mOnTouchListener;
    
        public interface OnTouchListener {
            void onTouch(int state);
        }
    
        public CustomViewPager(Context context) {
            super(context);
        }
    
        public CustomViewPager(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            if (mChildrenViews.size() > current) {
                View child = mChildrenViews.get(current);
                child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
                height = child.getMeasuredHeight();
            }
    
            heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
    
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    
        public void resetHeight(int current) {
            this.current = current;
            if (mChildrenViews.size() > current) {
    
                LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) getLayoutParams();
                if (layoutParams == null) {
                    layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, height);
                } else {
                    layoutParams.height = height;
                }
                setLayoutParams(layoutParams);
            }
        }
    
        /**
         * 保存position与对于的View
         */
        public void setObjectForPosition(View view, int position) {
            mChildrenViews.put(position, view);
        }
    
    
        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            if (!scrollble) {
                //返回true表示,表示消耗此次touch事件
                return true;
            }
            return super.onInterceptTouchEvent(ev);
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent ev) {
            if (!scrollble) {
                //返回true表示,表示消耗此次touch事件
                return true;
            }
            return super.onTouchEvent(ev);
        }
    
    
        public boolean isScrollble() {
            return scrollble;
        }
    
        public void setScrollble(boolean scrollble) {
            this.scrollble = scrollble;
        }
    
        @Override
        public boolean dispatchTouchEvent(MotionEvent ev) {
            if (mOnTouchListener != null) {
                mOnTouchListener.onTouch(ev.getAction());
            }
            return super.dispatchTouchEvent(ev);
        }
    
        public void setmOnTouchListener(OnTouchListener mOnTouchListener) {
            this.mOnTouchListener = mOnTouchListener;
        }
    
    }
    

    3、scrollview滑动定位,当scrollview处于滑动状态时,这时通过点击定位到scrollview的某一处会失效。

    解决:同时使用两个scrollview的滑动方法 scrollTo() 和smoothScrollTo()。
    smoothScrollTo()类似scroolTo(),但是滑动的时候是平缓的,而不是立即滚动到某处。
    smoothScrollTo()方法可以打断滑动动画。

    相关文章

      网友评论

        本文标题:使用scrollview必须知道的坑

        本文链接:https://www.haomeiwen.com/subject/zmzdtctx.html