最终效果
分析
我们实现一个跟手自由移动的效果。自定义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;
}
}
感谢阅读,下次再见。