Android源码系列之深入理解ImageView的ScaleType属性

做Android开发的童靴们肯定对系统自带的控件使用的都非常熟悉,比如Button、TextView、ImageView等。如果你问我具体使用,我会给说:拿ImageView来说吧,首先创建一个新的项目,在项目布局文件中应用ImageView控件,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:background="#bbaacc" > 

 <ImageView
 android:src="@drawable/ic_launcher"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:background="#aabbcc" /> 

</LinearLayout>

上边布局文件为了便于查看各种属性效果,故意加了两个背景颜色,这对我们今天的源码分析影响不大。接着运行一下代码,效果图如下:

恩,不错,运行结果正如所愿,屏幕上显示的正是我们设置的图片,这时候心中不由欣喜ImageView的使用就是这样简单,so easy嘛!呵呵,如果真是这么想那就大错特错了,上边的示例仅仅是在布局文件中使用了ImageView的src,layout_width和layout_height这三个属性罢了,它其他的重要属性我们还没有用到,今天这篇文章就是主要结合源码讲解ImageView的另一个重要的属性------ScaleType,其他的一些属性等将来需要的话再做详细解说。好了,现在正式进入主题。
        ScaleType属性主要是用来定义图片(Bitmap)如何在ImageView中展示的,姑且就认为是展示吧,系统给我们提供了8种可选属性:matrix、fitXY、fitStart、fitCenter、fitEnd、center、centerCrop和centerInside。每一种属性对应的展示效果是不一样的,下面我们先来做一个实验来说明每一种属性的显示效果,我从之前的项目中挑选了两张图片,一张图片的实际尺寸是720*1152,另一张是我把第一张图翻转放缩得到的,它的实际尺寸是96*60,之所以采用两张图片是为了便于对比和观察结果,原图片如下:

OK,测试图片准备好了,接下来我们在布局文件中分别使用ScaleType的每一个属性值,我们开始写布局文件,内容如下:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:background="#bbccaa" > 

 <TableLayout
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:padding="10dp" > 

 <TextView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_marginBottom="10dp"
 android:text="图片尺寸的宽和高都远远大于ImageView的尺寸" /> 

 <TableRow
 android:layout_width="match_parent"
 android:layout_height="wrap_content" > 

 <ImageView
 android:layout_width="300px"
 android:layout_height="300px"
 android:background="#aabbcc"
 android:scaleType="matrix"
 android:src="@drawable/test" /> 

 <ImageView
 android:layout_width="300px"
 android:layout_height="300px"
 android:layout_marginLeft="10dp"
 android:background="#aabbcc"
 android:scaleType="fitXY"
 android:src="@drawable/test" /> 

 <ImageView
 android:layout_width="300px"
 android:layout_height="300px"
 android:layout_marginLeft="10dp"
 android:background="#aabbcc"
 android:scaleType="fitStart"
 android:src="@drawable/test" /> 

 <ImageView
 android:layout_width="300px"
 android:layout_height="300px"
 android:layout_marginLeft="10dp"
 android:background="#aabbcc"
 android:scaleType="fitCenter"
 android:src="@drawable/test" />
 </TableRow> 

 <TableRow
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:layout_marginTop="5dp" > 

 <TextView
 android:layout_width="300px"
 android:layout_height="wrap_content"
 android:gravity="center"
 android:text="matrix" /> 

 <TextView
 android:layout_width="300px"
 android:layout_height="wrap_content"
 android:gravity="center"
 android:text="fitXY" /> 

 <TextView
 android:layout_width="300px"
 android:layout_height="wrap_content"
 android:gravity="center"
 android:text="fitStart" /> 

 <TextView
 android:layout_width="300px"
 android:layout_height="wrap_content"
 android:gravity="center"
 android:text="fitCenter" />
 </TableRow> 

 <TableRow
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:layout_marginTop="10dp" > 

 <ImageView
 android:layout_width="300px"
 android:layout_height="300px"
 android:background="#aabbcc"
 android:scaleType="fitEnd"
 android:src="@drawable/test" /> 

 <ImageView
 android:layout_width="300px"
 android:layout_height="300px"
 android:layout_marginLeft="10dp"
 android:background="#aabbcc"
 android:scaleType="center"
 android:src="@drawable/test" /> 

 <ImageView
 android:layout_width="300px"
 android:layout_height="300px"
 android:layout_marginLeft="10dp"
 android:background="#aabbcc"
 android:scaleType="centerCrop"
 android:src="@drawable/test" /> 

 <ImageView
 android:layout_width="300px"
 android:layout_height="300px"
 android:layout_marginLeft="10dp"
 android:background="#aabbcc"
 android:scaleType="centerInside"
 android:src="@drawable/test" />
 </TableRow> 

 <TableRow
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:layout_marginTop="5dp" > 

 <TextView
 android:layout_width="300px"
 android:layout_height="wrap_content"
 android:gravity="center"
 android:text="fitEnd" /> 

 <TextView
 android:layout_width="300px"
 android:layout_height="wrap_content"
 android:gravity="center"
 android:text="center" /> 

 <TextView
 android:layout_width="300px"
 android:layout_height="wrap_content"
 android:gravity="center"
 android:text="centerCrop" /> 

 <TextView
 android:layout_width="300px"
 android:layout_height="wrap_content"
 android:gravity="center"
 android:text="centerInside" />
 </TableRow>
 </TableLayout> 

