这些解决方案都不适合我,因为我想要一个支持水平或垂直方向上任意裁切的类,并且希望它允许我动态更改裁切。我还需要Picasso兼容性,而Picasso会懒惰地设置图像可绘制对象。
我的实现直接从AOSP中的ImageView.java改编而来。要使用它,请在XML中这样声明:
<com.yourapp.PercentageCropImageView
android:id="@+id/view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="matrix"/>
从源头上,如果您希望获得丰收,请致电:
imageView.setCropYCenterOffsetPct(0f);
如果您希望收成不好,请致电:
imageView.setCropYCenterOffsetPct(1.0f);
如果您希望在收割时下降1/3,请致电:
imageView.setCropYCenterOffsetPct(0.33f);
此外,如果您选择使用其他裁剪方法,例如fit_center,则可以这样做,并且不会触发任何此自定义逻辑。(其他实现仅允许您使用其裁剪方法)。
最后,我添加了一个方法redraw(),因此,如果您选择在代码中动态更改您的裁剪方法/ scaleType,则可以强制视图重新绘制。例如:
fullsizeImageView.setScaleType(ScaleType.FIT_CENTER);
fullsizeImageView.redraw();
要返回到自定义的中上三等作物,请致电:
fullsizeImageView.setScaleType(ScaleType.MATRIX);
fullsizeImageView.redraw();
这是课程:
/*
* Adapted from ImageView code at:
* http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.4.4_r1/android/widget/ImageView.java
*/
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;
public class PercentageCropImageView extends ImageView{
private Float mCropYCenterOffsetPct;
private Float mCropXCenterOffsetPct;
public PercentageCropImageView(Context context) {
super(context);
}
public PercentageCropImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public PercentageCropImageView(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
}
public float getCropYCenterOffsetPct() {
return mCropYCenterOffsetPct;
}
public void setCropYCenterOffsetPct(float cropYCenterOffsetPct) {
if (cropYCenterOffsetPct > 1.0) {
throw new IllegalArgumentException("Value too large: Must be <= 1.0");
}
this.mCropYCenterOffsetPct = cropYCenterOffsetPct;
}
public float getCropXCenterOffsetPct() {
return mCropXCenterOffsetPct;
}
public void setCropXCenterOffsetPct(float cropXCenterOffsetPct) {
if (cropXCenterOffsetPct > 1.0) {
throw new IllegalArgumentException("Value too large: Must be <= 1.0");
}
this.mCropXCenterOffsetPct = cropXCenterOffsetPct;
}
private void myConfigureBounds() {
if (this.getScaleType() == ScaleType.MATRIX) {
/*
* Taken from Android's ImageView.java implementation:
*
* Excerpt from their source:
} else if (ScaleType.CENTER_CROP == mScaleType) {
mDrawMatrix = mMatrix;
float scale;
float dx = 0, dy = 0;
if (dwidth * vheight > vwidth * dheight) {
scale = (float) vheight / (float) dheight;
dx = (vwidth - dwidth * scale) * 0.5f;
} else {
scale = (float) vwidth / (float) dwidth;
dy = (vheight - dheight * scale) * 0.5f;
}
mDrawMatrix.setScale(scale, scale);
mDrawMatrix.postTranslate((int) (dx + 0.5f), (int) (dy + 0.5f));
}
*/
Drawable d = this.getDrawable();
if (d != null) {
int dwidth = d.getIntrinsicWidth();
int dheight = d.getIntrinsicHeight();
Matrix m = new Matrix();
int vwidth = getWidth() - this.getPaddingLeft() - this.getPaddingRight();
int vheight = getHeight() - this.getPaddingTop() - this.getPaddingBottom();
float scale;
float dx = 0, dy = 0;
if (dwidth * vheight > vwidth * dheight) {
float cropXCenterOffsetPct = mCropXCenterOffsetPct != null ?
mCropXCenterOffsetPct.floatValue() : 0.5f;
scale = (float) vheight / (float) dheight;
dx = (vwidth - dwidth * scale) * cropXCenterOffsetPct;
} else {
float cropYCenterOffsetPct = mCropYCenterOffsetPct != null ?
mCropYCenterOffsetPct.floatValue() : 0f;
scale = (float) vwidth / (float) dwidth;
dy = (vheight - dheight * scale) * cropYCenterOffsetPct;
}
m.setScale(scale, scale);
m.postTranslate((int) (dx + 0.5f), (int) (dy + 0.5f));
this.setImageMatrix(m);
}
}
}
// These 3 methods call configureBounds in ImageView.java class, which
// adjusts the matrix in a call to center_crop (android's built-in
// scaling and centering crop method). We also want to trigger
// in the same place, but using our own matrix, which is then set
// directly at line 588 of ImageView.java and then copied over
// as the draw matrix at line 942 of ImageVeiw.java
@Override
protected boolean setFrame(int l, int t, int r, int b) {
boolean changed = super.setFrame(l, t, r, b);
this.myConfigureBounds();
return changed;
}
@Override
public void setImageDrawable(Drawable d) {
super.setImageDrawable(d);
this.myConfigureBounds();
}
@Override
public void setImageResource(int resId) {
super.setImageResource(resId);
this.myConfigureBounds();
}
public void redraw() {
Drawable d = this.getDrawable();
if (d != null) {
// Force toggle to recalculate our bounds
this.setImageDrawable(null);
this.setImageDrawable(d);
}
}
}