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

之前分享过一篇仿微信下拉显示小程序的控件,今天分享的与之相似,只不过是下拉展示全部的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的是否可滑动
    ...
    涉及代码比较零散,不好阐述,详细的实现点击查看源码
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    阳明AI阅读 16,044评论 3 119
  • 前几天朱茵参加综艺节目重演紫霞仙子。岁月对她很温柔,不如说她嫁给了爱情,变成了每天照镜子都会发现自己变美的黄太太。...
    木头4_阅读 3,308评论 0 0
  • 1 .关关:《想做你的疯女孩》 镜子前的乖乖女,人群中的路人乙,朋友们的安慰剂,裙子短点都会有人介意。 从小到...
    夏子轩Well阅读 10,497评论 1 11