【Android】两种方式实现可拖拽的控件(带吸附效果)

废话不多说,开门见山,实现的效果如下图所示,手指能拖拽悬浮球移动,并会根据距离判断自动吸附于屏幕边缘,其半边隐藏于屏幕外。效果图

方式一:自定义View重写onTouchEvent

onTouchEvent(MotionEvent event)是手机屏幕事件的处理方法,参数event为手机屏幕触摸事件封装类的对象,其中封装了该事件的所有信息;例如触摸的位置、触摸的类型以及触摸的时间等;该对象会在用户触摸手机屏幕时被创建。

开发中经常要用到的状态有以下三种,可以通过event.getAction()获得。

  • 手指按下:MotionEvent.ACTION_DOWN
  • 手指在屏幕上移动:MotionEvent.ACTION_MOVE
  • 手指抬起:MotionEvent.ACTION_UP

现在通过一个示例来实现可拖拽、自动吸附的控件。自定义一个MovedImageButton继承自ImageButton,然后重写onTouchEvent方法,在该方法中,event.getX()、event.getY() 是用来获取触摸点在控件上的实时位置,然后用 lastX、lastY 来记录按下的瞬间触摸点在控件上的位置。

ACTION_MOVE 状态触发后,计算出手指在x轴和y轴的偏移量,再调用 layout(int l,int t,int r,int b) 方法,此方法用来重新绘制控件位置,4个参数分别表示控件左上角(l、t)和右下角(r,b)相对于 屏幕 的坐标,当然也可以用offsetLeftAndRight(int offsetX)、offsetTopAndBottom(int offsetY) 方法实现同样效果;最后手指离开屏幕的瞬间。

触发ACTION_UP状态后,此时控件需要移动到屏幕边缘,实现吸附效果,这里使用了ObjectAnimator或是控件自带的animate() 方法来实现自动移动的动画,另外添加了对距离的判断,以此选择停靠在屏幕哪个边缘。

public class MovedImageButton extends android.support.v7.widget.AppCompatImageButton {
   

    private int lastX;
    private int lastY;
    private float screenWidth;

    public MovedImageButton(Context context) {
   
        super(context);
    }

    public MovedImageButton(Context context, AttributeSet attrs) {
   
        super(context, attrs);
    }

    public MovedImageButton(Context context, AttributeSet attrs, int defStyleAttr) {
   
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
   
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        DisplayMetrics dm = getResources().getDisplayMetrics();
        screenWidth =  dm.widthPixels;
    }

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public boolean onTouchEvent(MotionEvent event) {
   
        int x = (int) event.getX();
        int y = (int) event.getY();
        switch (event.getAction()){
   
            case MotionEvent.ACTION_DOWN:
                lastX = x;
                lastY = y;
                break;
            case MotionEvent.ACTION_MOVE:
                int offsetX = x-lastX;
                int offsetY = y-lastY;
                //第一种方法
                layout(getLeft()+offsetX,
                        getTop()+offsetY,
                        getRight()+offsetX,
                        getBottom()+offsetY);
                //第二种方法
                //offsetLeftAndRight(offsetX);
                //offsetTopAndBottom(offsetY);
                break;
            case MotionEvent.ACTION_UP:
                adsorbAnim(event.getRawX(), event.getRawY())
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值