ImageVerifierCode 换一换
格式:DOCX , 页数:20 ,大小:70.78KB ,
资源ID:20395567      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/20395567.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(手势滑动之玩转onTouchEvent与ScrollerWord文档格式.docx)为本站会员(b****5)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

手势滑动之玩转onTouchEvent与ScrollerWord文档格式.docx

1、xml version=1.0 encoding=utf-8LinearLayout xmlns:android= android:id=+id/content_scroll_methodlayout_width=match_parentlayout_height=orientation=verticalgravity=center +id/btn_scroll_byscrollBy(int,int)/LinearLayout这是Java代码:ViewGroup mContentRoot;Overrideprotected void onCreate(Bundle savedInstanceS

2、tate) super.onCreate(savedInstanceState); . mContentRoot = (ViewGroup) findViewById(R.id.content_scroll_method); findViewById(R.id.btn_scroll_to).setOnClickListener(this); findViewById(R.id.btn_scroll_by).setOnClickListener(this);private void onClick(View v) int id = v.getId(); switch (id) case R.id

3、.btn_scroll_to: mContentRoot.scrollTo(100, 100); break; case R.id.btn_scroll_by: mContentRoot.scrollBy(10, 20);这个很好理解了,点击scrollTo()按钮的时候调用Layout的scrollTo(int, int)放,让Layout的content滚动到相对Layout初始位置的(100, 100)处;点击scrooBy()按钮的时候调用Layout的scrollBy(int, int)让Layout的content滚动到相对Layout当前位置的(10, 20)处,来看看效果吧:我

4、们发现点击scrollTo()按钮的时候,滚动了一下,然后再点就不动了,因为此时Layout的content已经滚动到相对于它初始位置的(100,100)处了,所以再点它还是到这里,所以再次点击就看起来不动了。点击scrollBy()按钮的时候,发现Layout的content一直有在滚动,是因为无论何时,content的相对位置与当前位置都是不同的,所以它总是会去到一个新的位置,所以再次点击会一直滚动。注意:这里我们也发现scrollTo(int, int)与scrollBy(int, int)传入的值都是正数,经过我实验得出,x传入正数则向左移动,传入负数则向右移动;y传入正数则向上移动,

5、传入负数则向下移动,且这个xy的值是像素。这里和Android坐标系是相反的,不日我将新开一篇博客来专门讲这个问题。我们理解了View#scrollTo(int, int)和View#scrollBy(int, int)后结合View#onTouchEvent(MotionEvent)就可以做很多事了。View#onTouchEvent(MotionEvent)对于View#onTouchEvent(MotionEvent)方法,它是当View接受到触摸事件时被调用(暂不关心事件分发),第一我们从它可以拿到DOWN、MOVE、UP、CANCEL几个关键事件,第二我们可以拿到每个DOWN等事件发

6、生时手指在屏幕上的位置和手指在View内的位置。基于此我们可以想到做很多事,假如我们在手指DOWN时记录手指的xy,在MOVE时根据DOWN时的xy来计算手指滑动的距离,然后让View发生一个移动,在手指UP/CANCEL时让View回到最开始的位置,因此我们做了第一个效果,下面来做具体的代码分析。我们定义一个ScrollLayout,然后继承自LinearLayout,在xml中引用,然后在ScrollLayout中放一个TextView,并让内容居中:com.yanzhenjie.defineview.widget.ScrollLayout xmlns:TextView按住我拖动试试/co

7、m.yanzhenjie.defineview.widget.ScrollLayout布局就是这样的,根据上面的分析我们实现ScrollLayout的具体代码,请看:/ 手指最后在View中的坐标。private int mLastX;private int mLastY;/ 手指按下时View的相对坐标。private int mDownViewX;private int mDownViewY;public boolean onTouchEvent(MotionEvent event) / 第一步,记录手指在view的坐标。 int x = (int) event.getRawX(); in

8、t y = (int) event.getRawY(); int action = event.getAction(); switch (action) case MotionEvent.ACTION_DOWN: / 记录View相对于初始位置的滚动坐标。 mDownViewX = getScrollX(); mDownViewY = getScrollY(); / 更新手指此时的坐标。 mLastX = x; mLastY = y; return true; case MotionEvent.ACTION_MOVE: / 计算手指此时的坐标和上次的坐标滑动的距离。 int dy = y -

