1、自定义view  BottomDrawerLayout

/*** 作者:created by meixi* 邮箱:15913707499@163.com* 日期:2018/12/10 11*/public class BottomDrawerLayout extends ViewGroup {private static final String TAG = "BottomDrawerLayout";private View mDrawerView;private View mBottomView;private View mRotateView;private ViewDragHelper mDragHelper;private float mInitialX;private float mInitialY;private int mTouchSlop;private int mCurTop=-1;private int mBottomHeight;private int mDrawerHeight;private int mParentHeight;private float mDragOffset = 1;private boolean isUnderBottomView = false;private boolean isUnderDrawerView = false;private OnDrawerStatusChanged onDrawerStatusChanged;public BottomDrawerLayout(Context context) {super(context);init(context);}public BottomDrawerLayout(Context context, AttributeSet attrs) {super(context, attrs);init(context);}public BottomDrawerLayout(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init(context);}private void init(Context context) {mDragHelper = ViewDragHelper.create(this, 1.0f,new DragerCallBack());mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();}public void setOnDrawerStatusChanged(OnDrawerStatusChanged onDrawerStatusChanged) {this.onDrawerStatusChanged = onDrawerStatusChanged;}public void switchDrawer() {if(mDragOffset<1){minimize();}else{maximize();}}private class DragerCallBack extends  ViewDragHelper.Callback{//从底部到顶部的顺序遍历子view@Overridepublic int getOrderedChildIndex(int index) {int childCount = BottomDrawerLayout.this.getChildCount();int newIndex = childCount - index -1;return  newIndex;}@Overridepublic boolean tryCaptureView(View child, int pointerId) {return child == mDrawerView;}@Overridepublic int clampViewPositionHorizontal(View child, int left, int dx) {
//            Log.d(TAG, "clampViewPositionHorizontal " + left + "," + dx);
//            final int leftBound  = getPaddingLeft();
//            final int rightBound = getWidth() - mBottomView.getWidth() - leftBound;
//            //坐标系三种情况
//            final int newLeft = Math.min(Math.max(left, leftBound), rightBound);
//
//            return newLeft;return super.clampViewPositionHorizontal(child, left, dx);}//要想上下拖动必须重写此方法@Overridepublic int clampViewPositionVertical(View child, int top, int dy) {
//            Log.d(TAG, "clampViewPositionVertical " + top + "," + dy);final int topBound = getHeight() - mDrawerView.getMeasuredHeight() - mBottomView.getHeight();final int bottomBound = getHeight()  - mBottomView.getHeight();final int newTop = Math.min(Math.max(top, topBound), bottomBound);return newTop;}@Overridepublic void onViewCaptured(View capturedChild, int activePointerId) {super.onViewCaptured(capturedChild, activePointerId);}@Overridepublic void onViewReleased(View releasedChild, float xvel, float yvel) {//            Log.i(TAG, "onViewReleased:" + "xvel:" + xvel + ",yvel:" + yvel);//yvel Fling产生的值,yvel > 0 则是快速往下Fling || yvel < 0 则是快速往上Flingint top = mParentHeight - mDrawerHeight - mBottomHeight;if (yvel > 0 || (yvel == 0 && mDragOffset > 0.5f)/* 后面这个小括号里判断处理拖动之后停下来但是未松手的情况 */) {top += mDrawerHeight;}mDragHelper.settleCapturedViewAt(releasedChild.getLeft(), top);invalidate();//important 不加,就不会刷新View的位置}@Overridepublic void onViewDragStateChanged(int state) {super.onViewDragStateChanged(state);}@Overridepublic void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {mCurTop = top;mDragOffset = ((float) top -(mParentHeight - mDrawerHeight - mBottomHeight))/ mDrawerHeight;
//            Log.d(TAG, "onViewPositionChanged: mDragOffset:" + mDragOffset);//旋转与透明跟随效果mDrawerView.setAlpha(1-mDragOffset);
//            mRotateView.setRotation((1-mDragOffset)*180);requestLayout();if (onDrawerStatusChanged != null) {onDrawerStatusChanged.onChanged(mParentHeight,top);}//            if(onDrawerStatusChanged !=null){
//                if(mDragOffset == 0 || mDragOffset == 1){
//                    onDrawerStatusChanged.onChanged(mParentHeight,top);
//                }
//            }}}public interface OnDrawerStatusChanged{void onChanged(int parentHeight, int drawerTop);}public void maximize(){smoothSlideTo(0.0f);}public void minimize(){smoothSlideTo(1.0f);}private boolean smoothSlideTo(float slideOffset) {final int topBound = mParentHeight - mDrawerHeight - mBottomHeight;int y = (int) (topBound + slideOffset * mDrawerHeight);if(mDragHelper.smoothSlideViewTo(mDrawerView, mDrawerView.getLeft(), y)){ViewCompat.postInvalidateOnAnimation(this);return true;}return false;}@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {return super.dispatchTouchEvent(ev);}@Overridepublic boolean onInterceptTouchEvent(MotionEvent event) {int act = MotionEventCompat.getActionMasked(event);
//        final int action = event.getAction();switch (act) {//由于很多情况不能拦截事件,这种时候系统不会调用onTouchEvent()// 手动把事件传递给mDragHelper.processTouchEventcase MotionEvent.ACTION_DOWN:mInitialX = event.getX();mInitialY = event.getY();//Feed the down event to the detector so it has// context when/if dragging begins
//                mDetector.onTouchEvent(event);mDragHelper.processTouchEvent(event);isUnderBottomView = mDragHelper.isViewUnder(mBottomView, (int)mInitialX, (int)mInitialY);isUnderDrawerView = mDragHelper.isViewUnder(mDrawerView, (int)mInitialX, (int)mInitialY);break;case MotionEvent.ACTION_POINTER_DOWN:mDragHelper.processTouchEvent(event) ;break;case MotionEvent.ACTION_POINTER_UP:mDragHelper.processTouchEvent(event) ;break;case MotionEvent.ACTION_MOVE:final float x = event.getX();final float y = event.getY();final int yDiff = (int) Math.abs(y - mInitialY);final int xDiff = (int) Math.abs(x - mInitialX);//Verify that either difference is enough to be a dragif ((yDiff > mTouchSlop || xDiff > mTouchSlop) && (isUnderBottomView || isUnderDrawerView) ){//Start capturing eventsreturn true;}break;}//父类是viewgroup,返回的falsereturn super.onInterceptTouchEvent(event);}@Overridepublic boolean onTouchEvent(MotionEvent event) {mDragHelper.processTouchEvent(event);//down事件返回false,让其底部的平行层级的view能够接收到点击事件switch (event.getAction()) {case MotionEvent.ACTION_DOWN:return false;case MotionEvent.ACTION_UP:return false;//只有当手指达到拖动阈值时this才确定消耗此系列事件//若未达到阈值也返回true,则与其平行的view不会收到click事件case MotionEvent.ACTION_MOVE:final float x = event.getX();final float y = event.getY();final int yDiff = (int) Math.abs(y - mInitialY);final int xDiff = (int) Math.abs(x - mInitialX);//Verify that either difference is enough to be a dragif ((yDiff > mTouchSlop || xDiff > mTouchSlop) && (isUnderBottomView || isUnderDrawerView) ){//Start capturing eventsreturn true;}break;}return false;}@Overrideprotected void onFinishInflate() {super.onFinishInflate();mBottomView = findViewById(R.id.layout_bottom_bar);mDrawerView = findViewById(R.id.layout_price_detail);//        mRotateView = findViewById(R.id.img_spread_out);mBottomView.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {maximize();}});mDrawerView.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {minimize();}});}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {measureChildren(widthMeasureSpec,heightMeasureSpec);super.onMeasure(widthMeasureSpec, heightMeasureSpec);}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {mParentHeight = this.getHeight();mBottomHeight = mBottomView.getMeasuredHeight();mDrawerHeight = mDrawerView.getMeasuredHeight();
//        Log.d(TAG, "onLayout: drawHeight:"+drawHeight);mBottomView.layout(l,mParentHeight - mBottomHeight,r,b);if(mCurTop == -1){mCurTop = mParentHeight - mBottomHeight;}mDrawerView.layout(l,mCurTop,r,mCurTop + mDrawerHeight);}@Overridepublic void computeScroll() {if(mDragHelper.continueSettling(true)){ViewCompat.postInvalidateOnAnimation(this);}}
}

layout布局中使用这个自定义抽屉view即可,第一个LinearLayout是抽屉内容,第二个LinearLayout是固定底部把手

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent" android:layout_height="match_parent"><com.tianxin.shanghuact.BottomDrawerLayoutandroid:id="@+id/bottom_drawer_layout"android:layout_width="match_parent"android:layout_height="match_parent"><LinearLayoutandroid:id="@+id/layout_price_detail"android:layout_width="match_parent"android:background="@color/colorPrimary"android:orientation="horizontal"android:layout_height="180dp"></LinearLayout><LinearLayoutandroid:id="@+id/layout_bottom_bar"android:layout_width="match_parent"android:background="@color/transparent"android:orientation="horizontal"android:layout_height="40dp"></LinearLayout></com.tianxin.shanghuact.BottomDrawerLayout></RelativeLayout>

Android 固定式底部上滑抽屉view相关推荐

  1. Android 底部上拉抽屉view

    module链接:https://download.csdn.net/download/meixi_android/10839835 接入module方法:https://blog.csdn.net/ ...

  2. android底部上滑锁屏

    概述 各种测试,各种查资料,总算解决了底部上滑锁屏功能的实现.一个底部三大金钢折腾死个人. 最后借助的还是AccessibilityService实现.因为我想实现的底部导航栏一定要显示在屏幕最底端, ...

  3. html5移动端底部效果,spring mvc +HTML5实现移动端底部上滑异步加载更多内容分页效果...

    代码实现 1).前端代码: 前端代码需要用到jquery和zepto,大家在网上自己下载,下面是页面的代码: contentType="text/html; charset=UTF-8&qu ...

  4. Android 自定义底部上拉控件的实现

    前言 又到了新的一月,今天提供一个Android自定义底部上拉布局的实现,起因是自己在项目中需要实现这样一个控件,干脆自己写一个练练手. 写完了觉得能想到的需求都基本有了(可能会有其它需求,不过基本上 ...

  5. 从底部上滑失灵_iPad 上这 20 个快捷操作,真正帮你提高生产力!

    Hello 这里是一周进步,更多干货欢迎阅读:一周进步 · 2020半年文章精选 文 / 一周进步 · Cherry 如果你是想把 iPad 变成生产力工具(而不是盖泡面),熟悉使用界面的基础操作,就 ...

  6. 安全锁界面,防止底部上滑触发人脸解锁与绘制图案锁冲突

    原生在KeyguardSecurityContainer.java中,当滑动至安全锁界面时,如果设置了人脸解锁,会上滑再次触发人脸解锁. 此时若是图案解锁,会时有发生图案锁绘制与上滑触发人脸解锁冲突的 ...

  7. android 上滑隐藏view,Android CoordinatorLayout + AppBarLayout(向上滚动隐藏指定的View)

    在新的Android Support Library里面,新增了CoordinatorLayout, AppBarLayout等. 实现的效果: 向下滚动RecylerView,Tab会被隐藏,向上滚 ...

  8. 从底部上滑失灵_宝鸡终于也有超火的高空玻璃水滑啦!就在玉池公社!8月10日见~...

    夏天一定要去有"水"的地方 去哪里呢?小宝妹告诉你! 玉池公社千米玻璃水滑 这个夏季即将来袭 快来让激情燃烧一会儿! 宝鸡玉池玻璃水滑来了! 高空玻璃水滑采用钢结构框架 透明钢化玻 ...

  9. 从底部上滑失灵_雷达液位计测量液位失灵的检查处理方法

    1.检查供电是否正常. 2.检查通讯是否正常.通过安装了雷达调试软件的手提电脑.FBM(双向调制/解调器)接入FCU2160(现场通讯单元),可以在操作界面上读取雷达的所有数据,发射波.反射波强度,雷 ...

最新文章

  1. 美国邮政署将展开测试自驾卡车运输服务
  2. python3中的int类型占64位_在windows 10 64位计算机中,默认情况下,numpy数组数据类型将以int32形式出现...
  3. JavaScript instanceof 运算符深入剖析
  4. shell-4.bash的变量:用户自定义变量
  5. Linux驱动修炼之道-内存映射
  6. Redis集群的重启
  7. oracle批处理参数调用,bat调用jar包并传入多个参数
  8. ios textview间距_iOS 设置TextView控件内容行间距
  9. 肖仰华 | 基于知识图谱的问答系统
  10. 4-1MapReduce原理
  11. 解析linux中的vfs文件系统机制,解析Linux中的VFS文件系统机制
  12. Python稳基修炼的经典案例9(计算机二级、初学者必会turtle库例题)
  13. 快速开发框架工作笔记001---项目开发中整理_整合好的_springcloud快速开发框架_springcloud框架_springcloud架构
  14. 私钥、公钥、数字签名、数字证书、HTTPS
  15. Java 多线程详解(五)------线程的声明周期
  16. boost::asio c++ 网络编程socket通信一个简单例子
  17. Silverlight 2应用程序中XAP文件揭秘
  18. 2 月全国程序员工资统计 + 大厂新入职员工职级对应表
  19. TOM邮箱|国内适合商务人士的邮箱是什么邮箱
  20. 教你用优化视频的方法提高视频的质量

热门文章

  1. [css] 头部设置meta也可以做到自适应为啥还要用rem?
  2. 前端学习(2835):小程序中使用less
  3. 前端学习(2778):uni组件库的使用
  4. 前端学习(2001)vue之电商管理系统电商系统之获取商品分类数据
  5. 前端学习(1879)vue之电商管理系统电商系统之通过axios拦截器添加token认证
  6. 前端学习(1274):Vue路由管理器
  7. 前端学习(765):使用构造函数的原因
  8. 神经网络中的 Dropout 以及变体方法
  9. php 获取localstorage,浅谈localStorage的本地存储
  10. 大屏某区域滚动效果循环