</ScrollView>

为了快速进入今天文章主题,布局文件并没有按照平时开发中所遵循的Android开发规范来写。布局中使用的是TableLayout标签嵌套TableRow的方式,分成两行,每一行是4列,恰好8种属性可以合理对比查看。当然了这里有更高效的写法来实现同样的效果,比如使用RelativeLayout布局等。
        在布局文件中我们定义了每个ImageView的宽高都是固定的300像素,这个尺寸远小于或者是远大于测试的图片尺寸,另外为了便于观察效果我给每个ImageView的背景都设置了颜色,接着运行大图和小图的测试结果,效果如下:

通过上述实验结果对比,就可以得出部分属性的展示效果。比如fitXY属性,当ImageView的属性设置成了fitXY时,图片的宽和高就会相应的拉伸或者是压缩来填充满整个ImageView,注意这种拉放缩不成比例。当ImageView的属性设置成了matrix时,如果图片宽高大于ImageView的宽高时,图片的显示就是从ImageView的左上角开始平铺,超出部分不再显示;如果图片宽高小于ImageView的宽高时,图片的显示也是从ImageView的左上角开始平铺,缺少部分空白显示出来或者是显示ImageView的背景。以上仅仅是根据运行结果来得出的结果,权威结论还要通过查看源码来得出,本文分析的源码是Android2.2版本。
        分析ImageView的源码首先从它的构造方法开始,看一下构造方法里边都做了什么工作。构造方法如下:

public ImageView(Context context) {
 super(context);
 initImageView();
} 

public ImageView(Context context, AttributeSet attrs) {
 this(context, attrs, 0);
} 

public ImageView(Context context, AttributeSet attrs, int defStyle) {
 super(context, attrs, defStyle);
 initImageView(); 

 TypedArray a = context.obtainStyledAttributes(attrs,
 com.android.internal.R.styleable.ImageView, defStyle, 0); 

 Drawable d = a.getDrawable(com.android.internal.R.styleable.ImageView_src);
 if (d != null) {
 setImageDrawable(d);
 } 

 //////////////////////////////////////////////////
 //
 // 以下源码部分属性初始化不涉及主核心,不再贴出
 //
 ////////////////////////////////////////////////// 

 a.recycle(); 

 //need inflate syntax/reader for matrix
}

通过查看构造方法发现,在三个构造方法中都调用了initImageView()这个方法,这个方法是干嘛使的,我们稍后在看。其次是根据在布局文件中定义的属性来初始化相关属性,在测试布局中我们仅仅是用了ImageView的src,layout_width,layout_height和scaleType属性(background属性暂时忽略)。那也就是说在构造函数的初始化中就是对相关属性进行了赋值操作,通过解析src属性我们获取到了一个Drawable的实例对象d,如果d是非空的话就把d作为参数又调用了setImageDrawable(d)函数,我们看看一下这个函数主要做了什么工作,源码如下:

/**
 * Sets a drawable as the content of this ImageView.
 *
 * @param drawable The drawable to set
 */
