View体系(九)从LinearLayout分析ViewGroup的测量流程
之前的文章《View体系(八)深入剖析View的onMeasure方法》我们深入分析了View的onMeasure方法,我们今天就来看一下ViewGroup的测量流程。 (注:文中源码基于 Android 12) 在View做测量时,会调用View的onMeasure方法,但是我们翻看ViewGroup的源码,并没有发现onMeasure方法,难道ViewGroup不用测量?显然不是,我们换一个类来看,LinearLayout继承自ViewGroup,我们从LinearLayout的源码中找到了熟悉的onMeasure方法,我们看一下源码: 1234567891011public class LinearLayout extends ViewGroup { ... @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (mOrientation == VERTICAL) {//1 ...
设计模式(一)单例模式
单例设计模式(Singleton Design Pattern)理解起来非常简单。一个类只允许创建一个对象(或者实例),那这个类就是一个单例类,这种设计模式就叫作单例设计模式,简称单例模式。 定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点。 单例模式结构图如下: Client为客户端,Singleton为单例类,Client通过调用Singleton.getInstance()方法获取实例对象。 下面介绍常见的6种单例写法: 饿汉式饿汉式的实现方式比较简单。在类加载的时候,instance 静态实例就已经创建并初始化好了,所以,instance 实例的创建过程是线程安全的。不过,这样的实现方式不支持延迟加载(在真正用到 instance 的时候,再创建实例),从名字中我们也可以看出这一点。具体的代码实现如下所示: 12345678910public class Singleton { private static Singleton instance = new Singleton(); private Singleton() { ...
View体系(八)深入剖析View的onMeasure方法
之前的文章《View体系(六)View工作流程入口》介绍了View是从什么地方开始它的工作流程的,《View体系(七)理解 MeasureSpec》介绍了View在measure流程时的一个重要参数。有了上两篇的铺垫,我们就来看一下View的onMeasure方法到底做了什么。 (注:文中源码基于 Android 12) 在View做测量时,会调用View的onMeasure方法: 1234protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));} 这里只调用了一个setMeasuredDimension方法,看它的注释: This method...
View体系(七)理解 MeasureSpec
MeasureSpec是View的内部类,MeasureSpec 封装了从父级传递到子级的测量要求。每个 MeasureSpec 代表对宽度或高度的要求。 MeasureSpec 由大小和模式两部分组成。 更详细的说明请看 Google官方文档 下面是MeasureSpec的源码:(基于Android 12) 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768public static class MeasureSpec { private static final int MODE_SHIFT = 30; private static final int MODE_MASK = 0x3 << MODE_SHIFT; public static final int UNSPECIFIED = 0 << MODE_SHIFT;...
View体系(六)View工作流程入口
View的工作流程,就是View进行measure、layout和draw的过程,本篇文章我们就来一起看一下View是如何开始他的工作流程的。 (注:文中源码基于 Android 12) 在上篇文章《View体系(五)熟悉又陌生的setContentView》中我们讲过Activity的结构,包括了Activity、PhoneWindow及DecorView。讲了PhoneWindow的创建和DecorView的创建,但此时DecorView还没有加载到PhoneWindow中,下面我们就从源码看一下DecorView是如何加载到PhoneWindow中的。 当我们调用Activity的startActivity时,最终会调用到ActivityThread的handleLaunchActivity,代码如下: android.app.ActivityThread 12345public Activity handleLaunchActivity(ActivityClientRecord r, PendingTransactionActions...
View体系(五)熟悉又陌生的setContentView
为什么说setContentView熟悉呢?因为该方法是我们从入门Android开发就接触的一个方法,在我们写过的每一个Activity中都有他的身影。但为什么又说setContentView陌生呢?因为我们在日常的开发中只知道用,并没有深入分析该方法是怎么将我们传入的layout资源id变为一个可视的界面的。今天我们就来揭开这层神秘的面纱,扒一扒其中的原理(注:源码基于Android12)。 因为我们日常开发的Activity最终都会继承自android.app.Activity,所以先看Activity类的setContentView方法: android.app.Activity 1234public void setContentView(@LayoutRes int layoutResID) { getWindow().setContentView(layoutResID); //1 ...
View体系(四)深入理解事件分发机制
上篇文章《View体系(三)初探View事件分发机制》对View的事件分发机制进行了粗略的讲解,并用代码实际探究了View事件的传递和处理过程。这篇文章就对View的事件分发机制进行一个更深入的讲解。之前提到过事件分发机制中的三个方法:dispatchTouchEvent(MotionEvent event)、onInterceptTouchEvent(MotionEvent ev)和onTouchEvent(MotionEvent event),那么这三个方法到底有什么样的关联呢?他们的关系其实可以用如下的伪代码表示: 123456789public boolean dispatchTouchEvent(MotionEvent event) { boolean result = false; if (onInterceptTouchEvent(event)) { result = onTouchEvent(event); } else { result =...
View体系(三)初探View事件分发机制
事件分发机制,简而言之就是Android对触摸事件的一系列传递和处理的机制。在了解分发机制之前需要对下面三个方法有个大概的了解: public boolean dispatchTouchEvent(MotionEvent event) 用来进行事件的分发。如果有事件传递给当前View,那么此方法一定会被调用。返回值受当前View的onTouchEvent(MotionEvent event)和子View的dispatchTouchEvent(MotionEvent event)方法的影响,表示是否消耗当前事件。 public boolean onInterceptTouchEvent(MotionEvent ev) 用来判断是否拦截事件,返回值表示是否拦截当前事件。 public boolean onTouchEvent(MotionEvent...
View体系(二)View滑动的六种方式
在日常开发中,有时会遇到需要对View进行滑动处理的情况,今天我们就一起来看一下如何实现View的滑动。 不管采用什么方式,实现思路基本是一致的:当触摸到View时,记下当前触摸点的坐标;当手指移动时,记下移动后触摸点的坐标,然后用两个坐标算出移动的偏移量,再利用偏移量来修改View的坐标。 下面分别来讲解实现View滑动的6种方式。 一、layout()layout()方法是View在进行布局流程时调用的一个方法,我们可以在移动View时调用次方法,不断的进行View的布局,达到滑动View的目的。具体过程如下: (1)先自定义一个View,重写onTouchEvent(MotionEvent event)方法,在ACTION_DOWN时获取按下时的坐标。代码如下: 1234567891011@Overridepublic boolean onTouchEvent(MotionEvent event) { int x = (int) event.getX(); int y = (int) event.getY(); switch...