先贴一个实现的效果图(图片不会变色,应该是转换gif图的时候帧的问题):
使用ViewDragHelper遇到的问题:
- 因为需求是一个悬浮窗,悬浮窗布局包裹两个子布局,所以使用ViewDragHelper没法处理跟随滑动(或许是我不知道)
- 我做的只要求图片可以滑动,并且不可以滑出屏幕,图片不滑出屏幕有直接能用的方法可以用,但是多了个删除按钮,就需要判断滑到右边屏幕的时候去掉间距和删除按钮的宽度。
- 计算悬浮窗滑到水平距离距左边近还是右边,需要让悬浮窗落到相应位置。
跟随滑动具体实现方法
重写onViewPositionChanged方法,实时监听位置发生变化的回调,根据回调得到滑动的距离。然后手动移动删除按钮跟随图片移动。代码如下:
private void viewFollowChanged( int dx, int dy) {
mAutoBackView1.offsetTopAndBottom(dy);
mAutoBackView1.offsetLeftAndRight(dx);
invalidate();
}
设置只有按住图片可以滑动
mAutoBackView 表示图片那个view
重写tryCaptureView方法, return child == mAutoBackView;
计算悬浮窗落下位置的关键代码
if (x < (getMeasuredWidth() / 2f - releasedChild.getMeasuredWidth() / 2f)) {
x = 0;
} else {
x = getMeasuredWidth() - releasedChild.getMeasuredWidth()-50;
}
Log.e("dbj","x="+x+",y="+y);
// 移动到指定位置
mDragger.settleCapturedViewAt( (int) x, (int) y);
invalidate();
自定义View的全部,可以直接用
public class MyDragView extends RelativeLayout {
private ViewDragHelper mDragger;
private View mAutoBackView,mAutoBackView1;
public MyDragView(Context context, AttributeSet attrs) {
super(context, attrs);
mDragger = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {
@Override
public int getViewHorizontalDragRange(View child) {
//返回可拖动的子视图的水平运动范围(以像素为单位)的大小。
//对于不能垂直移动的视图,此方法应该返回0。
return getMeasuredWidth() - child.getMeasuredWidth();
}
@Override
public int getViewVerticalDragRange(View child) {
//返回可拖动的子视图的竖直运动范围(以像素为单位)的大小。
//对于不能垂直移动的视图,此方法应该返回0。
return getMeasuredHeight() - child.getMeasuredHeight();
}
@Override
public boolean tryCaptureView(View child, int pointerId) {
//返回true表view示捕获当前touch到的
return child == mAutoBackView;
}
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
if (left > getWidth() - child.getMeasuredWidth()){
//超出左侧边界处理
left = getWidth() - child.getMeasuredWidth();
} else if (left < 0) {
//超出右侧边界处理
left = 0;
}
return left;
}
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
if (top > getHeight() - child.getMeasuredHeight()){
//超出下边界处理
top = getHeight() - child.getMeasuredHeight();
} else if (top < 0) {
//超出上边界处理
top = 0;
}
return top;
}
@Override
public void onViewReleased(@NonNull View releasedChild, float xvel, float yvel) {
float x = releasedChild.getX();
float y = releasedChild.getY();
if (x < (getMeasuredWidth() / 2f - releasedChild.getMeasuredWidth() / 2f)) {
x = 0;
} else {
x = getMeasuredWidth() - releasedChild.getMeasuredWidth()-50;
}
Log.e("dbj","x="+x+",y="+y);
// 移动到指定位置
mDragger.settleCapturedViewAt( (int) x, (int) y);
invalidate();
super.onViewReleased(releasedChild, xvel, yvel);
/**
* 贴一个可以贴上下左右四边的代码
float x = releasedChild.getX();
float y = releasedChild.getY();
if (x < (getMeasuredWidth() / 2f - releasedChild.getMeasuredWidth() / 2f)) { // 0-x/2
if (x < releasedChild.getMeasuredWidth() / 3f) {
x = 0;
} else if (y < (releasedChild.getMeasuredHeight() * 3)) { // 0-y/3
y = 0;
} else if (y > (getMeasuredHeight() - releasedChild.getMeasuredHeight() * 3)) { // 0-(y-y/3)
y = getMeasuredHeight() - releasedChild.getMeasuredHeight();
} else {
x = 0;
}
} else { // x/2-x
if (x > getMeasuredWidth() - releasedChild.getMeasuredWidth() / 3f - releasedChild.getMeasuredWidth()) {
x = getMeasuredWidth() - releasedChild.getMeasuredWidth();
} else if (y < (releasedChild.getMeasuredHeight() * 3)) { // 0-y/3
y = 0;
} else if (y > (getMeasuredHeight() - releasedChild.getMeasuredHeight() * 3)) { // 0-(y-y/3)
y = getMeasuredHeight() - releasedChild.getMeasuredHeight();
} else {
x = getMeasuredWidth() - releasedChild.getMeasuredWidth();
}
}
// 移动到x,y
mDragger.settleCapturedViewAt((int) x, (int) y);
invalidate();
super.onViewReleased(releasedChild, xvel, yvel);
**/
}
@Override
public void onViewPositionChanged(@NonNull View changedView, int left, int top, int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
//位置发生改变时回调
viewFollowChanged( dx,dy);
}
});
}
private void viewFollowChanged( int dx, int dy) {
mAutoBackView1.offsetTopAndBottom(dy);
mAutoBackView1.offsetLeftAndRight(dx);
invalidate();
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
return mDragger.shouldInterceptTouchEvent(event);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
mDragger.processTouchEvent(event);
return true;
}
@Override
public void computeScroll() {
if (mDragger.continueSettling(true)) {
invalidate();
}
}
/**
* onFinishInflate 当View中所有的子控件均被映射成xml后触发
*/
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mAutoBackView = getChildAt(0);
mAutoBackView1=getChildAt(1);
}
有什么问题,可以在下面评论。