9、mLastY; int dx = x - mLastX; / 滑动相对距离。 scrollBy(-dx, -dy); case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: scrollTo(mDownViewX, mDownViewY); return super.onTouchEvent(event);那么这里再来说明两个方法:View#getScrollX() 获取View相对于它初始位置X方向的滚动量。View#getScrollY() 获取View相对于它初始位置Y方向的滚动量。根据我们上面的分析,这里处理了四个事件,分

10、别是:MotionEvent.ACTION_DOWNMotionEvent.ACTION_MOVEMotionEvent.ACTION_UPMotionEvent.ACTION_CANCEL第一步,因为ACTION_DOWN、ACTION_MOVE中都需要记录手指当前坐标,所以一进入就记录了event.getRawX()和event.getRawY()。第二步,ACTION_DOWN手指按下时被调用,在一次触摸中只会被调用一次,在ACTION_DOWN的时候记录了content相对于最开始滚动的坐标getScrollX()和getScrollY(),在我们我们手指松开时它滚动了多少getScr

11、ollX()和多少getScrollY(),那么我们就调用scrollTo(int, int)滚动多少-getScrollX()和多少-getScrollY(),这样它不就回到初始位置了吗?同时记录了手指此时的坐标,用来在ACTION_MOVE的时候计算第一次ACTION_MOVE时的移动距离。第三步,ACTION_MOVE会在手指移动的时候调用,所以它会调用多次,所以每次需要计算与上次的手指坐标的滑动距离,并且更新本次的手指坐标,然后调用scrollBy(int, int)去滑动当前手指与上次手指的坐标(当前View的位置)的距离。第四步,ACTION_UP在手指抬起时被调用,ACTION_

12、CANCEL在手指滑动这个View的区域时被调用,此时我们调用scrollTo(int, int)回到最初的位置。我们来看看效果:嗯效果已经实现了,但是我们发现和开头演示的效果有点出入,就是手指松开时View一下子就回去了而不是平滑的回到最初的位置,因此我们需要用到Scroller。ScrollerScroller是手指滑动中比较重要的一个辅助类,可以辅助我们完成一些动画参数的计算等,下面把它的几个重要的方法做个简单解释。Scroller#startScroll(int startX, int startY, int dx, int dy)Scroller#startScroll(int st

13、artX, int startY, int dx, int dy, int duration) 这俩方法几乎是一样的,用来标记一个View想要从哪里移动到哪里。 startX,x方向从哪里开始移动。startY,y方向从哪里开始移动。dx,x方向移动多远。dy,y方向移动多远。duration,这个移动操作需要多少时间执行完,默认是250毫秒。当然光这个方法是不够的,它只是标记一个位置和时间,那么怎么计算呢?Scroller#computeScrollOffset() 这个方法用来计算当前你想知道的一个新位置,Scroller会自动根据标记时的坐标、时间、当前位置计算出一个新位置,记录到内部,

14、我们可以通过Scroller#getCurrX()和Scroller#getCurrY()获取的新的位置。要知道的是,它计算出的新位置是一个闭区间x, y,而且会在你调用startScroll传入的时间内渐渐从你指定的int startX和int startY移动int dx和int dy的距离,所以我们每次调用Scroller#computeScrollOffset()后再调用View的scrollTo(int, int)然后传入Scroller#getCurrX()和Scroller#getCurrY()就可以得到一个渐渐移动的效果。同时这个方法有一个返回值是boolean类型的,内部是用

15、一个boolean来记录是否完成的,在调用Scroller#startScroll)时会把这个boolean参数置为false。内部逻辑是先判断startScroll()动画是否还在继续,如果没有完成则计算最新位置,计算最新位置前会对duration做判断,第一如果时间没到,则真正的计算位置,并且返回true,第二如果时间到了,把记录是否继续的boolean成员变量标记完成,并直接赋值最新位置为最终目的位置,并且返回true;如果startScroll()已经完成则直接返回false。我们判断Scroller#computeScrollOffset()是true时说明还没完成,此时拿到Scro

