这是一个下拉抽屉,仿华为手机的系统下拉抽屉
未使用动画,是折叠打开效果,如使用压缩打开和移动打开效果,请加缩放动画和平移动画 本demo是动态改变高度,主要用到了ontouch方法 直接附上效果图和activity
/* * 这是一个下拉抽屉,仿华为手机的系统下拉抽屉 * 未使用动画,是折叠打开效果,如使用压缩打开和移动打开效果,请加缩放动画和平移动画 * 本demo是动态改变高度 * */ public class MainActivity extends AppCompatActivity implements View.OnTouchListener, GestureDetector.OnGestureListener{ //滚动布局 ScrollView show; //滑动按钮 Button btn; //动态改变布局用 private RelativeLayout.LayoutParams linearParams; //配合ontouch使用,手势监听 private GestureDetector mGestureDetector; int phone_high;//屏幕的高度 int stop_high;//需要停留的位置 int small_high = 100;//最小位置 int speed = 50;//自动展开或收回的滑动速率,默认为50,大小自己设,越大越快 //设定定时器用来自动弹回和弹出 Handler myHanlder = new Handler(); Runnable run=new Runnable() { @Override public void run() { //向上收回 if(stop_high == small_high){ if(linearParams.height>stop_high){ //速率自己调 linearParams.height = linearParams.height-speed; show.setLayoutParams(linearParams); // 使设置好的布局参数应用到控件 // 递归 myHanlder.postDelayed(run, 1); } //向下展开 }else if(stop_high == phone_high){ if(linearParams.height<stop_high){ linearParams.height = linearParams.height+speed; show.setLayoutParams(linearParams); // 使设置好的布局参数应用到控件 // 递归 myHanlder.postDelayed(run, 1); } }else { } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); show = (ScrollView) findViewById(R.id.show); btn = (Button) findViewById(R.id.btn); // 取控件当前的布局参数 linearParams = (RelativeLayout.LayoutParams) show.getLayoutParams(); btn.setOnTouchListener(this); mGestureDetector = new GestureDetector(this); mGestureDetector.setIsLongpressEnabled(true); //获取屏幕的高度 phone_high = getMetrics().heightPixels; } @Override public boolean onTouch(View v, MotionEvent event) { //触摸返回值 int action = event.getAction(); switch (action) { //开始触摸 case MotionEvent.ACTION_DOWN: //开始触摸时候返回的坐标 //取消计时器 myHanlder.removeCallbacks(run); break; //触摸移动 case MotionEvent.ACTION_MOVE: //动态设定布局的高度为手势移动的高度 if(event.getRawY()>=small_high){ linearParams.height = (int) event.getRawY(); show.setLayoutParams(linearParams); } break; //终止触摸 case MotionEvent.ACTION_UP: break; } // return false; //引入手势,为了抓取到加速度,不引入的话,自己算比较麻烦 return mGestureDetector.onTouchEvent(event); } //获取屏幕高度的方法 private DisplayMetrics getMetrics(){ WindowManager wm = getWindowManager(); DisplayMetrics outMetrics = new DisplayMetrics(); wm.getDefaultDisplay().getMetrics(outMetrics); return outMetrics; } //以下为手势监听,配合ontouch方法使用 //滑动的距离和速率。为了判断手势 final int FLING_MIN_DISTANCE = 50, FLING_MIN_VELOCITY = 200; @Override public boolean onDown(MotionEvent e) { return false; } @Override public void onShowPress(MotionEvent e) { } @Override public boolean onSingleTapUp(MotionEvent e) { return false; } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { return false; } @Override public void onLongPress(MotionEvent e) { } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { //判断当滑动距离大于50并且速率大于200,即自动收回,向上滑动 if (e1.getRawY() - e2.getRawY() > FLING_MIN_DISTANCE && Math.abs(velocityX) > FLING_MIN_VELOCITY) { //停止的高度为50,就是抽屉的最后的停留位置 stop_high = small_high; myHanlder.post(run); /*之前用的动画但是不是想要的效果,如果 想达到想要的效果还要动态改变上部外 边距,索性直接用了定时器来取代动画*/ /*if(animation!=null){ animation.cancel(); } animation = new TranslateAnimation(0, 0, 0, -e2.getRawY()); animation.setDuration(500); show.startAnimation(animation);*/ //判断当滑动距离小于50并且速率大于200,即自动展开,向下滑动 }else if(e1.getRawY() - e2.getRawY() <- FLING_MIN_DISTANCE && Math.abs(velocityX) > FLING_MIN_VELOCITY) { //停止的高度即屏幕高度,就是抽屉的最后的停留位置 stop_high = phone_high; myHanlder.post(run); } return false; } }
附上demo的地址:http://download.csdn.net/detail/kac930/9797456