歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> ImageView ScaleType 的擴展之Top Crop 的實現

ImageView ScaleType 的擴展之Top Crop 的實現

日期:2017/3/1 10:17:12   编辑:Linux編程

ImageView中ScaleType屬性可用來設置image的填充方式,主要通過以下兩種途徑:1、XML文件中設置Android:scaleType屬性。2、代碼中使用函數setScaleType(ScaleType scaleType)來設定。目前內置的填充方式有如下8種:

CENTER /center 按圖片的原來size居中顯示,當圖片長/寬超過View的長/寬,則截取圖片的居中部分顯示

CENTER_CROP / centerCrop 按比例擴大圖片的size居中顯示,使得圖片長(寬)等於或大於View的長(寬)

CENTER_INSIDE / centerInside 將圖片的內容完整居中顯示,通過按比例縮小或原來的size使得圖片長/寬等於或小於View的長/寬

FIT_CENTER / fitCenter 把圖片按比例擴大/縮小到View的寬度,居中顯示

FIT_END / fitEnd 把圖片按比例擴大/縮小到View的寬度,顯示在View的下部分位置

FIT_START / fitStart 把圖片按比例擴大/縮小到View的寬度,顯示在View的上部分位置

FIT_XY / fitXY 把圖片不按比例 擴大/縮小到View的大小顯示

MATRIX / matrix 用矩陣來繪制首先要選擇設定圖片填充方式的時機,不管如何,我們在必須在draw之前設定填充方式,因此我們可以考慮在layout的時候,通過查看layout源碼,注意到setFrame函數,setFrame主要是設定view的尺寸和位置,並返回view是否changed,因此可在setFrame中設定填充方式,layout代碼片段如下:

  1. public void layout(int l, int t, int r, int b) {
  2. int oldL = mLeft;
  3. int oldT = mTop;
  4. int oldB = mBottom;
  5. int oldR = mRight;
  6. boolean changed = setFrame(l, t, r, b);
  7. if (changed || (mPrivateFlags & LAYOUT_REQUIRED) == LAYOUT_REQUIRED) {
  8. if (ViewDebug.TRACE_HIERARCHY) {
  9. ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_LAYOUT);
  10. }
  11. onLayout(changed, l, t, r, b);

然而對於人像為主的圖片來說,默認的幾種方式都無法很好的滿足需求,因為人像的頭部往往被切割了,我們可以忍受人像下半部分被切割,但是無法忍受頭部被切割,因此我們考慮第9種填充方式:TOP_CROP,TOP_CROP按如下方式填充圖片:按比例擴大圖片的size,僅僅橫向居中,使得圖片長(寬)等於或大於View的長(寬)。對於CENTER_CROP,其不僅橫向居中,而且垂直也居中。
具體實現方式:重載ImageView,並重寫setFrame方法來對ImageView中的drawable進行變換,代碼如下:

  1. public class TopCropImageView extends ImageView {
  2. public TopCropImageView(Context context, AttributeSet attrs) {
  3. super(context, attrs);
  4. setScaleType(ScaleType.MATRIX);
  5. }
  6. public TopCropImageView(Context context, AttributeSet attrs, int defStyle) {
  7. super(context, attrs, defStyle);
  8. setScaleType(ScaleType.MATRIX);
  9. }
  10. public TopCropImageView(Context context) {
  11. super(context);
  12. setScaleType(ScaleType.MATRIX);
  13. }
  14. @Override
  15. protected boolean setFrame(int l, int t, int r, int b)
  16. {
  17. if (getDrawable() == null) {
  18. return super.setFrame(l, t, r, b);
  19. }
  20. Matrix matrix = getImageMatrix();
  21. float scaleWidth = getWidth()/(float)getDrawable().getIntrinsicWidth();
  22. float scaleHeight = getHeight()/(float)getDrawable().getIntrinsicHeight();
  23. float scaleFactor = (scaleWidth > scaleHeight) ? scaleWidth : scaleHeight;
  24. matrix.setScale(scaleFactor, scaleFactor, 0, 0);
  25. if (scaleFactor == scaleHeight) {
  26. float tanslateX = ((getDrawable().getIntrinsicWidth() * scaleFactor) - getWidth()) / 2;
  27. matrix.postTranslate(-tanslateX, 0);
  28. }
  29. setImageMatrix(matrix);
  30. return super.setFrame(l, t, r, b);
  31. }
  32. }

代碼中首先計算ImageView尺寸和Drawable尺寸的比值,用變量scaleWidth和scaleHeight保存,並用scaleFactor取兩者較大值,因為我們要滿足圖片長(寬)等於或大於View的長(寬),然後調用matri.setScale進行圖片的縮放操作,接下來的if (scaleFactor == scaleHeight) 的含義是Drawable放大後的width大於ImageView的width,這意味著我們需要進行水平居中平移,if分支中的代碼即實現了平移操作,最後通過setImageMatrix(matrix)將matrix應用到image中來實現TOP_CROP的填充方式。下面兩張圖顯示了CENTER_CROP和TOP_CROP的不同效果:

Copyright © Linux教程網 All Rights Reserved