ImageView实现原理分析

ImageView 是 Android 中用于显示图片的一个基本视图组件。它继承自 View 类,并且可以用来展示静态的图像资源,如位图、动画 GIF、矢量图形等。下面我们将结合源码分析 ImageView 的实现原理。

1. 构造方法与初始化

ImageView 的构造方法和其他 View 子类类似,通常接受一个 Context 对象,可能还包含 AttributeSetint 类型的默认样式。在构造方法中,ImageView 初始化其样式属性,设置默认的缩放类型等。

1public ImageView(Context context) {
2    super(context);
3    init(null, null, 0, 0);
4}
5
6public ImageView(Context context, AttributeSet attrs) {
7    this(context, attrs, 0);
8}
9
10public ImageView(Context context, AttributeSet attrs, int defStyleAttr) {
11    super(context, attrs, defStyleAttr);
12    init(attrs, null, defStyleAttr, 0);
13}
14
15private void init(AttributeSet attrs, AttributeSet defStyleAttrRes, int defStyleAttr, int defStyleRes) {
16    // 初始化ImageView的属性
17}

2. 设置图片资源

ImageView 支持多种方式来设置图片资源,包括从资源文件、Drawable 对象、位图或者 URL 加载图片。

  • 从资源文件加载

     Java 

    深色版本

    1public void setImageResource(@DrawableRes int resId) {
    2    Drawable drawable = null;
    3    if (resId != 0) {
    4        drawable = ContextCompat.getDrawable(getContext(), resId);
    5    }
    6    setImageDrawable(drawable);
    7}
  • 从 Drawable 设置

    1public void setImageDrawable(Drawable drawable) {
    2    if (mImage != drawable) {
    3        if (drawable != null) {
    4            drawable.setCallback(this);
    5            if (mAdjustViewBounds && drawable instanceof ScaleDrawable) {
    6                ((ScaleDrawable) drawable).setTargetDensity(getDrawableDensity());
    7            }
    8        }
    9        if (mImage != null) {
    10            mImage.setCallback(null);
    11        }
    12        mImage = drawable;
    13        requestLayout();
    14        invalidate();
    15    }
    16}
  • 从位图设置

    1public void setImageBitmap(Bitmap bm) {
    2    setImageDrawable(new BitmapDrawable(getResources(), bm));
    3}

3. 缩放类型

ImageView 支持不同的缩放类型,如 FIT_XY, CENTER_CROP, CENTER_INSIDE 等。缩放类型决定了如何在 ImageView 内部调整图片的大小和位置。

1public void setScaleType(ScaleType scaleType) {
2    if (scaleType != mScaleType) {
3        mScaleType = scaleType;
4        requestLayout(); // 请求重新布局
5    }
6}

4. 测量与布局

ImageView 需要根据图片的大小和缩放类型来确定自己的大小。onMeasure 方法负责计算 ImageView 的大小。

1@Override
2protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
3    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
4    setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
5                         getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
6
7    final int width = getMeasuredWidth();
8    final int height = getMeasuredHeight();
9    if (getDrawable() != null) {
10        // 根据图片和缩放类型计算ImageView的大小
11        final int childWidth = getDrawable().getIntrinsicWidth();
12        final int childHeight = getDrawable().getIntrinsicHeight();
13        final ScaleType scaleType = getScaleType();
14
15        int widthSize = width;
16        int heightSize = height;
17
18        if (scaleType == ScaleType.FIT_XY) {
19            // FIT_XY 会拉伸图片以填满ImageView
20            widthSize = childWidth;
21            heightSize = childHeight;
22        } else if (scaleType == ScaleType.CENTER_CROP) {
23            // CENTER_CROP 会裁剪图片以适应ImageView
24            // 计算新的宽度和高度
25        }
26
27        setMeasuredDimension(resolveSizeAndState(widthSize, widthMeasureSpec, 0),
28                             resolveSizeAndState(heightSize, heightMeasureSpec, 0));
29    }
30}

5. 绘制图片

onDraw 方法中,ImageView 负责将图片绘制到屏幕上。

1@Override
2protected void onDraw(Canvas canvas) {
3    super.onDraw(canvas);
4    final Drawable drawable = getDrawable();
5    if (drawable != null) {
6        final Rect bounds = drawable.getBounds();
7        if (!bounds.isEmpty()) {
8            final int saveCount = canvas.save();
9            final int w = bounds.width();
10            final int h = bounds.height();
11            final int tw = getWidth() - getPaddingLeft() - getPaddingRight();
12            final int th = getHeight() - getPaddingTop() - getPaddingBottom();
13            final int scaleType = getScaleType();
14            if (scaleType != null) {
15                switch (scaleType) {
16                    case FIT_XY:
17                        canvas.scale((float) tw / w, (float) th / h);
18                        break;
19                    case CENTER_CROP:
20                        // ... 其他缩放类型 ...
21                    default:
22                        break;
23                }
24            }
25            canvas.translate(getPaddingLeft(), getPaddingTop());
26            drawable.draw(canvas);
27            canvas.restoreToCount(saveCount);
28        }
29    }
30}

总结

ImageView 的实现涉及到构造、图片资源的加载和管理、缩放类型的设置、测量与布局逻辑以及图片的绘制。这些功能的实现确保了 ImageView 可以灵活地显示不同类型的图片资源,并能适应不同的布局需求。

相关推荐

  1. ImageView实现原理分析

    2024-07-23 03:32:04       18 阅读
  2. LinearLayout实现原理分析

    2024-07-23 03:32:04       19 阅读
  3. Qt源码分析:QMetaObject实现原理

    2024-07-23 03:32:04       32 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-23 03:32:04       52 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-23 03:32:04       54 阅读
  3. 在Django里面运行非项目文件

    2024-07-23 03:32:04       45 阅读
  4. Python语言-面向对象

    2024-07-23 03:32:04       55 阅读

热门阅读

  1. 数据结构---二叉树

    2024-07-23 03:32:04       18 阅读
  2. [k8s源码]6.reflector

    2024-07-23 03:32:04       11 阅读
  3. NumPy冷知识66个

    2024-07-23 03:32:04       15 阅读
  4. 怀庄之醉是勾兑酒吗?

    2024-07-23 03:32:04       15 阅读
  5. 【开源库学习】libodb库学习(一)

    2024-07-23 03:32:04       14 阅读
  6. 【Apollo学习笔记】—— Cyber RT之创建组件, test ok

    2024-07-23 03:32:04       16 阅读
  7. Linux Shell 022-按日期清理文件

    2024-07-23 03:32:04       16 阅读
  8. Red Playing Cards (牛客多校2 I)

    2024-07-23 03:32:04       17 阅读
  9. Husky 入门

    2024-07-23 03:32:04       16 阅读
  10. ResNeSt

    ResNeSt

    2024-07-23 03:32:04      18 阅读