转载请说明出处
最近在做公司新产品的设计,看到腾讯安全管家首页的抽屉效果设计的挺不错,一方面可以讲经常使用的功能模块直接显示给用户,另一方面将用户不常用的功能模块隐藏起来,而这些功能模块的显示和隐藏可以通过一个抽屉组建实现。所以我们想将这个设计理念加入到我们的产品中。腾讯安全管家效果图如下:
虽然android 文档中向我们提供了一个叫SlidingDrawer的抽屉组建,但是这个组建的使用限制比较多,也实现不了我们想要的效果。故到网上搜了一会,也没看到有开发者写这样的组建。所以只能靠自己了,但是在网上还是看到了一下有价值的参考案例。
不费话了,直接上实现后的效果图:
下面是自定义组建的实现代码
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
public class CustomSlidingDrawer extends LinearLayout implements GestureDetector.OnGestureListener, View.OnTouchListener{
private final static String TAG = "CustomSlidingDrawer";
private Button btnHandler;
private LinearLayout container;
private int mBottonMargin=0;
private GestureDetector mGestureDetector;
private boolean mIsScrolling=false;
private float mScrollY;
private int moveDistance;
public CustomSlidingDrawer(Context context,View otherView,int width,int height, int hideDistance) {
super(context);
moveDistance = hideDistance;
//定义手势识别
mGestureDetector = new GestureDetector(context,this);
mGestureDetector.setIsLongpressEnabled(false);
//改变CustomSlidingDrawer附近组件的属性
LayoutParams otherLP=(LayoutParams) otherView.getLayoutParams();
//这一步很重要,要不组建不会显示
otherLP.weight=1;
otherView.setLayoutParams(otherLP);
//设置CustomSlidingDrawer本身的属性
LayoutParams lp=new LayoutParams(width, height);
lp.bottomMargin = -moveDistance;
mBottonMargin=Math.abs(lp.bottomMargin);
this.setLayoutParams(lp);
this.setOrientation(LinearLayout.VERTICAL);
//this.setBackgroundColor(Color.BLUE);
//设置Handler的属性
btnHandler=new Button(context);
btnHandler.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, 35));
btnHandler.setOnTouchListener(this);
this.addView(btnHandler);
//设置Container的属性
container=new LinearLayout(context);
//container.setBackgroundColor(Color.GREEN);
container.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT));
this.addView(container);
}
/**
* 把View放在CustomSlidingDrawer的Container
* @param v
*/
public void fillPanelContainer(View v)
{
container.addView(v);
}
/**
* 异步移动CustomSlidingDrawer
*/
class AsynMove extends AsyncTask<Integer, Integer, Void> {
@Override
protected Void doInBackground(Integer... params) {
Log.e(TAG, "AsynMove doInBackground");
int times;
if (mBottonMargin % Math.abs(params[0]) == 0)// 整除
times = mBottonMargin / Math.abs(params[0]);
else
// 有余数
times = mBottonMargin / Math.abs(params[0]) + 1;
for (int i = 0; i < times; i++) {
publishProgress(params);
}
return null;
}
@Override
protected void onProgressUpdate(Integer... params) {
Log.e(TAG, "AsynMove onProgressUpdate");
LayoutParams lp = (LayoutParams) CustomSlidingDrawer.this.getLayoutParams();
if (params[0] < 0)
lp.bottomMargin = Math.max(lp.bottomMargin + params[0],
(-mBottonMargin));
else
lp.bottomMargin = Math.min(lp.bottomMargin + params[0], 0);
CustomSlidingDrawer.this.setLayoutParams(lp);
}
}
@Override
public boolean onDown(MotionEvent e) {
mScrollY=0;
mIsScrolling=false;
return false;
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
LayoutParams lp = (LayoutParams) CustomSlidingDrawer.this.getLayoutParams();
if (lp.bottomMargin < 0)
new AsynMove().execute(new Integer[] { moveDistance });// 正数展开
else if (lp.bottomMargin >= 0)
new AsynMove().execute(new Integer[] { -moveDistance });// 负数收缩
return false;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
mIsScrolling=true;
mScrollY+=distanceY;
LayoutParams lp=(LayoutParams) CustomSlidingDrawer.this.getLayoutParams();
if (lp.bottomMargin < -1 && mScrollY > 0) {//往上拖拉
lp.bottomMargin = Math.min((lp.bottomMargin + (int) mScrollY),0);
CustomSlidingDrawer.this.setLayoutParams(lp);
} else if (lp.bottomMargin > -(mBottonMargin) && mScrollY < 0) {//往下拖拉
lp.bottomMargin = Math.max((lp.bottomMargin + (int) mScrollY),-mBottonMargin);
CustomSlidingDrawer.this.setLayoutParams(lp);
}
return false;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {return false;}
@Override
public void onLongPress(MotionEvent e) {}
@Override
public void onShowPress(MotionEvent e) {}
@Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction()==MotionEvent.ACTION_UP && //onScroll时的ACTION_UP
mIsScrolling==true)
{
LayoutParams lp=(LayoutParams) CustomSlidingDrawer.this.getLayoutParams();
if (lp.bottomMargin >= (-mBottonMargin/2)) {//往上超过一半
new AsynMove().execute(new Integer[] { moveDistance });// 正数展开
}
else if (lp.bottomMargin < (-mBottonMargin/2)) {//往下拖拉
new AsynMove().execute(new Integer[] { -moveDistance });// 负数收缩
}
}
return mGestureDetector.onTouchEvent(event);
}
}
下面是demo的源码: