RoundedImageView源碼解析(三)RoundedImageView解析

現在開始RoundedImageView的源碼解析了,之前的RoundedDrawable就是爲RoundedImageView的實現做鋪墊。

RoundedDrawable的作用主要是把Drawable轉化爲圓角的Drawable. 如果不清楚RoundedDrawable的話,可以參考我的前一篇博客http://blog.csdn.net/wangdong20/article/details/50737333

現在RoundedImageView就要利用RoundedDrawable來實現圓角圖片功能。


首先RoundedImageView繼承於ImageView,這就說明ImageView該有的特性RoundedImageView都有。

RoundedImageView也有src和background屬性,而且都支持src和background爲圓角功能。


我們可以先看看關於ImageView的src屬性的設置相關代碼。

 @Override
  public void setImageDrawable(Drawable drawable) {
    mResource = 0;
    mDrawable = RoundedDrawable.fromDrawable(drawable);
    updateDrawableAttrs();
    super.setImageDrawable(mDrawable);
  }

  @Override
  public void setImageBitmap(Bitmap bm) {
    mResource = 0;
    mDrawable = RoundedDrawable.fromBitmap(bm);
    updateDrawableAttrs();
    super.setImageDrawable(mDrawable);
  }

  @Override
  public void setImageResource(@DrawableRes int resId) {
    if (mResource != resId) {
      mResource = resId;
      mDrawable = resolveResource();
      updateDrawableAttrs();
      super.setImageDrawable(mDrawable);
    }
  }

我們可以發現重寫了ImageView的setImageDrawable,setImageBitmap和setImageResource方法,其中setImageDrawable和setImageBitmap方法,都使用了RoundedDrawable對Drawable或者Bitmap進行轉換然後賦值給mDrawable,setImageResource裏面也調用了resolveResource()方法。代碼如下:


private Drawable resolveResource() {
    Resources rsrc = getResources();
    if (rsrc == null) { return null; }

    Drawable d = null;

    if (mResource != 0) {
      try {
        d = rsrc.getDrawable(mResource);
      } catch (Exception e) {
        Log.w(TAG, "Unable to find resource: " + mResource, e);
        // Don't try again.
        mResource = 0;
      }
    }
    return RoundedDrawable.fromDrawable(d);
  }

從代碼中我們可以看出,resolveResource()方法也是根據mResource獲取Drawable,然後將其轉換爲RoundedDrawable最後賦值給mDrawable。


setImageDrawable,setImageBitmap,setImageResource方法後面都調用了updateDrawableAttrs()方法,我們來看看這部分代碼。


private void updateDrawableAttrs() {
    updateAttrs(mDrawable);
  }

這裏就一行代碼,updateAttrs(mDrawable); 我們繼續跟蹤下去。


private void updateAttrs(Drawable drawable) {
    if (drawable == null) { return; }

    if (drawable instanceof RoundedDrawable) {
      ((RoundedDrawable) drawable)
          .setScaleType(mScaleType)
          .setBorderWidth(mBorderWidth)
          .setBorderColor(mBorderColor)
          .setOval(mIsOval)
          .setTileModeX(mTileModeX)
          .setTileModeY(mTileModeY);

      if (mCornerRadii != null) {
        ((RoundedDrawable) drawable).setCornerRadius(
            mCornerRadii[Corner.TOP_LEFT],
            mCornerRadii[Corner.TOP_RIGHT],
            mCornerRadii[Corner.BOTTOM_RIGHT],
            mCornerRadii[Corner.BOTTOM_LEFT]);
      }

      applyColorMod();
    } else if (drawable instanceof LayerDrawable) {
      // loop through layers to and set drawable attrs
      LayerDrawable ld = ((LayerDrawable) drawable);
      for (int i = 0, layers = ld.getNumberOfLayers(); i < layers; i++) {
        updateAttrs(ld.getDrawable(i));
      }
    }
  }

這部分代碼就跟之前的RoundedDrawable的fromDrawable()方法類似,首先對傳入的Drawable參數進行檢查,如果是RoundedDrawable,那麼我們就把RoundedDrawable相關的屬性設置給Drawable,如果是LayerDrawable的話,就把LayerDrawable的每一個Drawable提取出來重新進入updateAttrs流程。


以上部分代碼我們就可以觀察到,基本上就可以實現RoundedImageView的src屬性爲圓角效果,但是我們的RoundedImageView還支持background屬性呢!


@Override
  public void setBackground(Drawable background) {
    setBackgroundDrawable(background);
  }

@Override
  @Deprecated
  public void setBackgroundDrawable(Drawable background) {
    mBackgroundDrawable = background;
    updateBackgroundDrawableAttrs(true);
    super.setBackgroundDrawable(mBackgroundDrawable);
  }

觀察以上代碼發現調用了updateBackgroundDrawableAttrs(true),直接跟進去。


private void updateBackgroundDrawableAttrs(boolean convert) {
    if (mMutateBackground) {
      if (convert) {
        mBackgroundDrawable = RoundedDrawable.fromDrawable(mBackgroundDrawable);
      }
      updateAttrs(mBackgroundDrawable);
    }
  }


這段代碼可以看出這裏面涉及到mMutateBackground屬性,如果mMutateBackground爲true,並且傳入的參數也爲true的話,會調用RoundedDrawable的方法把mBackgroundDrawable轉化爲圓角,最後通過之前講的updateAttrs(Drawable)方法實現更新mBackgroundDrawable有關RoundedDrawable的屬性。


上面提到了mMutateBackground屬性,就是實現background是否也可以有圓角效果。

mMutateBackground = a.getBoolean(R.styleable.RoundedImageView_riv_mutate_background, false);

這裏的mMutateBackground屬性默認爲false,所以如果希望background也有圓角效果,那麼需要在xml裏面或者代碼裏面將mMutateBackground設置爲true。


<com.makeramen.roundedimageview.RoundedImageView
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/imageView1"
        android:src="@drawable/photo1"
        android:background="@drawable/background"
        android:scaleType="fitCenter"
        app:riv_corner_radius="30dip"
        app:riv_border_width="2dip"
        app:riv_border_color="#333333"
        app:riv_mutate_background="true"
        app:riv_tile_mode="repeat"
        app:riv_oval="true" />

也就是在xml裏面設置app:riv_mutate_background="true"或者再代碼裏面riv.mutateBackground(true)。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章