2013-09-23 54 views
12

我試圖定位一個ImageView,使圖像的底部總是固定在視圖的底部,不管ImageView的高度有多小。然而,沒有一種規模類型似乎適合我所要做的。 CenterCrop很近,但我不希望圖像居中。類似於CSS如何處理絕對定位。Android - ImageView的bottomCrop而不是centerCrop

原因是,我需要動畫化ImageView的高度,但看起來好像它是「揭示」圖像的上半部分。我認爲找出這種裁剪圖像的方法並將ImageView高度動畫化是最簡單的方法,但如果有人知道更好的方法,我會喜歡指向正確的方向。

任何幫助表示讚賞。

回答

19

我最終創建了ImageView子類並創建了一種啓用'BottomCrop'類型圖像縮放的方法。

我通過根據視圖高度計算比例和預期圖像高度,將圖像分配到正確大小的RectF。

public class BottomCropImage extends ImageView { 

public BottomCropImage(Context context) { 
    super(context); 
    setup(); 
} 

public BottomCropImage(Context context, AttributeSet attrs) { 
    super(context, attrs); 
    setup(); 
} 

public BottomCropImage(Context context, AttributeSet attrs, 
     int defStyle) { 
    super(context, attrs, defStyle); 
    setup(); 
} 

private void setup() { 
    setScaleType(ScaleType.MATRIX); 
} 

@Override 
protected boolean setFrame(int l, int t, int r, int b) { 
    Matrix matrix = getImageMatrix(); 

    float scale; 
    int viewWidth = getWidth() - getPaddingLeft() - getPaddingRight(); 
    int viewHeight = getHeight() - getPaddingTop() - getPaddingBottom(); 
    int drawableWidth = getDrawable().getIntrinsicWidth(); 
    int drawableHeight = getDrawable().getIntrinsicHeight(); 

    //Get the scale 
    if (drawableWidth * viewHeight > drawableHeight * viewWidth) { 
     scale = (float) viewHeight/(float) drawableHeight; 
    } else { 
     scale = (float) viewWidth/(float) drawableWidth; 
    } 

    //Define the rect to take image portion from 
    RectF drawableRect = new RectF(0, drawableHeight - (viewHeight/scale), drawableWidth, drawableHeight); 
    RectF viewRect = new RectF(0, 0, viewWidth, viewHeight); 
    matrix.setRectToRect(drawableRect, viewRect, Matrix.ScaleToFit.FILL); 


    setImageMatrix(matrix); 

    return super.setFrame(l, t, r, b); 
}   

} 
+0

如何將其轉換爲TopCropImage? – Mani

+1

