Android View事件体系

本文详细介绍了Android开发中关于View滑动控制(包括scrollTo/scrollBy、动画和改变LayoutParams)、Scroller实现弹性滑动、事件分发机制(如dispatchTouchEvent和解决滑动冲突的方法)等内容,为开发者提供了实用的技术指导。
2.1 使用scrollTo/scrollBy
  • scrollTo和scrollBy只能改变View内容的位置而不能改变View在布局中的位置
2.2 使用动画

主要是操作View的translationX和translationY属性.

//View动画

val loadAnimation = AnimationUtils.loadAnimation(applicationContext, R.anim.animation_scroll)

btn_animation_scroll.startAnimation(loadAnimation)

//属性动画

btn_animation_scroll.animate().translationX(200f).translationY(200f).start()

2.3 LayoutParams

val layoutParams = btn_layout_params.layoutParams as? FrameLayout.LayoutParams

layoutParams?.leftMargin = layoutParams?.leftMargin?.plus(100)

//或者btn_layout_params.setLayoutParams(params)

btn_layout_params.requestLayout()

2.4 View滑动总结
  • scrollTo/scrollBy:操作简单,适合对View内容的滑动;

  • 动画:操作简单,主要适用于没有交互的View和实现复杂的动画效果;

  • 改变布局参数:操作稍微复杂,适用于有交互的View。

3. View的弹性滑动

3.1 使用Scroller

原理: 调用startScroll()方法,其实里面并没有进行滑动,而是因为紧接着调用的invalidate(),导致View重绘.在View的draw方法里面又会去调用computeScroll方法.computeScroll是需要自己去实现的,computeScroll会去向Scroller获取当前的scrollX和scrollY(Scroller内部是根据时间去计算当前的scrollX和scrollY的值),然后又调用scrollTo,又invalidate(),又要重绘,如此反复.实现了弹性滑动.

View不断重绘,不断通过时间流逝来计算新的滑动位置,小幅度的滑动,最终形成了弹性滑动.

3.2 通过动画
  • 动画天生就自带弹性的属性,哈哈,自然没啥问题

  • 说点利用动画来实现一些动画不能实现的效果->动画可以不作用于任何View上,而是通过它在具体的时间内完成了整个动画过程,我们可以获取这个值,从而干一些操作.比如通过ValueAnimator在1000ms内从0-100,然后我们可以根据这个来画一个进度条,在1000ms内到达100%.

模仿Scroller来实现View的弹性滑动

final int startX = 0;

final int deltaX = 100;

ValueAnimator animator = ValueAnimator.ofInt(0,1).setDuration(1000);

animator.addUpdateListener(new AnimatorUpdateListener() {

@Override

public void onAnimationUpdate(ValueAnimator animator) {

float fraction = animator.getAnimatedFraction();

mButton1.scrollTo(startX + (int) (deltaX * fraction),0);

}

});

animator.start();

3.3 Handler.postDelayed

不断发生延时消息,不断scrollTo.发送消息无法精确地定时,系统的消息调度是需要时间的,并且所需时间不定.

3.4 Thread#sleep

4.事件分发

主要是3个方法: dispatchTouchEvent(),onInterceptTouchEvent(),onTouchEvent()

  • 从Activity的dispatchTouchEvent开始,然后传到PhoneWindow的superDispatchTouchEvent(),再传入DecorView的superDispatchTouchEvent(),即ViewGroup的dispatchTouchEvent.

  • 在ViewGroup的dispatchTouchEvent()中,先调用onInterceptTouchEvent(),判断是否需要拦截事件.默认是不拦截的,继续向子View传递事件,找到被点击的响应子View控件,调用该View的dispatchTouchEvent.至此,完成了从ViewGroup向子View事件传递的过程,子View也可能是ViewGroup,但是过程是一样的,类似的递归下去. 当ViewGroup拦截了事件时,自己处理事件,调用自身的onTouch()->onTouchEvent()->performClick()->onClick()

  • 当事件来到View这里,调用dispatchTouchEvent,调用View.onTouch(),如果这个方法返回true,那么事件已经被消费了,不用再继续往下传递了.如果返回false,那么消费事件,调用onTouchEvent().调用performClick(),调用onClick()

三者关系伪代码

public boolean dispatchTouchEvent(MotionEvent ev) {

boolean consume = false;

if (onInterceptTouchEvent(ev)) {

consume = onTouchEvent(ev);

} else {

consume = child.dispatchTouchEvent(ev);

}

return consume;

}

5. 解决滑动冲突

这里借用刚哥 安卓开发艺术探索中的图叙述一下

在这里插入图片描述

对于场景1,当用户左右滑动时,让外部的View拦截点击事件,当用户上下滑动时让内部的View拦截点击事件. 如何判断用户是上下还是左右滑动: 用2个按下点与抬起点的距离差判断,如果横向多,那么就是横向滑动,如果竖向多,就是竖向滑动.

对于场景2和3,需要根据具体的业务场景来判断当时应该让谁拦截事件.

抛开具体的场景,滑动冲突其实有一种通用的解决方式.

5.1 外部拦截法

外部拦截法,就是指点击事件都先经过父控件的处理,如果父控件需要这个事件就拦截,然后自己处理.不需要就不拦截,传递给子控件.

它的伪代码如下所示:

public boolean onInterceptTouchEvent(MotionEvent event) {

boolean intercepted = false;

int x = (int) event.getX();

int y = (int) event.getY();

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN: {

intercepted = false;

break;

}

case MotionEvent.ACTION_MOVE: {

if (父容器需要当前点击事件) {

intercepted = true;

} else {

intercepted = false;

}

最后

总之啊,家里没矿的同学们,如果你们想以后的日子过得好一些,多想想你们的业余时间怎么安排吧;

技术方面的提升肯定是重中之重,但是技术外的一些“软实力”也不能完全忽视,很多时候升职确实是因为你的技术足够强,但也与你的“软实力”密切相关

在这我也分享一份大佬自己收录整理的 Android学习PDF+架构视频+面试文档+源码笔记 ,还有高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料这些都是我闲暇还会反复翻阅并给下属员工学习的精品资料。在脑图中,每个知识点专题都配有相对应的实战项目,可以有效的帮助大家掌握知识点。

总之也是在这里帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习

相信自己,没有做不到的,只有想不到的

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

744)]

相信自己,没有做不到的,只有想不到的

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值