歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

ImageView ScaleType 的擴展之Top Crop 的實現

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

代碼中首先計算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