相信大家都有用过QQ,而QQ上面的侧滑菜单大家都有使用过,这一设计给用户带来了不错的交互乐趣。ViewDragHelper顾名思义View托拽帮助类,一个在
2013的谷歌大会上提出来的一个类简化View拖拽的操作的类
要实现侧滑效果还需要导入一个android-support-v4.jar包,用来帮助实现拖拽效果和nineoldandroids-2.4.0.jar开源动画库
private ViewGroup mLeftContent;
private ViewGroup mMainContent;
private int width;//子View测量的宽度
private int height;//子View测量的高度
private int dragRange;//子View拖拽的范围
private Context context;
private ViewDragHelper Mydraghelper;
**那么应该如何使用ViewDragHelper类来实现拖拽操作呢?**
一.ViewDragHelper类对象的创建
这里要传入三个参数
this-->代表ViewGroup对象
1.0f 表示拖拽的敏感度,1.0f表示最高
dragCallback-->一个Callback接口类对象,必须实现
Mydraghelper = ViewDragHelper.create(this,1.0f,dragCallback);
二。实现Callback接口中的某些方法
由于Callback方法中的方法比较多,在此只讲解一些需要完成侧滑效果而实现的方法
//返回值决定了哪些View可以进行拖拽,返回true表示所有的View可以进行拖拽
@Override
public boolean tryCaptureView(View arg0, int arg1) {
return arg0 == mMainContent || arg0 == mLeftContent;
}
@Override
/*决定了View水平方向拖拽到的位置 child-->拖拽的View
* left-->view拖拽到的位置,距离父控件左边边缘的距离
* dx -->拖拽的距离
*/
public int clampViewPositionHorizontal(View child, int left, int dx) {
if(child == mMainContent){
left = dragtoleft(left);
}
return left;
}
private int dragtoleft(int left) {
if(left<0){
return 0;
}else if(left>dragRange){
left = dragRange;
}
return left;
}
//返回一个大于0的数,否则无法进行拖拽
@Override
public int getViewHorizontalDragRange(View child) {
return dragRange;
}
//view坐标发生改变时,回调,从新设置布局
@Override
public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
if(changedView == mLeftContent){
mLeftContent.layout(0, 0, width, height);
int newLeft = mMainContent.getLeft()+dx;
newLeft = dragtoleft(newLeft);
mMainContent.layout(newLeft, 0, newLeft+width, height);
}
//dispatchDragState(mMainContent.getLeft());
animView(mMainContent.getLeft());
invalidate();//解决低版本不能拖拽的问题
}
//手指释放时回调--> xve1表示手指释放时在X轴的速度,正向大于0,反向小于0
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
if(xvel==0.0f&&mMainContent.getLeft()<0.5f*dragRange){
close();
}else if(xvel<0){
close();
}else{
open();
}
}
三.在自定义View中判断是要否拦截事件,将拦截的事件交给ViewDragHelper类来处理
//拦截触摸事件,判断是否进行拦截
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
return Mydraghelper.shouldInterceptTouchEvent(ev);
}
//将拦截的事件进行处理,内部消费掉
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
Mydraghelper.processTouchEvent(event);
return true;
}
四.关于Callback中调用的一些自定义方法已经变量的说明
设置侧滑菜单的动画效果
private void animView(int left) {
float percent = left * 1.0f / dragRange;
//设置主界面缩放
ViewHelper.setScaleX(mMainContent, 1.0f+(0.8f-1.0f)*percent);
ViewHelper.setScaleY(mMainContent, 1.0f+(0.8f-1.0f)*percent);
//设置左边界面的缩放
ViewHelper.setScaleX(mLeftContent, 0.5f+(1.0f-0.5f)*percent);
ViewHelper.setScaleY(mLeftContent, 0.5f+(1.0f-0.5f)*percent);
//摄制左边界面的透明度变化
ViewHelper.setAlpha(mLeftContent, 1.0f*percent);
getBackground().setColorFilter(
(Integer) EvaluateUtil.evaluateArgb(percent, Color.BLACK, Color.TRANSPARENT),
Mode.SRC_OVER);
}
设置侧滑菜单的打开与关闭
protected void open() {
open(true);
}
public void open(boolean isSmooth) {
int finalLeft = dragRange;
if(isSmooth){
Mydraghelper.smoothSlideViewTo(mMainContent, finalLeft, 0);
invalidate();
}
else{
mMainContent.layout(finalLeft, 0, finalLeft+width, height);
}
}
protected void close() {
close(true);
}
public void close(boolean isSmooth) {
int finalLeft = 0;
if (isSmooth) {
// 平滑关闭
// "触发"一个平滑动画, 计算了第一帧
Mydraghelper.smoothSlideViewTo(mMainContent, finalLeft, 0);
invalidate();
} else {
mMainContent.layout(finalLeft, 0, finalLeft + width, height);
}
}
//五.
//布局加载完成后回调该函数
@Override
protected void onFinishInflate() {
super.onFinishInflate();
if (getChildCount() < 2) {
Log.i("duwenwne", "hahhaha");
throw new RuntimeException("You must have at least 2 child views");
}
if (!(getChildAt(0) instanceof ViewGroup) || !(getChildAt(1) instanceof ViewGroup)) {
Log.i("duwenwne", "hahhaha");
throw new IllegalArgumentException("Your child views must be ViewGroup");
}
mLeftContent = (ViewGroup) getChildAt(0);
mMainContent = (ViewGroup) getChildAt(1);
}
//OnMearsure方法之后调用
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
width = mMainContent.getMeasuredWidth();//测量View的宽(测量的宽度)
height = mLeftContent.getMeasuredHeight();
dragRange = (int) (width*0.6f);
}