public void setImageDrawable(Drawable drawable) {
 if (mDrawable != drawable) {
 mResource = 0;
 mUri = null; 

 int oldWidth = mDrawableWidth;
 int oldHeight = mDrawableHeight; 

 updateDrawable(drawable); 

 if (oldWidth != mDrawableWidth || oldHeight != mDrawableHeight) {
 requestLayout();
 }
 invalidate();
 }
}

此方法类型是public的,目的是干嘛使的不再解释了,注释上说的是把给定的drawable作为当前ImageView的展示内容,接着是个条件判断,在刚刚完成初始化的时候mDrawable属性还没有被赋值此时为空,因此判断成立程序进入条件语句继续执行,在这里把属性mResource和mUri归零操作并计入mDrawableWidth和mDrawableHeight的初始值,紧接着把传递进来的drawable参数传递给了updateDrawable()方法,那我们继续跟进updateDrawable()看看这里边又做了什么操作,源码如下:

private void updateDrawable(Drawable d) {
 if (mDrawable != null) {
 mDrawable.setCallback(null);
 unscheduleDrawable(mDrawable);
 }
 mDrawable = d;
 if (d != null) {
 d.setCallback(this);
 if (d.isStateful()) {
 d.setState(getDrawableState());
 }
 d.setLevel(mLevel);
 mDrawableWidth = d.getIntrinsicWidth();
 mDrawableHeight = d.getIntrinsicHeight();
 applyColorMod();
 configureBounds();
 } else {
 mDrawableWidth = mDrawableHeight = -1;
 }
}

该方法首先进行了非空判断,此时mDrawable的值依然是空,所以条件判断不成立跳过此部分,紧接着把传递进来的非空参数d的字赋值给了属性mDrawable,到这里mDrawable才算是完成了赋值操作。然后又进行了条件判断,并设置d的callback为当前ImageView(因为ImageView的父类View实现了Drawable的Callback接口)接下来又把图片的宽和高分别赋值给了mDrawableWidth和mDrawableHeight,紧接着又调用了applyColorMod()方法,当我们没有给ImageView设置透明度或者是颜色过滤器时该方法不会执行。然后调用configureBounds()方法,此方法是我们今天要讲的和ScaleType属性息息相关的重点,不耽误时间了赶紧瞅一下源码吧,(*^__^*) 嘻嘻……

 private void configureBounds() {
 if (mDrawable == null || !mHaveFrame) {
 return;
 } 

 int dwidth = mDrawableWidth;
 int dheight = mDrawableHeight; 

 int vwidth = getWidth() - mPaddingLeft - mPaddingRight;
 int vheight = getHeight() - mPaddingTop - mPaddingBottom; 

 boolean fits = (dwidth < 0 || vwidth == dwidth) &&
 (dheight < 0 || vheight == dheight); 

 ////////////////////////////////////////代码块一//////////////////////////////////////// 

 if (dwidth <= 0 || dheight <= 0 || ScaleType.FIT_XY == mScaleType) {
 /* If the drawable has no intrinsic size, or we're told to
 scaletofit, then we just fill our entire view.
 */
 mDrawable.setBounds(0, 0, vwidth, vheight);
 mDrawMatrix = null; 

 ////////////////////////////////////////代码块二//////////////////////////////////////// 

 } else {
 // We need to do the scaling ourself, so have the drawable
 // use its native size.
 mDrawable.setBounds(0, 0, dwidth, dheight); 

 if (ScaleType.MATRIX == mScaleType) {
 // Use the specified matrix as-is.
 if (mMatrix.isIdentity()) {
 mDrawMatrix = null;
 } else {
 mDrawMatrix = mMatrix;
 } 

 ////////////////////////////////////////代码块三//////////////////////////////////////// 

 } else if (fits) {
 // The bitmap fits exactly, no transform needed.
 mDrawMatrix = null; 

 ////////////////////////////////////////代码块四//////////////////////////////////////// 

 } else if (ScaleType.CENTER == mScaleType) {
 // Center bitmap in view, no scaling.
 mDrawMatrix = mMatrix;
 mDrawMatrix.setTranslate((int) ((vwidth - dwidth) * 0.5f + 0.5f),
  (int) ((vheight - dheight) * 0.5f + 0.5f)); 

 ////////////////////////////////////////代码块五//////////////////////////////////////// 

 } else if (ScaleType.CENTER_CROP == mScaleType) {
 mDrawMatrix = mMatrix; 

 float scale;
 float dx = 0, dy = 0; 

 if (dwidth * vheight > vwidth * dheight) {
 scale = (float) vheight / (float) dheight;
 dx = (vwidth - dwidth * scale) * 0.5f;
 } else {
 scale = (float) vwidth / (float) dwidth;
 dy = (vheight - dheight * scale) * 0.5f;
 } 

 mDrawMatrix.setScale(scale, scale);
 mDrawMatrix.postTranslate((int) (dx + 0.5f), (int) (dy + 0.5f)); 

 ////////////////////////////////////////代码块六//////////////////////////////////////// 

 } else if (ScaleType.CENTER_INSIDE == mScaleType) {
 mDrawMatrix = mMatrix;
 float scale;
 float dx;
 float dy; 

 if (dwidth <= vwidth && dheight <= vheight) {
 scale = 1.0f;
 } else {
 scale = Math.min((float) vwidth / (float) dwidth,
 (float) vheight / (float) dheight);
 } 

 dx = (int) ((vwidth - dwidth * scale) * 0.5f + 0.5f);
 dy = (int) ((vheight - dheight * scale) * 0.5f + 0.5f); 

 mDrawMatrix.setScale(scale, scale);
 mDrawMatrix.postTranslate(dx, dy); 

 ////////////////////////////////////////代码块七//////////////////////////////////////// 

 } else {
 // Generate the required transform.
 mTempSrc.set(0, 0, dwidth, dheight);
 mTempDst.set(0, 0, vwidth, vheight); 

 mDrawMatrix = mMatrix;
 mDrawMatrix.setRectToRect(mTempSrc, mTempDst, scaleTypeToScaleToFit(mScaleType)); 

 ////////////////////////////////////////代码块八//////////////////////////////////////// 

 }
 }
 }

