Android——自定义View随手自由移动

本文介绍如何在Android中创建自定义View,并实现其在屏幕上自由拖动的功能。通过重写onTouchEvent方法处理ACTION_MOVE事件,利用nineoldandroids库中的ViewHelper实现View的平滑移动。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考《Android开发艺术探索》

最终效果

这里写图片描述

分析

我们实现一个跟手自由移动的效果。自定义View,拖动它可以让它在整个屏幕随意移动。
这个View实现起来很简单。我们只需要重写它的 onTouchEvent()方法并处理ACTION_MOVE事件,根据两次滑动之间的距离就可以实现它的滑动了。如下:

首先

打开 Android Studio,新建 ViewTest 项目。
由于我们需要用到动画兼容库nineoldandroids中ViewHelper这个类,所以我们需要导入库

build.gradle

compile 'com.nineoldandroids:library:2.4.0'

然后新建一个Scroll.java 继承 ImageView 并实现三个构造方法。代码如下:

public class Scroll extends ImageView {


    public Scroll(Context context) {
        this(context, null);
    }

    public Scroll(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

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

}

并重写onTouchEvent()方法,代码如下

@Override
    public boolean onTouchEvent(MotionEvent event) {

        //获取屏幕的位置 xy值
        int x = (int) event.getRawX();
        int y = (int) event.getRawY();

        switch (event.getAction()){

            case MotionEvent.ACTION_DOWN:

                break;

            case MotionEvent.ACTION_MOVE:

                int deltaX = x - mLastX;
                int deltaY = y - mLastY;

                int translationX = (int) (ViewHelper.getTranslationX(this) + deltaX);
                int translationY = (int) (ViewHelper.getTranslationY(this) + deltaY);

                ViewHelper.setTranslationX(this,translationX);
                ViewHelper.setTranslationY(this,translationY);

                break;
            case MotionEvent.ACTION_UP:
                break;
        }
        //记录View移动的初始值
        mLastX = x;
        mLastY = y;
        return true;
    }

getX/getY——getRawX/getRawY

在这里面我们先来理解getX,getRawX的区别:

getX/getY:返回的是相对于当前View左上角的x 和 y 坐标。
getRawX/getRawY:返回的是相对于手机屏幕左上角的x 和 y 坐标。

getTranslationX

ViewHelper.getTranslationY(this)计算该View的偏移量,初始值为0,向左偏移值为负,向右偏移值为正。

setTranslationX

ViewHelper.setTranslationX (View view, float translationX)这个方法。

view:是要移动的控件
translationX:是要移动的距离。


上述代码:首先我们通过getRawX()方法和getRawY()方法来获取手指当前的坐标,注意不能使用getX()方法和getY()方法,因为个是要全屏滑动的,所以需要获取当前点击事件在屏幕中的坐标而不是相对于View本身的坐标。并且声明两个变量mLastX,mLastY,来记录view初始的位置,然后通过 两点的坐标计算出两次滑动的之间的位移,有了这个位移就可以移动当前的View,移动方法采用的是动画兼容库nineoldandroids中的ViewHelper类所提供的setTranslationX 和 setTranslationY方法。其中translationX、translationY是View左上角相对于父布局的偏移量。

引用

引用自定义View

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <com.example.pc.day11.Scroll
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_launcher"/>
</RelativeLayout>

最后

附上完整代码:

package com.example.pc.day11;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.ImageView;

import com.nineoldandroids.view.ViewHelper;

/**
 * Created by PC on 2017/11/29.
 */
public class Scroll extends ImageView {

    int mLastX;
    int mLastY;

    public Scroll(Context context) {
        this(context,null);
    }

    public Scroll(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }

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




    @Override
    public boolean onTouchEvent(MotionEvent event) {

        //获取屏幕的位置 xy值
        int x = (int) event.getRawX();
        int y = (int) event.getRawY();

        switch (event.getAction()){

            case MotionEvent.ACTION_DOWN:

                break;

            case MotionEvent.ACTION_MOVE:

                int deltaX = x - mLastX;
                int deltaY = y - mLastY;

                int translationX = (int) (ViewHelper.getTranslationX(this) + deltaX);
                int translationY = (int) (ViewHelper.getTranslationY(this) + deltaY);

                ViewHelper.setTranslationX(this,translationX);
                ViewHelper.setTranslationY(this,translationY);

                break;
            case MotionEvent.ACTION_UP:
                break;
        }
        //记录View移动的初始值
        mLastX = x;
        mLastY = y;
        return true;
    }
}

感谢阅读,下次再见。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值