View体系(上)|青训营笔记(二)

简介: View 体系是较为复杂的,但是又非常重要的一个知识点。我们把这部分知识吃透吃熟是十分必要的,打卡第一天,我把View体系的第一部分知识整理出来,快来和我一起学习吧。

PropertyValuesHolder 组合动画

该动画无法实现前后关系,都是并行执行的。用法如下

val valuesHolder1 = PropertyValuesHolder.ofFloat("scaleX",1.0f,1.5f)
val valuesHolder2 = PropertyValuesHolder.ofFloat("rotationX",0.0f,90.0f,0.0f)
val valuesHolder3 = PropertyValuesHolder.ofFloat("alpha",1.0f,0.3f,1.0f)
        ObjectAnimator.ofPropertyValuesHolder(binding.coutomView,valuesHolder1,valuesHolder2,valuesHolder3).apply {
        duration = 2000
        start()
 }
复制代码

使用属性动画

//aimator.scale.xml
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="3000"
    android:propertyName="scaleX"
    android:valueFrom="1.0"
    android:valueTo="2.0"
    android:valueType="floatType">
</objectAnimator>
复制代码
AnimatorInflater.loadAnimator(this,R.animator.scale).apply {
    setTarget(binding.coutomView)
    start()
}
复制代码

Scroller




public void smoothScrollTo(int destX,int destY){
        int scrollX = getScrollX();
        int delta = destX - scrollX;
        mScroller.startScroll(scrollX,0,delta,0,2000);
        invalidate();
    }
@Override
    public void computeScroll() {
        super.computeScroll();
        if (mScroller.computeScrollOffset()){
            ((View)getParent()).scrollTo(mScroller.getCurrX(),mScroller.getCurrY());
            invalidate();
        }
    }
复制代码

Scroller 并不能直接实现滑动,他最大的功能是在 startScroll() 处保存传入的滑动信息。后面再不断调用到 computeScroll() 这个方法,使用其中的 scrollTo() 来实现滑动。

computeScroll() 中,在判断方法中会调用到 mScroller.computeScrollOffset() ,这是用于获取 scrollXscrollY 两个位置参数以及做出判断是否滑动结束。若是未滑动结束,就会让 computeScroll() 不断滑动重绘。

View事件分发

1.webp.jpg

Activity构成图

Activity 的层级基本如上所示,在 xml 文件中构建的布局就是在 contentParent 位置,也就是 contentView 位置。

分发机制

首先需要了解的是 MotionEvent ,当屏幕被点击 ->产生点击事件 ->MotionEvent 产生。

点击事件产生后层层下发,不断传递到根 ViewGroup

image.png

事件分发的三大方法

  • dispatchTouchEvent(MotionEvent event) : 用以事件分发。下面简称dTE()方法
  • onInterceptTouchEvent(MotionEvent e) : 用以拦截事件,在 dispatchTouchEvent(MotionEvent event) 中被调用来拦截。该方法只有 ViewGroup 中有, View 中没有
  • onTouchEvent(MotionEvent e) : 用以处理点击事件,在 dispatchTouchEvent(MotionEvent event) 中被调用。这个方法是 View 中的,但是由于 ViewGroup 是继承自 View 的,所以 ViewGroup 可以使用。下面简称oTE()方法

下面简述一下 dispatchTouchEvent(MotionEvent event) 方法,

//ViewGroup内
public boolean dispatchTouchEvent(MotionEvent ev){
    //拦截部分
    ...
        onInterceptTouchEvent(ev);
    ...
    //点击处理事件
    ...
        if(dispatchTransformedTouchEvent(ev,false,child,idBitsToAssign))
    ...
}
private boolean dispatchTransformedTouchEvent(MotionEvent event, boolean cancel,View child,int desiredPointerIdBits){
    ...
        if(child == null){
            handled = super.dispatchTouchEvent(event);
        }else{
            handled = child..dispatchTouchEvent(event);
        }
    ...
}
//View内
public boolean dispatchTouchEvent(MotionEvent ev){
    if(... && li.mOnTouchListener != null && li.mOnTouchListener.onTouch(this,event)){
        result = true;
    }
    if(!result && onTouchEvent(event)){
        result = true;
    }
}
复制代码

拦截的处理逻辑