configureBoundd()函数比较长,为了方便分析源码,我把该函数代码分成了8小块,每一个小块都是一个单独的逻辑。每一块的详解如下:
代码块一:
        该模块代码首先做了一个条件判断,如果当前mDrawable为空或者是mHaveFrame为false则函数直接返回不再往下执行,由于后边的逻辑主要是根据ScaleType属性的类型来判断图片的展示方式,所以再后来这个函数肯定是能往下走的通的,由于篇幅的原因不再深入讲解该函数的调用时机,我会在之后的文章中专门根据源码讲解一下Android系统下View的绘制流程,在之后的绘制流程中会提到configureBounds()的调用时机。该代码块的逻辑是获取图片的宽高存储在dwidth,dheight中,然后又获取到了ImageView的显示图片区域的宽高存放在vwidth和vheight中。然后定义了一个boolean类型的变量,该变量若为true就表示不需要对图片进行放缩处理。
代码块二:
        该代码块的逻辑是当获取到的图片尺寸的宽高未知或者是ImageView的ScaleType属性为FIT_XY时,将mDrawable的显示边界设置成控件ImageView的显示区域大小,并且把mDrawMatrix对象设置成null。需要说明的是setBounds方法用来设置Drawable的绘制区域的,最终在ImageView的onDraw方法中把mDrawable表示的图片绘制到ImageView上。
代码块三:
        如果图片宽高不为0并且ImageView的ScaleType属性不是FIT_XY时,就会把mDrawable的绘制区域设置成图片的原始大小。接着进行判断ImageView的ScaleType属性值是否是MATRIX,如果是MATRIX类型,就会把当前mMatrix赋值给mDrawMatrix。
代码块四:
        代码块四是一个if(fits)的判断,如果fits的值为true,就表示图片大小等于ImageView的大小,不需要对图片进行放缩处理了。
代码块五:
       当mScaleType的类型为CENTER时,实际是将图片进行移位操作,直接点说就是把图片的中心点移动到ImageView的中心点,如果图片的宽高大于ImageView的宽高此时只显示ImageView所包含的部分,大于ImageView的部分不再显示。
      【注意:CENTER属性只对图片进行移动操作而不会进行放缩操作】。
