转载请注明原创出处,谢谢!
public class DragStickLinearLayout extends LinearLayout {
// 是否吸边
private boolean mIsStick = true;
private float v = 1.f; // 宽比例(适配横竖屏)(保证取值在0-1)
private float h = 0.8f; // 高比例(适配横竖屏)(保证取值在0-1)
private int mTop = 0;
private int mLeft = 0;
private ViewDragHelper mViewDragHelper;
public DragStickLinearLayout(@NonNull Context context) {
super(context);
init();
}
public DragStickLinearLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public DragStickLinearLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
v = SpUtils.getFloat("v", v);
h = SpUtils.getFloat("h", h);
mViewDragHelper = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {
@Override
public boolean tryCaptureView(@NonNull View child, int pointerId) {
return true;
}
@Override
public int clampViewPositionVertical(@NonNull View child, int top, int dy) {
if (top <= 0) {
mTop = 0;
} else {
mTop = Math.min(top, getMeasuredHeight() - child.getMeasuredHeight());
}
return mTop;
}
@Override
public int clampViewPositionHorizontal(@NonNull View child, int left, int dx) {
if (left <= 0) {
mLeft = 0;
} else {
mLeft = Math.min(left, getMeasuredWidth() - child.getMeasuredWidth());
}
return mLeft;
}
@Override
public int getViewHorizontalDragRange(@NonNull View child) {
return 1; // 返回1不影响子view的点击事件
}
@Override
public int getViewVerticalDragRange(@NonNull View child) {
return 1; // 返回1不影响子view的点击事件
}
// @Override
// public void onViewDragStateChanged(int state) {
// super.onViewDragStateChanged(state);
// if (state == ViewDragHelper.STATE_IDLE) {
// Log.i("TAGaaaaaaaaaaaa", "onViewDragStateChangedtop: " + getChildAt(0).getTop());
// Log.i("TAGaaaaaaaaaaaa", "onViewDragStateChangedleft: " + getChildAt(0).getLeft());
// }
// }
// @Override
// public void onViewPositionChanged(@NonNull View changedView, int left, int top, int dx, int dy) {
// super.onViewPositionChanged(changedView, left, top, dx, dy);
// Log.i("TAGaaaaaaaaaaaa", "onViewPositionChanged: l:" + left + " t:" + top + " " + changedView);
// }
@Override
public void onViewReleased(@NonNull View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
if (mIsStick) {
if (mLeft < (getMeasuredWidth() - getChildAt(0).getMeasuredWidth()) / 2) { // 贴左边
mLeft = 0;
((ImageView) getChildAt(0)).setImageResource(R.drawable.iv_ai_start);
} else { // 贴右边
mLeft = getMeasuredWidth() - releasedChild.getMeasuredWidth();
((ImageView) getChildAt(0)).setImageResource(R.drawable.iv_ai_end);
}
mViewDragHelper.smoothSlideViewTo(getChildAt(0), mLeft, mTop);
ViewCompat.postInvalidateOnAnimation(DragStickLinearLayout.this);
}
}
});
}
@Override
public void computeScroll() {
super.computeScroll();
// 处理贴边
if (mViewDragHelper.continueSettling(true)) {
invalidate();
}
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return mViewDragHelper.shouldInterceptTouchEvent(ev);
}
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_UP) {
// 保存top和left的比例
int width = getMeasuredWidth() - getChildAt(0).getMeasuredWidth();
int height = getMeasuredHeight() - getChildAt(0).getMeasuredHeight();
h = 1.f * mTop / height;
if (mIsStick) {
// 切边
if (mLeft < width / 2) {
v = 0.f;
} else {
v = 1.f;
}
} else {
v = 1.f * mLeft / width;
}
// 保存v和h(保证取值在0-1)
SpUtils.putFloat("v", Math.min(1, Math.max(0, v)));
SpUtils.putFloat("h", Math.min(1, Math.max(0, h)));
} else if (ev.getAction() == MotionEvent.ACTION_DOWN) {
((ImageView) getChildAt(0)).setImageResource(R.drawable.iv_ai_move);
}
mViewDragHelper.processTouchEvent(ev);
// 判断触摸是否在子View的范围内,不影响底部view的时间
return mViewDragHelper.isViewUnder(getChildAt(0), (int) ev.getX(), (int) ev.getY());
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
int width = getMeasuredWidth() - getChildAt(0).getMeasuredWidth();
int height = getMeasuredHeight() - getChildAt(0).getMeasuredHeight();
mTop = (int) (height * h);
mLeft = (int) (width * v);
getChildAt(0).layout(mLeft, mTop, mLeft + getChildAt(0).getMeasuredWidth(), mTop + getChildAt(0).getMeasuredHeight());
if (isFirst) {
isFirst = false;
if (mLeft <= 0) {
((ImageView) getChildAt(0)).setImageResource(R.drawable.iv_ai_start);
} else {
((ImageView) getChildAt(0)).setImageResource(R.drawable.iv_ai_end);
}
}
}
private boolean isFirst = true;
public void initVH(float v, float h) {
this.v = v;
this.h = h;
invalidate();
}
}