美文网首页
B1(负一楼)展示页---BasementView

B1(负一楼)展示页---BasementView

作者: truemi | 来源:发表于2018-08-01 13:10 被阅读0次

    之前分享过一篇仿微信下拉显示小程序的控件,今天分享的与之相似,只不过是下拉展示全部的view,同时主界面可以添加任意布局.支持绑定AbsListview子类,和可滑动的view.

    演示:

    b1.gif

    从上面的演示中,可以看到,有4种动作:

    1. 下拉,没有超过预设阀值,则回弹到关闭状态
    2. 下拉,超过阀值,这滚动到b1(隐藏的view)完全打开的状态
    3. 上拉,没有超过预设阀值,则回弹到b1完全打开状态
    4. 上拉,超过阀值,这滚动到b1(隐藏的view)完全关闭的状态

    作用的view上就是view的显示与隐藏问题,之前我们使用改变viewpadding值,这里我们使用动态改变view的margin值,从而改变view显示与隐藏.

    所以我们的思路是:

    在onTouchEvent的监听中,

    • MOVE状态下,根据手势,时刻改变b1的marginTop值,达到随手势打开view和关闭view的动态效果
    • 在UP状态下,根据手势状态(下拉或上拉),预设阀值,b1的显示状态判断b1的滚动动作.
      view的滚动,依然使用Scroller滚动器.
    关键步骤:

    1.自定义view继承LinearLayout,初始化basementLayout和currentLayout布局

      setOrientation(VERTICAL);//设置纵向布局
            basementLayout = new RelativeLayout(context);//负一楼layout
            currentLayout = new RelativeLayout(context);//当前layout
    
            getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {
                    getViewTreeObserver().removeOnGlobalLayoutListener(this);
    //                测量当前view的高度,通过margintop隐藏负一楼layout
                    height = getHeight();
                    layoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, height);
                    layoutParams.setMargins(0, -height, 0, 0);//隐藏b1
                    basementLayout.setLayoutParams(layoutParams);
                    basementLayout.setEnabled(true);
                    LinearLayout.LayoutParams layoutParams1 = new            LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, height);
                    currentLayout.setLayoutParams(layoutParams1);
                    //添加到当前view中
                    addView(basementLayout);
                    addView(currentLayout);
                }
            });
    

    2.MOVE状态下,改变b1的marginTop
    计算手指在Y轴上滑动的距离,根据手势方向设置marginTop

     layoutParams.setMargins(0, marginTop, 0, 0);
     basementLayout.setLayoutParams(layoutParams);
    

    3.UP状态下,view自动滚动到指定位置
    创建Scroller实例,同时设置插值器(初始化里创建)
    scroller = new Scroller(context, new DecelerateInterpolator());
    使用startScroll设置滚动区间

    scroller.startScroll(0, startY, 0, endY, duration);
    postInvalidate();//必须(或Invalidate();)
    

    重写computeScroll()方法:

     public void computeScroll() {
            moving = scroller.computeScrollOffset();
            if (scroller.computeScrollOffset()) {
    /*获取实时的Y轴的变化值
    *这个变化值是从上边传入的startY 到 (startY + endY)
    *如:startY =0,endY=100;则变化区间是从0一直递增到100;
    *startY=100,endY = -100,则变化区间是100递减到0
    */
                int currY = scroller.getCurrY();//获取实时的Y轴的变化值
                postInvalidate();//必须(或Invalidate();)
    //通过这个变化值,时刻改变marginTop的值,就达到了自动滚动的效果
     layoutParams.setMargins(0, currY, 0, 0);
     basementLayout.setLayoutParams(layoutParams);
    }
    

    以上只是一些重点环节,要想实现最终效果,还有很多细节要处理:

    • onInterceptTouchEvent(MotionEvent ev)对于手势拦截的处理(关键)
    • float,int转换导致的精度损失问题
    • 零界点的判断
    • 子view的是否可滑动
      ...
      涉及代码比较零散,不好阐述,详细的实现点击查看源码

    相关文章

      网友评论

          本文标题:B1(负一楼)展示页---BasementView

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