代码块六:
        代码块六是当mScaleType==CENTER_CROP时,进行了一个条件判断:if(dwidth *vheight >vwidth *dheight),看到这句代码的时候我并没有理解其含义,然后我把这句代码转换了一下写法:if(dwidth / vwidth > dheight / vheight),通过这种转换写法然后再看就比较明白了,主要是用来判断宽高比的,就是说用来判断是图片的宽比较接近ImageView控件的宽还是图片的高比较接近ImageView控件的高。如果是图片的高比较接近ImageView的高,通过计算获取需要放缩的scale的值,再计算出需要对图片的宽进行移动的值,最后通过对mDrawMatrix属性进行设置放缩和移动来达到控制图片进行放缩和移动的效果,同样的逻辑处理了当图片的宽比较接近ImageView的宽的情况。从代码可以总结CENTER_CROP属性的特点是:对图片的宽高进行放缩处理,使一边达到ImageView控件的宽高,另一边进行进行移动居中显示若超出则不再显示。
代码块七:
        代码块七是当mScaleType==CENTER_INSIDE时,首先判断图片宽高是否小于ImageView宽高,如果图片宽高小于ImageView的宽高,则scale=1.0f,也就是说不对图片进行放缩处理而是直接移动图片进行居中显示,否则通过Math.min((float)vwidth / (float)dwidth, (float) vheight / (float)dheight);计算出需要对图片进行的放缩值,然后放缩图片宽高并对图片移动居中显示。从代码可以总结CENTER_INSIDE的特点是:控制图片尺寸,对图片宽高进行压缩处理,根据图片和控件的宽高比拿最大的一边进行压缩使之同控件一边相同,另一边小于控件。
代码块八:
        代码块八是对mScaleType为FIT_CENTER,FIT_START,FIT_END的情况下统一做了处理,先设置mTempSrc和mTempDst的边界后,通过调用mDrawMatrix的setRectToRect()方法来对图片进行放缩和移动操作,使图片最大边始终等于ImageView相应的边。结合代码和代码测试结果可以得出如下结论:
        当图片的高大于宽时:
1.当mScaleType == FIT_START时,对图片进行等比放缩,使图片的高与ImageView的高相等,移动图片使之左对齐。
2.当mScaleType == FIT_CENTER时,对图片进行等比放缩,使图片的高与ImageView的高相等,移动图片使之居中对齐。
3.当mScaleType == FIT_END时,对图片进行等比放缩,使图片的高与ImageView的高相等,移动图片使之右对齐。
        当图片的宽大于高时:
1.当mScaleType == FIT_START时,对图片进行等比放缩,使图片的宽与ImageView的宽相等,移动图片使之上对齐。
2.当mScaleType == FIT_CENTER时,对图片进行等比放缩,使图片的宽与ImageView的宽相等,移动图片使之居中对齐。
3.当mScaleType == FIT_END时,对图片进行等比放缩,使图片的宽与ImageView的宽相等,移动图片使之下对齐。
        到这里mScaleType的8种用根据法算是分析完了,现在稍做总结:
FIT_XY:对原图宽高进行放缩,该放缩不保持原比例来填充满ImageView。
MATRIX:不改变原图大小从ImageView的左上角开始绘制,超过ImageView部分不再显示。
CENTER:对原图居中显示,超过ImageView部分不再显示。
CENTER_CROP:对原图居中显示后进行等比放缩处理,使原图最小边等于ImageView的相应边。
CENTER_INSIDE:若原图宽高小于ImageView宽高,这原图不做处理居中显示,否则按比例放缩原图宽(高)是之等于ImageView的宽(高)。
FIT_START:对原图按比例放缩使之等于ImageView的宽高,若原图高大于宽则左对齐否则上对其。
FIT_CENTER:对原图按比例放缩使之等于ImageView的宽高使之居中显示。
FIT_END:对原图按比例放缩使之等于ImageView的宽高,若原图高大于宽则右对齐否则下对其。
        还记得在博文开始的时候说到在ImageView的构造方法中都调用了initImageView()方法么?他的源码如下:

