实现方法一:自定义View
可随意拖动拖拽的View,限制拖动范围是父布局中;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.widget.ImageView;
public class DragActionButton extends ImageView {
private int parentHeight;
private int parentWidth;
private int lastX;
private int lastY;
private ViewGroup parent;
public DragActionButton(Context context) {
super(context);
}
public DragActionButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public DragActionButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int rawX = (int) event.getRawX();
int rawY = (int) event.getRawY();
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
getParent().requestDisallowInterceptTouchEvent(true);
lastX = rawX;
lastY = rawY;
if (getParent() != null) {
parent = (ViewGroup) getParent();
parentHeight = parent.getHeight();
parentWidth = parent.getWidth();
}
break;
case MotionEvent.ACTION_MOVE:
if (parentHeight <= 0.2 || parentWidth <= 0.2) {
break;
}
int dx = rawX - lastX;
int dy = rawY - lastY;
//这里修复一些华为手机无法触发点击事件
int distance = (int) Math.sqrt(dx * dx + dy * dy);
if (distance == 0) {
break;
}
float x = getX() + dx;
float y = getY() + dy;
//检测是否到达边缘 左上右下
x = x < 0 ? 0 : x + getWidth() > parentWidth ? parentWidth - getWidth() : x;
y = y < 0 ? 0 : y + getHeight() > parentHeight ? parentHeight - getHeight() : y;
setX(x);
setY(y);
lastX = rawX;
lastY = rawY;
Log.i("ACTION_MOVE", "getX=" + getX() + ";getY=" + getY() + ";parentWidth=" + parentWidth+ ";parentHeight=" + parentHeight);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
this.setAlpha(1.0f);
Log.i("ACTION_UP", "getX=" + getX() + ";getY=" + getY());
break;
}
return true;
}
}
下面是可以左右吸边的效果;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.DecelerateInterpolator;
import android.widget.ImageView;
import android.widget.Toast;
import androidx.annotation.Nullable;
public class DragFloatActionButton extends ImageView {
private int parentHeight;
private int parentWidth;
Handler handler = new Handler();
Runnable runnable = new Runnable() {
@Override
public void run() {
setAlpha(0.3f);
}
};
private int lastX;
private int lastY;
private ViewGroup parent;
public DragFloatActionButton(Context context) {
super(context);
}
public DragFloatActionButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public DragFloatActionButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
private int downX;
private int downY;
private long downTime;
@Override
public boolean onTouchEvent(MotionEvent event) {
int rawX = (int) event.getRawX();
int rawY = (int) event.getRawY();
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
this.setAlpha(0.9f);
getParent().requestDisallowInterceptTouchEvent(true);
lastX = rawX;
lastY = rawY;
downX = rawX;
downY = rawY;
downTime = System.currentTimeMillis();
if (getParent() != null) {
parent = (ViewGroup) getParent();
parentHeight = parent.getHeight();
parentWidth = parent.getWidth();
}
break;
case MotionEvent.ACTION_MOVE:
if (parentHeight <= 0.2 || parentWidth <= 0.2) {
break;
}
this.setAlpha(0.9f);
int dx = rawX - lastX;
int dy = rawY - lastY;
//这里修复一些华为手机无法触发点击事件
int distance = (int) Math.sqrt(dx * dx + dy * dy);
if (distance == 0) {
break;
}
float x = getX() + dx;
float y = getY() + dy;
//检测是否到达边缘 左上右下
x = x < 0 ? 0 : x + getWidth() > parentWidth ? parentWidth - getWidth() : x;
y = y < 0 ? 0 : y + getHeight() > parentHeight ? parentHeight - getHeight() : y;
setX(x);
setY(y);
lastX = rawX;
lastY = rawY;
Log.i("ACTION_MOVE", "getX=" + getX() + ";getY=" + getY() + ";parentWidth=" + parentWidth+ ";parentHeight=" + parentHeight);
break;
case MotionEvent.ACTION_UP:
moveHide(rawX);
if(onClickListener != null
&& Math.abs(downX - rawX) < 10
&& Math.abs(downY - rawY) < 10
&& System.currentTimeMillis() - downTime < 1000){
Log.i("ACTION_UP", "触发点击事件 ");
onClickListener.onClick(this);
}
break;
}
return true;
}
OnClickListener onClickListener;
@Override
public void setOnClickListener(@Nullable OnClickListener l) {
onClickListener = l;
}
private void moveHide(int rawX) {
if (rawX >= parentWidth / 2) {
//靠右吸附
animate().setInterpolator(new DecelerateInterpolator())
.setDuration(500)
.xBy(parentWidth - getWidth() - getX())
.start();
myRunable();
} else {
//靠左吸附
ObjectAnimator oa = ObjectAnimator.ofFloat(this, "x", getX(), 0);
oa.setInterpolator(new DecelerateInterpolator());
oa.setDuration(500);
oa.start();
myRunable();
}
}
private void myRunable() {
handler.removeCallbacks(runnable);
handler.postDelayed(runnable, 2000);
}
实现方法二:自定义ViewGroup
使用ViewDragHelper实现:
ViewDragHelper is a utility class for writing custom ViewGroups. It offers a number of useful operations and state tracking for allowing a user to drag and reposition views within their parent ViewGroup.
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.RelativeLayout;
import androidx.customview.widget.ViewDragHelper;
public class DragViewGroup extends RelativeLayout {
private ViewDragHelper mDragger;
private View mDragView;
public DragViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
this.setGravity(Gravity.CENTER);
mDragger = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {
@Override
public boolean tryCaptureView(View child, int pointerId) {
return true;
}
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
final int leftBound = getPaddingLeft();
final int rightBound = getWidth() - mDragView.getWidth();
final int newLeft = Math.min(Math.max(left, leftBound), rightBound);
return newLeft;
}
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
final int topBound = getPaddingTop();
final int bottomBound = getHeight() - mDragView.getHeight();
final int newTop = Math.min(Math.max(top, topBound), bottomBound);
return newTop;
}
//手指释放的时候回调
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
Log.i("onViewReleased", "view: x :"+mDragView.getX() +"y:"+mDragView.getY()
+"\nviewgroup: w: "+getWidth() + "h : "+getHeight());
}
});
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
return mDragger.shouldInterceptTouchEvent(event);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
mDragger.processTouchEvent(event);
return true;
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mDragView = getChildAt(0);
}
}
本站资源均来自互联网,仅供研究学习,禁止违法使用和商用,产生法律纠纷本站概不负责!如果侵犯了您的权益请与我们联系!
转载请注明出处: 免费源码网-免费的源码资源网站 » Android 可拖拽的View,限制在父布局中随意拖拽;拖拽结束后可左右吸边;
发表评论 取消回复