android圆圈拖动值变化,android AttachLayout 拖动吸边效果

package com.xin.view;

import android.content.Context;

import android.content.res.TypedArray;

import android.graphics.Rect;

import android.util.AttributeSet;

import android.view.MotionEvent;

import android.view.View;

import android.view.ViewGroup;

import android.view.ViewPropertyAnimator;

import android.view.animation.BounceInterpolator;

import android.widget.LinearLayout;

import androidx.annotation.Nullable;

import com.hrg.hefei.R;

/**

* 自定义View实现拖动并自动吸边效果

*

* 处理滑动和贴边 {@link #onTouchEvent(MotionEvent)}

* 处理事件分发 {@link #dispatchTouchEvent(MotionEvent)}

*

*

* @attr customIsAttach //是否需要自动吸边

* @attr customIsDrag //是否可拖曳

*/

public class AttachLayout extends LinearLayout {

private float mLastRawX;

private float mLastRawY;

private final String TAG = "AttachButton";

private boolean isDrug = false;

private int mRootMeasuredWidth = 0;

private int mRootMeasuredHeight = 0;

private int mRootTopY = 0;

private int customAttachDirect; /*-1不吸附 0所有的边 1左 2上 3右 4下 5左右 6上下 */

private boolean customIsDrag;

private boolean touchIsTargetView = true;

private int customIsTargetView;

private View targetView;

public AttachLayout(Context context) {

this(context, null);

}

public AttachLayout(Context context, @Nullable AttributeSet attrs) {

this(context, attrs, 0);

}

public AttachLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

initAttrs(context, attrs);

}

@Override

protected void onFinishInflate() {

super.onFinishInflate();

if (customIsTargetView > 0) {

targetView = findViewById(customIsTargetView);

}

}

/**

* 初始化自定义属性

*/

private void initAttrs(Context context, AttributeSet attrs) {

TypedArray mTypedAttay = context.obtainStyledAttributes(attrs, R.styleable.AttachLayout);

customAttachDirect = mTypedAttay.getInteger(R.styleable.AttachLayout_customAttachDirect, 0);

customIsDrag = mTypedAttay.getBoolean(R.styleable.AttachLayout_customIsDrag, true);

customIsTargetView = mTypedAttay.getResourceId(R.styleable.AttachLayout_customIsTargetView, 0);

mTypedAttay.recycle();

}

@Override

public boolean dispatchTouchEvent(MotionEvent event) {

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

touchIsTargetView = true;

}

if (targetView != null) {

// /*判断是否有目标view,若有不在目标view内不执行*/

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN://手指按下

Rect rect = new Rect();

targetView.getHitRect(rect);

if (!rect.contains((int) event.getX(), (int) event.getY())) {

touchIsTargetView = false;

}

}

}

if (touchIsTargetView) {

doTouch(event);

}

return super.dispatchTouchEvent(event);

}

@Override

public boolean onTouchEvent(MotionEvent ev) {

//判断是否需要滑动

// doTouch(ev); /*不能放在这,放在这子view收不到事件了*/

//是否拦截事件

if (isDrug) {

return true;

}

return super.onTouchEvent(ev);

}

private void doTouch(MotionEvent ev) {

if (customIsDrag) {

//当前手指的坐标

float mRawX = ev.getRawX();

float mRawY = ev.getRawY();

switch (ev.getAction()) {

case MotionEvent.ACTION_DOWN://手指按下

isDrug = false;

//记录按下的位置

mLastRawX = mRawX;

mLastRawY = mRawY;

ViewGroup mViewGroup = (ViewGroup) getParent();

if (mViewGroup != null) {

int[] location = new int[2];

mViewGroup.getLocationInWindow(location);

//获取父布局的高度

mRootMeasuredHeight = mViewGroup.getMeasuredHeight();

mRootMeasuredWidth = mViewGroup.getMeasuredWidth();

//获取父布局顶点的坐标

mRootTopY = location[1];

}

break;

case MotionEvent.ACTION_MOVE://手指滑动

if (mRawX >= 0 && mRawX <= mRootMeasuredWidth && mRawY >= mRootTopY && mRawY <= (mRootMeasuredHeight + mRootTopY)) {

//手指X轴滑动距离

float differenceValueX = mRawX - mLastRawX;

//手指Y轴滑动距离

float differenceValueY = mRawY - mLastRawY;

//判断是否为拖动操作

if (!isDrug) {

if (Math.sqrt(differenceValueX * differenceValueX + differenceValueY * differenceValueY) < 2) {

isDrug = false;

} else {

isDrug = true;

}

}

//获取手指按下的距离与控件本身X轴的距离

float ownX = getX();

//获取手指按下的距离与控件本身Y轴的距离

float ownY = getY();

//理论中X轴拖动的距离

float endX = ownX + differenceValueX;

//理论中Y轴拖动的距离

float endY = ownY + differenceValueY;

//X轴可以拖动的最大距离

float maxX = mRootMeasuredWidth - getWidth();

//Y轴可以拖动的最大距离

float maxY = mRootMeasuredHeight - getHeight();

//X轴边界限制

endX = endX < 0 ? 0 : endX > maxX ? maxX : endX;

//Y轴边界限制

endY = endY < 0 ? 0 : endY > maxY ? maxY : endY;

//开始移动

setX(endX);

setY(endY);

//记录位置

mLastRawX = mRawX;

mLastRawY = mRawY;

}

break;

case MotionEvent.ACTION_UP://手指离开

//根据自定义属性判断是否需要贴边

if (customAttachDirect >= 0 && isDrug) {

//判断是否为点击事件 0所有的边 1左 2上 3右 4下 5左右 6上下

float centerX = mRootMeasuredWidth / 2;

float centerY = mRootMeasuredHeight / 2;

float x = -1, y = -1;

if (customAttachDirect == 1) { /*左*/

x = 0;

y = -1;

} else if (customAttachDirect == 2) { /*上*/

x = -1;

y = 0;

} else if (customAttachDirect == 3) { /*右*/

x = mRootMeasuredWidth - getWidth();

y = -1;

} else if (customAttachDirect == 4) {

x = -1;

y = mRootMeasuredWidth - getHeight();

} else if (customAttachDirect == 5) { /*左右*/

x = mLastRawX <= centerX ? 0 : (mRootMeasuredWidth - getWidth());

y = -1;

} else if (customAttachDirect == 6) { /*上下*/

x = -1;

y = mLastRawY <= centerY ? 0 : (mRootMeasuredHeight - getHeight());

} else if (customAttachDirect == 0) { /*距那个边近去那个*/

// TODO: 2020/5/28 0028

}

//自动贴边

ViewPropertyAnimator animator = AttachLayout.this.animate()

.setInterpolator(new BounceInterpolator())

.setDuration(500);

if (x >= 0) {

animator.x(x);

}

if (y >= 0) {

animator.y(y);

}

animator.start();

}

break;

}

}

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值