1.webp.jpg

这其中的 允许拦截? ,一般通过子View的 requestDisallowInterceptTouchEvent 来设置,这也是处理滑动冲突的方法之一。

当事件在 ViewGroup 被拦截之后,后续的事件序列都交给其处理了

点击事件处理逻辑

1.webp.jpg

事件被拦截后会被当前的 ViewGroup 处理,上图就是详细的点击事件处理流程图。

事件分发传递规则

View 的事件分发是,首先 View 层层分发下来,若是 onInterceptTouchEvent(ev)true 就拦截,为 false 就继续下发。

当某一层级拦截后,就调用 onTouchEvent(event) 来处理,若是该层无法处理,就传递给父层的 onTouchEvent(event) 来处理。如此层层传递直到有对应可以处理的父层。

整个事件的分发过程看起来复杂,当最终归于三大方法可以用下面的伪代码表示

public boolean dispatchTouchEvent(MotionEvent ev){
    boolean result = false;
    if(onInterceptTouchEvent(ev)){
        result = onTouchEvent(ev);
    }else{
        result = child.dispatchTouchEvent(ev);
    }
    return result;
}
复制代码

总结

1.webp.jpg

以上就是 View 体系的基础内容,理解 View 的事件分发原理,是我们能化用 View 的前提。View 处理事件层层下发的思想,是非常具有借鉴学习价值的,我们代码的设计也可以借鉴这套思想,提高代码的质量。

相关文章
|
运维 架构师 测试技术
架构师成长日记 - 01 4+1视图模型
架构师成长日记 - 01 4+1视图模型
272 0
架构师成长日记 - 01 4+1视图模型
|
异构计算
View体系(下)|青训营笔记
熟悉完 View 的基础,了解完其分发流程,事件分发的传递规则。我们需要深入理解 View 的工作流程,包括绘制原理以及三大方法的流程,洞悉其原理和实现。
View体系(下)|青训营笔记
|
Android开发
View体系(上)|青训营笔记(一)
View 体系是较为复杂的,但是又非常重要的一个知识点。我们把这部分知识吃透吃熟是十分必要的,打卡第一天,我把View体系的第一部分知识整理出来,快来和我一起学习吧。
View体系(上)|青训营笔记(一)
View体系的一些小问题|青训营笔记
设置点击事件逻辑的时候,最基础的办法就是先用 findViewById() 来绑定实例,其次就是设置一个匿名内部类来监听点击,继而处理事件。
View体系的一些小问题|青训营笔记
|
前端开发 Android开发
带你封装MVP架构(上)|青训营笔记(一)
我们做一个 MVP 架构的封装,主要其相对于MVC更加解耦,能让开发人员在编写代码的时候更加高效和舒服。
|
前端开发 API
带你封装MVP架构(上)|青训营笔记(二)
我们做一个 MVP 架构的封装,主要其相对于MVC更加解耦,能让开发人员在编写代码的时候更加高效和舒服。
带你封装MVP架构(下)|青训营笔记(二)
在 Base 类中,我们需要做的就是把每个 Activity 或者 Fragment 等这些组件,或者对应的 MVP 层会用到的基本操作以及联系都编写好。
|
JSON 数据处理 Android开发
带你封装MVP架构(下)|青训营笔记(一)
在 Base 类中,我们需要做的就是把每个 Activity 或者 Fragment 等这些组件,或者对应的 MVP 层会用到的基本操作以及联系都编写好。
|
Web App开发 小程序 API
小程序开发-第一章第四节从block盒式布局到Flex弹性布局-全栈工程师之路-中级篇(下)
小程序开发-第一章第四节从block盒式布局到Flex弹性布局-全栈工程师之路-中级篇(下)
143 0
小程序开发-第一章第四节从block盒式布局到Flex弹性布局-全栈工程师之路-中级篇(下)
|
Web App开发 小程序 iOS开发
小程序开发-第一章第四节从block盒式布局到Flex弹性布局-全栈工程师之路-中级篇(上)
小程序开发-第一章第四节从block盒式布局到Flex弹性布局-全栈工程师之路-中级篇(上)
273 0
小程序开发-第一章第四节从block盒式布局到Flex弹性布局-全栈工程师之路-中级篇(上)