我正在Android中编写自定义的Circular ImageView。我需要在它上面设置一个Drawable覆盖,所以我选择编写一个自定义的CircularImageView来保存图片本身+ drawable。
其实我有两个问题:
有些人要澄清:
我想要实现的目标:
我现在拥有的东西:(请不要考虑黑框边框,只是为了澄清错误的图像“重力”)
我的观看代码:
public class CrownCircularImageView extends ImageView {
private Drawable crown;
private int canvasSize;
private int crownWidth;
private int crownHeight;
// Object used to draw
private Bitmap image;
private Drawable drawable;
private Paint paint;
private Paint crownPaint;
public CrownCircularImageView(Context context) {
this(context, null, 0);
}
public CrownCircularImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CrownCircularImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs, defStyleAttr);
}
private void init(Context context, AttributeSet attrs, int defStyleAttr) {
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
crownPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
this.crown = ContextCompat.getDrawable(context, R.drawable.ic_crown);
}
private void loadBitmap() {
if (this.drawable == getDrawable())
return;
this.drawable = getDrawable();
this.image = drawableToBitmap(this.drawable);
updateShader();
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
canvasSize = w - crownWidth;
if (h < canvasSize)
canvasSize = h - crownHeight;
if (image != null)
updateShader();
}
private void updateShader() {
if (image == null)
return;
// Crop Center Image
image = cropBitmap(image);
// Create Shader
BitmapShader shader = new BitmapShader(image, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
// Center Image in Shader
Matrix matrix = new Matrix();
matrix.setScale((float) canvasSize / (float) image.getWidth(), (float) canvasSize / (float) image.getHeight());
shader.setLocalMatrix(matrix);
// Set Shader in Paint
paint.setShader(shader);
}
private Bitmap cropBitmap(Bitmap bitmap) {
Bitmap bmp;
if (bitmap.getWidth() >= bitmap.getHeight()) {
bmp = Bitmap.createBitmap(
bitmap,
bitmap.getWidth() / 2 - bitmap.getHeight() / 2,
0,
bitmap.getHeight(),
bitmap.getHeight());
} else {
bmp = Bitmap.createBitmap(
bitmap,
0,
bitmap.getHeight() / 2 - bitmap.getWidth() / 2,
bitmap.getWidth(),
bitmap.getWidth());
}
return bmp;
}
private Bitmap drawableToBitmap(Drawable drawable) {
if (drawable == null) {
return null;
} else if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
}
int intrinsicWidth = drawable.getIntrinsicWidth();
int intrinsicHeight = drawable.getIntrinsicHeight();
if (!(intrinsicWidth > 0 && intrinsicHeight > 0))
return null;
try {
// Create Bitmap object out of the drawable
Bitmap bitmap = Bitmap.createBitmap(intrinsicWidth, intrinsicHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
} catch (OutOfMemoryError e) {
// Simply return null of failed bitmap creations
Log.e(getClass().toString(), "Encountered OutOfMemoryError while generating bitmap!");
return null;
}
}
@Override
public void onDraw(Canvas canvas) {
// Load the bitmap
loadBitmap();
// Check if image isn't null
if (image == null)
return;
if (!isInEditMode()) {
canvasSize = canvas.getWidth();
if (canvas.getHeight() < canvasSize) {
canvasSize = canvas.getHeight();
}
}
int circleCenter = (canvasSize - crownHeight) / 2;
int cx = (canvasSize - crownWidth) / 2;
int cy = (canvasSize - crownHeight) / 2;
Bitmap crownBmp = drawableToBitmap(crown);
int crownX = cx;
int crownY = cy;
canvas.drawCircle(cx, cy, circleCenter, paint);
canvas.drawBitmap(crownBmp, crownX, crownY, crownPaint);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = measureWidth(widthMeasureSpec);
int height = measureHeight(heightMeasureSpec);
crownWidth = crown.getIntrinsicWidth();
crownHeight = crown.getIntrinsicHeight();
setMeasuredDimension(width, height);
}
@Override
public ScaleType getScaleType() {
return ScaleType.CENTER_CROP;
}
private int measureWidth(int measureSpec) {
int result;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
// The parent has determined an exact size for the child.
result = specSize;
} else if (specMode == MeasureSpec.AT_MOST) {
// The child can be as large as it wants up to the specified size.
result = specSize;
} else {
// The parent has not imposed any constraint on the child.
result = canvasSize;
}
return result + crown.getIntrinsicWidth();
}
private int measureHeight(int measureSpecHeight) {
int result;
int specMode = MeasureSpec.getMode(measureSpecHeight);
int specSize = MeasureSpec.getSize(measureSpecHeight);
if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else if (specMode == MeasureSpec.AT_MOST) {
// The child can be as large as it wants up to the specified size.
result = specSize;
} else {
// Measure the text (beware: ascent is a negative number)
result = canvasSize;
}
return (result + 2 + crown.getIntrinsicHeight());
}
}
答案 0 :(得分:1)
您可以创建一个新的位图,在带有圆形遮罩的透明背景上绘制旧位图,然后在其上绘制表冠。此示例还允许在图像周围添加填充。
您需要调整CIRCLE_PADDING
和RESIZE_CROWN_FACTOR
的值以满足您的需求。
public class CrownImageView extends ImageView {
private static final int CIRCLE_PADDING = 25;
private static final float RESIZE_CROWN_FACTOR = 1.5f;
private Bitmap rounded;
private Bitmap resizedCrown;
public CrownImageView(final Context context) {
super(context);
}
public CrownImageView(final Context context, final AttributeSet attrs) {
super(context, attrs);
}
public CrownImageView(final Context context, final AttributeSet attrs, final int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onDraw(Canvas canvas) {
Drawable drawable = getDrawable();
if (drawable == null || getWidth() == 0 || getHeight() == 0) {
return;
}
if (resizedCrown == null) {
loadCrown();
}
loadImage(drawable);
canvas.drawBitmap(rounded, 0, 0, null);
canvas.drawBitmap(resizedCrown, canvas.getWidth() - resizedCrown.getWidth(), 0, null);
}
private void loadImage(Drawable drawable) {
Bitmap bmp = bitmapFromDrawable(drawable);
final Rect rect = new Rect(0, 0, bmp.getWidth(), bmp.getHeight());
final Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setDither(true);
rounded = Bitmap.createBitmap(bmp.getWidth(),
bmp.getHeight(), Bitmap.Config.ARGB_8888);
Canvas newCanvas = new Canvas(rounded);
newCanvas.drawARGB(0, 0, 0, 0);
float centerX = getWidth() / 2;
float centerY = getHeight() / 2;
float radius = Math.min(getWidth(), getHeight()) / 2 - CIRCLE_PADDING;
newCanvas.drawCircle(centerX, centerY, radius, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
newCanvas.drawBitmap(bmp, rect, rect, paint);
}
private void loadCrown() {
Bitmap crown = BitmapFactory.decodeResource(getResources(), R.drawable.crown);
resizedCrown = Bitmap.createScaledBitmap(crown,
(int) (crown.getWidth() * RESIZE_CROWN_FACTOR),
(int) (crown.getHeight() * RESIZE_CROWN_FACTOR),
true);
}
private Bitmap bitmapFromDrawable(Drawable drawable) {
Bitmap bmp;
if (drawable instanceof BitmapDrawable) {
bmp = ((BitmapDrawable) drawable).getBitmap();
} else {
bmp = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas bmpCanvas = new Canvas(bmp);
drawable.setBounds(0, 0, bmpCanvas.getWidth(), bmpCanvas.getHeight());
drawable.draw(bmpCanvas);
}
return bmp;
}
}
更新:您可以像这样使用Glide
final CrownImageView imageView = (CrownImageView) findViewById(R.id.fragment_kids_row_img_kids);
Glide.with(this).load(yourimageurl).into(imageView);
答案 1 :(得分:0)
图像是左上角绘制的,我需要将它绘制在视图的中心
是的,这是因为.drawCircle的参数
canvas.drawCircle(cx, cy, circleCenter, paint);
您不是为图像计算它们。这应该是
int centerX = getWidth() / 2;
int centerY = getHeight() / 2;
float bitmapRadius = Math.min(image.getWidth(), image.getHeight()) / 2f;
canvas.drawCircle(centerX, centerY, bitmapRadius, paint);
但我认为最好保存这些值并在大小更改时重新计算它们。
我需要我的王冠更大(可画)但我不知道如何调整它。
您自己指定位图的大小 - 通过指定其他大小使其更大一些。
Bitmap bitmap = Bitmap.createBitmap(
intrinsicWidth + scale,
intrinsicHeight + scale,
Bitmap.Config.ARGB_8888);
我修改了您的代码:http://pastebin.com/0h02Tqh1