Android ScrollView Banner悬浮方案

原创
2020/03/08 16:23
阅读数 537

一、滚动过程悬浮

ScrollView悬浮是很常见的用法,之前用过StickScrollView,存在的问题是只是把View图像定位到了顶部,无法处理touch event。这里我们提供一种相对简单的View组件。

二、核心要点

layout方法top设置

bingToFront方法,该方法不会重新布局,但是会改变View层次

三、代码实现

public class FloatScrollView extends ScrollView {

    private List<StickView> mStickView = null;

    public FloatScrollView(Context context) {
        this(context,null);
    }

    public FloatScrollView(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }

    public FloatScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }


    int getRealChildCount(){
        int childCount = getChildCount();
        if(childCount==0) return 0;
        ViewGroup wrapperView = (ViewGroup) getChildAt(0);
        if(wrapperView==null) return 0;

        return wrapperView.getChildCount();
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        if(!changed) return;
        super.onLayout(changed, l, t, r, b);

        if(mStickView==null){
            mStickView = new ArrayList<>();
        }else{
            mStickView.clear();
        }
        int realChildCount = getRealChildCount();

        for (int i=0;i<realChildCount;i++){
            ViewGroup parent = (ViewGroup) getChildAt(0);
            View child = parent.getChildAt(i);
            Object tag = child.getTag();
            if(!(tag instanceof CharSequence)) continue;

            if("sticky".equals(tag)){
                mStickView.add(new StickView(child));
            }
        }

    }

    @Override
    protected void onScrollChanged(int sl, int st, int oldsl, int oldst) {
        if(mStickView==null){
            mStickView = new ArrayList<>();
        }
        for (int i=0;i<mStickView.size();i++){
            StickView childView = mStickView.get(i);
            int offset = childView.srcTop - st;

            if(offset>0){
                refreshTopOffset(childView.widget,childView.srcTop);
               continue;
            }

            //让前面stickView的回归原始位置
            for (int prev=i-1;prev>=0;prev--){
                StickView preChildView = mStickView.get(i);
                refreshTopOffset(preChildView.widget,preChildView.srcTop);
            }

            Log.d("FloatScrollView", "offset=" + offset + ", st="+st);

            //计算下一个stcikview距离顶部的位置
            int nextChildIndex = i+1;
            if(nextChildIndex>mStickView.size()-1) {
                refreshTopOffset(childView.widget, st);
            }else {
                StickView nextChildView = mStickView.get(nextChildIndex);
                int nextChildOffset = nextChildView.srcTop - st;
                if (nextChildOffset > childView.widget.getHeight()) {
                    refreshTopOffset(childView.widget, st);
                } else {
                    float dx = childView.widget.getHeight() - nextChildOffset;
                    refreshTopOffset(childView.widget,st-dx);
                }
            }
        }
        super.onScrollChanged(sl, st, oldsl, oldst);
    }

    private void refreshTopOffset(View childView, float offset) {
        int topOffset = (int) ( offset);
        childView.layout(childView.getLeft(),topOffset,childView.getRight(),topOffset+childView.getHeight());
        childView.bringToFront(); //解决被其他view遮挡问题
    }


    class StickView{
        int srcTop;
        View widget;

        public StickView(View child) {
            this.widget = child;
            this.srcTop = child.getTop();
        }
    }

}

 

展开阅读全文
加载中

作者的其它热门文章

打赏
0
0 收藏
分享
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部