@Mani我最終做了兩個,我想它會派上用場! [Github鏈接](https://github.com/Jpoliachik/BottomTopCropImage/blob/master/example/src/com/justinpoliachik/bottomtopcropimage/TopCropImage.java) – Jpoliachik

+0

我自己做過,因爲我需要在昨天完成它本身,感謝無論如何,我做的和你做的一樣 – Mani

-2

你試過Imageview的Scaletype FIT_END這是最好的可用選項來顯示圖像的結尾。

+2

FIT_END不裁剪圖像。它適合可用框架中的圖像。它看起來像沒有可用的內置比例類型做我正在尋找,但我需要繼承ImageView。 – Jpoliachik

+0

這就是對,FIT_END不裁剪圖像。但這是顯示圖像結束的唯一選項。 – prijupaul

12

我用@Jpoliachik代碼和它的工作很好,我做了幾個調整的,因爲有時getWidthgetHeight正在返回0 - getMeasuredWidthgetMeasuredHeight解決了這個問題。

@Override 
protected boolean setFrame(int l, int t, int r, int b) { 
    if (getDrawable() == null) 
     return super.setFrame(l, t, r, b); 

    Matrix matrix = getImageMatrix(); 

    float scale; 
    int viewWidth = getMeasuredWidth() - getPaddingLeft() - getPaddingRight(); 
    int viewHeight = getMeasuredHeight() - getPaddingTop() - getPaddingBottom(); 
    int drawableWidth = getDrawable().getIntrinsicWidth(); 
    int drawableHeight = getDrawable().getIntrinsicHeight(); 
    //Get the scale 
    if (drawableWidth * viewHeight > drawableHeight * viewWidth) { 
     scale = (float) viewHeight/(float) drawableHeight; 
    } else { 
     scale = (float) viewWidth/(float) drawableWidth; 
    } 

    //Define the rect to take image portion from 
    RectF drawableRect = new RectF(0, drawableHeight - (viewHeight/scale), drawableWidth, drawableHeight); 
    RectF viewRect = new RectF(0, 0, viewWidth, viewHeight); 
    matrix.setRectToRect(drawableRect, viewRect, Matrix.ScaleToFit.FILL); 

    setImageMatrix(matrix); 

    return super.setFrame(l, t, r, b); 
} 
+1

這解決了我在景觀和肖像之間切換的問題,謝謝。 – Gabe

+1

當軟鍵盤調整「ImageView」(當封閉的Activity有'android:windowSoftInputMode =「adjustResize」')時,'Jpoliachik'代碼會遇到問題。你的代碼很好的解決了這個問題! Thx –

30

Jpoliachik's答案是不夠冷靜,讓我想概括它同時支持頂部/底部和左/右,通過可變的量。 :)現在頂部裁剪,只需撥打setOffset(0,0),底部裁剪setOffset(0,1),左邊裁剪也是setOffset(0,0),右邊裁剪setOffset(1,0)。如果要在一個維度上將圖像的一部分偏移到視口中,可以調用例如setOffset(0, 0.25f)將其向下移動25%的非可見空間,而0.5f將居中。乾杯!

public class CropImageView extends ImageView { 
    float mWidthPercent = 0, mHeightPercent = 0; 

    public CropImageView(Context context) { 
     super(context); 
     setup(); 
    } 

    public CropImageView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     setup(); 
    } 

    public CropImageView(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
     setup(); 
    } 

    // How far right or down should we place the upper-left corner of the cropbox? [0, 1] 
    public void setOffset(float widthPercent, float heightPercent) { 
     mWidthPercent = widthPercent; 
     mHeightPercent = heightPercent; 
    } 

    private void setup() { 
     setScaleType(ScaleType.MATRIX); 
    } 

    @Override 
    protected boolean setFrame(int l, int t, int r, int b) { 
     Matrix matrix = getImageMatrix(); 

     float scale; 
     int viewWidth = getWidth() - getPaddingLeft() - getPaddingRight(); 
     int viewHeight = getHeight() - getPaddingTop() - getPaddingBottom(); 
     int drawableWidth = 0, drawableHeight = 0; 
     // Allow for setting the drawable later in code by guarding ourselves here. 
     if (getDrawable() != null) { 
      drawableWidth = getDrawable().getIntrinsicWidth(); 
      drawableHeight = getDrawable().getIntrinsicHeight(); 
     } 

     // Get the scale. 
     if (drawableWidth * viewHeight > drawableHeight * viewWidth) { 
      // Drawable is flatter than view. Scale it to fill the view height. 
      // A Top/Bottom crop here should be identical in this case. 
      scale = (float) viewHeight/(float) drawableHeight; 
     } else { 
      // Drawable is taller than view. Scale it to fill the view width. 
      // Left/Right crop here should be identical in this case. 
      scale = (float) viewWidth/(float) drawableWidth; 
     } 

     float viewToDrawableWidth = viewWidth/scale; 
     float viewToDrawableHeight = viewHeight/scale; 
     float xOffset = mWidthPercent * (drawableWidth - viewToDrawableWidth); 
     float yOffset = mHeightPercent * (drawableHeight - viewToDrawableHeight); 

     // Define the rect from which to take the image portion. 
     RectF drawableRect = new RectF(xOffset, yOffset, xOffset + viewToDrawableWidth, 
       yOffset + viewToDrawableHeight); 
     RectF viewRect = new RectF(0, 0, viewWidth, viewHeight); 
     matrix.setRectToRect(drawableRect, viewRect, Matrix.ScaleToFit.FILL); 

     setImageMatrix(matrix); 

     return super.setFrame(l, t, r, b); 
    } 
} 
+7

我改變了,所以調整大小的代碼將從onSizeChanged()方法而不是setFrame()調用,因爲它不會在調整大小後調用並且圖像不能正確對齊。似乎工作。謝謝 –

+1

正如Carlos Fonseca所說,最好在onSizeChanged()中放置調整大小的代碼,特別是如果在視圖尋呼機中使用此CropImageView,或者您將有一些圖像根本不顯示 –

相關問題