您的位置:首页 > 移动开发 > Android开发

【Android】Android View的滑动实现

2016-04-20 15:49 549 查看
        首先,了解触控事件对象MotionEent中封装的一些常用变量:

//单点触摸按下动作
public static final int ACTION_DOWN = 0;
//单点触摸离开动作
public static final int ACTION_UP = 1;
//触摸点移动动作
public static final int ACTION_MOVE = 2;
//触摸动作取消
public static final int ACTION_CANCEL = 3;
//触摸动作超出边界
public static final int ACTION_OUTSIDE = 4;
//多点触摸按下动作
public static final int ACTION_POINTER_DOWN = 5;
//多点离开动作
public static final int ACTION_POINTER_UP = 6;


        再来,了解获取坐标值的各种方法:



(图片转自http://www.linuxidc.com/Linux/2015-11/125391.htm)

        其中,View 提供的获取坐标方法有:

getTop(): 获取到的是View自身的顶边到其父布局顶边的距离

getLeft(): 获取到的是View自身的左边到其父布局左边的距离

getRight():获取到的是View自身的右边到其父布局右边的距离

getBottom():获取到的是View自身的底部到其父布局底部的距离

        MotionEent 提供的方法有:

getX(): 获取点击事件距离控件左边的距离,即视图坐标

getY(): 获取点击事件距离控件顶边的距离,即视图坐标

getRawX(): 获取点击事件距离整个屏幕左边的距离,即绝对坐标

getRawY(): 获取点击事件距离整个屏幕顶边的距离,即绝对坐标

        项目结构:



布局结构:

<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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >

<com.example.scrolltest.widget.MyTextView
android:id="@+id/tv"
android:layout_width="65dp"
android:layout_height="65dp"
android:background="#949494"
/>

</RelativeLayout>


MainActivity.java

package com.example.scrolltest;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends Activity {

private TextView tv;

int lastX = 0;
int lastY = 0;
int offsetX = 0;
int offsetY = 0;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

tv = (TextView) findViewById(R.id.tv);
}
}


MyTextView.java

<span style="font-size:12px;">package com.example.scrolltest.widget;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Scroller;
import android.widget.TextView;

/**
* 一个自定义TextView
* 通过方法一 二 三实现拖拽滑动
* 当手指放开时通过方法四实现平滑滑动到原来位置
*/
public class MyTextView extends TextView{

private Scroller scroller;

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

public MyTextView(Context context, AttributeSet attrs) {
super(context, attrs);
scroller = new Scroller(getContext());
}

//按下时的坐标
int lastX = 0;
int lastY = 0;
//滑动时产生的偏移量
int offsetX = 0;
int offsetY = 0;
@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:
offsetX = x - lastX;
offsetY = y - lastY;
Log.d("Lutext", "offsetX = " + offsetX);
//方法一:监听触摸滑动,每次滑动调用layout方法重新对View布局
//			layout(getLeft() + offsetX,
//					getTop() + offsetY,
//					getRight() + offsetX,
//					getBottom() + offsetY);

//方法二:相当于系统提供地一个对左右 上下移动的API封装
//			offsetLeftAndRight(offsetX);
//			offsetTopAndBottom(offsetY);

//方法三:scrollTo scrollBy移动的是View的content,必须在ViewGroup中使用,才能移动子View
//这里其实移动的就是ViewGroup,所以偏移值为负数,即将ViewGroup向左移动3单位,则结果为子View向右移动3单位
//原文:想象手机屏幕是一个中空地盖板,盖板下面是一个巨大地画布,也就是我们想要显示的视图。当把这个盖板盖在画布上的某一处时,透过中间空的矩形,我们看见了手机屏幕上显示的视图,而画布上其他地方的视图,则被盖板盖住栏无法看见
((View)getParent()).scrollBy(-offsetX, -offsetY);
break;

case MotionEvent.ACTION_UP:
//方法四:Scroller
//步骤一:通过自定义View的构造方法来创建一个Scroller对象
//步骤二:重写computeScroll()方法,实现模拟滑动
//步骤三:通过scroller.startScroll开启模拟过程
View viewGroup = (View) getParent();
//手指离开时,执行scroller的滑动过程,必须是通过scrollby/scrollto滑动时才有效
scroller.startScroll(
//getScrollX/Y 获取子View的移动距离
viewGroup.getScrollX(),
viewGroup.getScrollY(),
-viewGroup.getScrollX(),
-viewGroup.getScrollY(), 5000);
Log.d("Lutext", "ACTION_UP");
Log.d("Lutext", "viewGroup.getScrollX() = " + viewGroup.getScrollX());
invalidate();
break;

default:
break;
}
return true;
}

/*
* @see android.widget.TextView#computeScroll()
*     只能在此方法中获取模拟过程中的scrollX和scrollY坐标
* 但computeScroll()方法是不会自动调用的,
* 只能通过invalidate() -> draw() -> computeScroll()
* 来间接调用computeScroll()方法,所以要在此方法中调用invalidate()
* 实现循环获取scrollX和scrollY的目的
*     当模拟过程结束后,scroller.computeScrollOffset()返回false,
* 从而中断循环,完成整个平滑的过程
*     此方法实际使用的就是scrollTo方法
*/
@Override
public void computeScroll() {
super.computeScroll();
//判断Scroller是否完成整个滑动
if(scroller.computeScrollOffset()) {
((View)getParent()).scrollTo(
//getCurrX/Y 获得当前滑动坐标
scroller.getCurrX(),
scroller.getCurrY());
//通过重绘来循环调用computeScroll
invalidate();
}
}

}</span>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android Scroller