16、ller#getCurrX()和Scroller#getCurrY()做一个滚动,待会代码中可以看到这个逻辑。Scroller#getCurrX()Scroller#getCurrY() 这两个方法就是拿到通过Scroller#computeScrollOffset()计算出的新的位置,上面也解释过了。Scroller.isFinished() 上次的动画是否完成。Scroller.abortAnimation() 取消上次的动画。这里要强调的是Scroller.isFinished()和一般是配套使用的,一般咋ACTION_DWON的时候判断是否完成,如果没有完成咋取消动画。基于此,我们完善

17、上面的效果,让它平滑滚动,所以我们来完善一下。View#onTouchEvent(MotionEvent)与Scroller结合完善动画private Scroller mScroller; public ScrollLayout(Context context) this(context, null, 0);public ScrollLayout(Context context, AttributeSet attrs) this(context, attrs, 0);public ScrollLayout(Context context, AttributeSet attrs, int de

18、fStyleAttr) super(context, attrs, defStyleAttr); mScroller = new Scroller(context); if (!mScroller.isFinished() / 如果上次的调用没有执行完就取消。 mScroller.abortAnimation(); / XY都从滑动的距离回去,最后一个参数是多少毫秒内执行完这个动作。 mScroller.startScroll(getScrollX(), getScrollY(), -getScrollX(), -getScrollY(), 1000); invalidate();/* * 这

19、个方法在调用了invalidate()后被回调。 */public void computeScroll() if (mSputeScrollOffset() / 计算新位置,并判断上一个滚动是否完成。 scrollTo(mScroller.getCurrX(), mScroller.getCurrY();/ 再次调用computeScroll。第一步,在构造方法中初始化Scroller。第二步,在ACTION_DOWN时去掉最开始记录的content的初始位置,下面讲为什么。并且判断Scroller的动画是否完成,没有完成则取消。第三步,在ACTION_MOVE的时候调用滚动,让View跟着

20、手指走。第四步,在ACTION_UP和ACTION_CANCEL时让View平滑滚动到最初位置。根据上面Scroller的分析,这里可以调用Scroller#startScroll(startX, startY, dx, dy, duration)记录开始位置,和滑动的距离以及指定动画完成的时间。(startX, startY)传入当前content的相对与最开始滚动的位置(getScrollX(), getScrollY()。(dx, dy)要传入要平滑滑动的距离,那么传什么呢?既然它滚动了(getScrollX(), getScrollY(),那么我们就让它滚这么多的距离回去不久行了?所以

21、我们传入(-getScrollX(), -getScrollY()。duration滚动时间,我们传个800毫秒,1000毫秒的都可以,默认是250毫秒。第五步,调用invalidate()/postInvalidate()刷新View,最底层View会调用一系列方法,这里我们重写其中computeScroll()方法。我们看到invalidate()和postInvalidate(),invalidate()在当前线程调用,也就是主线程,这里我们使用invalidate();postInvalidate()一般在子线程需要刷新View时调用。computeScroll()方法是用来计算滚动的

22、,我们平滑滚动时不就是要它么。第六步,根据上面Scroller的分析,在computeScroll()中此时调用SputeScrollOffset()再好不过了,计算出一个新的相对位置,然后调用scrollTo(int, int)滑动过去。第七步,在computeScroll()中scrollTo(int, int)后调用invalidate()computeScroll刷新视图,呈现出一个动画的效果。View#onTouchEvent(MotionEvent)与Scroller再升级View#onTouchEvent(MotionEvent)与Scroller结合再升级,这一节是基于上一节的

23、,如果你没看上一节,那么最好看完再看这个,不然非常可能看不懂。下面我们来完成文中开头的第二个效果,一个模拟ViewPager翻页且加弹性动画的效果。上面的自定义ScrollLayout是继承LinearLayout的,下面我们新建一个ScrollPager的继承ViewGroup,来完成目标:public class ScrollPager extends ViewGroup public ScrollPager(Context context) public ScrollPager(Context context, AttributeSet attrs) public ScrollPager(Context context, AttributeSet attrs, int defStyleAttr) 然后我们把布局写好,放三个Layout,高度为100dp,宽度都为match_parent:com.yanzhenjie.defineview.widget.ScrollPagerxmlns:LinearLayoutlayout_height=

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1