private void initImageView() {
 mMatrix = new Matrix();
 mScaleType = ScaleType.FIT_CENTER;
}

可以看到,当我们没有在布局文件中使用scaleType属性或者是没有手动调用setScaleType方法时,那么mScaleType的默认值就是FIT_CENTER。
        好了,有关ImageView的ScaleType的讲解就算结束了,如有错误欢迎指正。以后如有其它属性需要详解,再做记录吧。

原文地址:http://blog.csdn.net/llew2011/article/details/50855655

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 图文讲解Android的ImageView类中的ScaleType属性设置

    ScaleType设置图解 图文相配很清晰的看出每个属性的效果, 感觉 CENTER_CROP 比较有用,长宽自动适应 ImageView ,整个图片自动缩略填充整个区域且居中显示(高宽不一定是view的尺寸),以前用JS在网页上实现的,在 android上一开始还在想要用java来自己实现这个效果太麻烦了,没想到系统自带方便多了 ImageView的Scaletype决定了图片在View上显示时的样子,如进行何种比例的缩放,及显示图片的整体还是部分,等等. 设置的方式包括: 1. 在layou

  • 实例解析Android ImageView的scaleType属性

    这篇随笔将会简单的记录下ImageView这个控件的一些使用方法,以及其最重要的一个属性: scaleType ImageView这个控件是用来显示图片用的,例如我们可以通过下面这段xml配置来声明显示一张图片: <ImageView android:id="@+id/imageView" android:layout_width="100dp" android:layout_height="100dp" android:src="

  • Android 中ImageView的ScaleType使用方法

    Android 中ImageView的ScaleType使用方法 ImageView的ScaleType属性,表示的是ImageView中资源图片的填充方式.scaleType的属性值有好几种,分别是: matrix(默认) center centerCrop centerInside fitCenter fitEnd fitStart fitXY 这里要注意:matrix表示一种填充方式叫默认填充,如果布局和代码中不设置ScaleType属性,ImageView默认是fitCenter! 先上

  • Android中imageview.ScaleType使用方法详细介绍

    Android中imageview.ScaleType使用方法详细介绍 ScaleType属性用以表示显示图片的方式,共有8种取值: ScaleType.CENTER:图片大小为原始大小,如果图片大小大于ImageView控件,则截取图片中间部分,若小于,则直接将图片居中显示. ScaleType.CENTER_CROP:将图片等比例缩放,让图像的短边与ImageView的边长度相同,即不能留有空白,缩放后截取中间部分进行显示. ScaleType.CENTER_INSIDE:将图片大小大于Im

  • ImageView的属性android:scaleType的作用分析

    在网上查了好多资料,大致都雷同,大家都是互相抄袭的,看着很费劲,不好理解,自己总结一下,留着需要看的话来查找.代码中的例子如下: 复制代码 代码如下: <ImageView            android:id="@+id/iv_bit_1"            android:layout_width="@dimen/passcode_width"            android:layout_height="@dimen/passc

  • Android开发中ImageView的scaletype属性用法分析

    本文实例讲述了Android开发中ImageView的scaletype属性用法.分享给大家供大家参考,具体如下: ImageView的属性android:scaleType,即 ImageView.setScaleType(ImageView.ScaleType).android:scaleType是控制图片如何 resized/moved来匹对ImageView的size.ImageView.ScaleType / android:scaleType值的意义区别: CENTER /cente

  • Android源码系列之深入理解ImageView的ScaleType属性

    做Android开发的童靴们肯定对系统自带的控件使用的都非常熟悉,比如Button.TextView.ImageView等.如果你问我具体使用,我会给说:拿ImageView来说吧,首先创建一个新的项目,在项目布局文件中应用ImageView控件,代码如下: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.

  • Android从源码的角度彻底理解事件分发机制的解析(上)

    其实我一直准备写一篇关于Android事件分发机制的文章,从我的第一篇博客开始,就零零散散在好多地方使用到了Android事件分发的知识.也有好多朋友问过我各种问题,比如:onTouch和onTouchEvent有什么区别,又该如何使用?为什么给ListView引入了一个滑动菜单的功能,ListView就不能滚动了?为什么图片轮播器里的图片使用Button而不用ImageView?等等--对于这些问题,我并没有给出非常详细的回答,因为我知道如果想要彻底搞明白这些问题,掌握Android事件分发机

  • Android从源码的角度彻底理解事件分发机制的解析(下)

    记得在前面的文章中,我带大家一起从源码的角度分析了Android中View的事件分发机制,相信阅读过的朋友对View的事件分发已经有比较深刻的理解了. 还未阅读过的朋友,请先参考Android从源码的角度彻底理解事件分发机制的解析. 那么今天我们将继续上次未完成的话题,从源码的角度分析ViewGroup的事件分发. 首先我们来探讨一下,什么是ViewGroup?它和普通的View有什么区别? 顾名思义,ViewGroup就是一组View的集合,它包含很多的子View和子VewGroup,是And

  • Android 源码浅析RecyclerView ItemAnimator

    目录 前言 源码分析 前置基础 ItemHolderInfo InfoRecord ViewInfoStore ProcessCallback 动画处理 dispatchLayoutStep3 dispatchLayoutStep1 dispatchLayoutStep1 dispatchLayoutStep2 dispatchLayoutStep3 总结 动画执行 ItemAnimator SimpleItemAnimator DefaultItemAnimator 最后 前言 在这个系列博客

  • Android源码解析onResume方法中获取不到View宽高

    目录 前言 问题1.为什么onCreate和onResume中获取不到view的宽高? 问题2.为什么View.post为什么可以获取View宽高? 结论 前言 有一个经典的问题,我们在Activity的onCreate中可以获取View的宽高吗?onResume中呢? 对于这类八股问题,只要看过都能很容易得出答案:不能. 紧跟着追问一个,那为什么View.post为什么可以获取View宽高? 今天来看看这些问题,到底为何? 今日份问题: 为什么onCreate和onResume中获取不到vie

  • Android源码学习之工厂方法模式应用及优势介绍

    工厂方法模式定义: Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses. 定义一个用于创建对象的接口,让子类决定实例化哪一个类.工厂方法使一个类的实例化延迟到其子类. 常用的工厂方法模式结构: 如上图所示(截取自<Head Firs

  • 从Android源码剖析Intent查询匹配的实现

    前言     这篇文章主要是介绍一下Android Intent,并且从Android源码的角度对Intent查询匹配过程进行分析. Intent介绍     Intent的中文是"意图"的意思,而意图是一个非常抽象的概念,那么在Android的编码设计中,如何实例化意图呢?因此Android系统明确指定一个Intent可由两方面属性来衡量. 主要属性:包括Action和Data.其中Action用于表示该Intent所表达的动作意图,Data用于表示该Action所操作的数据.   

  • Android 源码如何编译调试

    android提供的工具链和开发工具比较完善,因此它的开发环境的搭建比较简单,相信许多朋友都已经搭建好环境,并编写了HelloActivity入门程序了.这里先看几个问题: 1.android的文件系统结构是怎样的,我们安装的程序放在那里? 编译android源码之后,在out/target/product/generic一些文件: ramdisk.img.system.img.userdata.img. system. data.root 其中, system.img是由 system打包压缩

  • Windows下获取Android 源码方法的详解

    前言:略!获取源码的原因千千万~~~ 1.安装GIT工具.GIT是林纳斯·托瓦兹大神为了管理器Linux内核开发而创立的分布式版本控制软件.下载地址:http://code.google.com/p/msysgit/一路next将安装进行到底. 2.在磁盘剩余空间较大的磁盘下新建一个文件夹,用于存放源码.我在F盘下:新建了androidsourcecode文件夹. 3.访问Android源码网站,获取你所需要的源码"下载链接".网站地址:http://android.git.kerne

  • Ubuntu Android源码以及内核下载与编译

    本教程是基于Ubuntu下Android6.0.1源码以及内核的下载和编译,记录一下,以后也就不用自己去找资料,一遍一遍的尝试了.可以翻墙的,英语好的,直接去AndroidSource. 系统环境:Ubuntu14.04LTS Android版本:6.0.1 重要网址 清华大学镜像 AndroidSource 下载前的准备 安装OpenJdk sudo add-apt-repository ppa:openjdk-r/ppa sudo apt-get update sudo apt-get in

随机推荐