【Android】Android View的滑动实现
2016-04-20 15:49
549 查看
首先,了解触控事件对象MotionEent中封装的一些常用变量:
再来,了解获取坐标值的各种方法:
(图片转自http://www.linuxidc.com/Linux/2015-11/125391.htm)
其中,View 提供的获取坐标方法有:
getTop(): 获取到的是View自身的顶边到其父布局顶边的距离
getLeft(): 获取到的是View自身的左边到其父布局左边的距离
getRight():获取到的是View自身的右边到其父布局右边的距离
getBottom():获取到的是View自身的底部到其父布局底部的距离
MotionEent 提供的方法有:
getX(): 获取点击事件距离控件左边的距离,即视图坐标
getY(): 获取点击事件距离控件顶边的距离,即视图坐标
getRawX(): 获取点击事件距离整个屏幕左边的距离,即绝对坐标
getRawY(): 获取点击事件距离整个屏幕顶边的距离,即绝对坐标
项目结构:
布局结构:
MainActivity.java
MyTextView.java
//单点触摸按下动作 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>
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories