Android的 ImageView 背景设置圆角没有什么效果 不过有时候在项目开发的过程中会出现很多稍微有点弧度的图片类似于ios的AppStore里面的应用图标如下图
接下来是代码
package com.example.gzl.myapplication.widget;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.net.Uri;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.ImageView;
import com.example.gzl.myapplication.R;
/**
* 圆角图片
* Created by 智光 on 2016/7/6.
*/
public class RadiusImageWidget extends ImageView {
private int mResource = 0;
private static final ImageView.ScaleType[] sScaleTypeArray = {
ImageView.ScaleType.MATRIX,
ImageView.ScaleType.FIT_XY,
ImageView.ScaleType.FIT_START,
ImageView.ScaleType.FIT_CENTER,
ImageView.ScaleType.FIT_END,
ImageView.ScaleType.CENTER,
ImageView.ScaleType.CENTER_CROP,
ImageView.ScaleType.CENTER_INSIDE
};
// Set default scale type to FIT_CENTER, which is default scale type of
// original ImageView.
private ImageView.ScaleType mScaleType = ImageView.ScaleType.FIT_CENTER;
private float mLeftTopCornerRadius = 0.0f;
private float mRightTopCornerRadius = 0.0f;
private float mLeftBottomCornerRadius = 0.0f;
private float mRightBottomCornerRadius = 0.0f;
private float mBorderWidth = 0.0f;
private static final int DEFAULT_BORDER_COLOR = Color.BLACK;
private ColorStateList mBorderColor = ColorStateList.valueOf(DEFAULT_BORDER_COLOR);
private boolean isOval = false;
private Drawable mDrawable;
private float[] mRadii = new float[]{0, 0, 0, 0, 0, 0, 0, 0};
public RadiusImageWidget(Context context) {
super(context);
}
public RadiusImageWidget(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public RadiusImageWidget(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.RadidsImageView, defStyle, 0);
final int index = a.getInt(R.styleable.RadidsImageView_android_scaleType, -1);
if (index >= 0) {
setScaleType(sScaleTypeArray[index]);
}
mLeftTopCornerRadius = a.getDimensionPixelSize(
R.styleable.RadidsImageView_left_top_radius, 0);
mRightTopCornerRadius = a.getDimensionPixelSize(
R.styleable.RadidsImageView_right_top_radius, 0);
mLeftBottomCornerRadius = a.getDimensionPixelSize(
R.styleable.RadidsImageView_left_bottom_radius, 0);
mRightBottomCornerRadius = a.getDimensionPixelSize(
R.styleable.RadidsImageView_right_bottom_radius, 0);
if (mLeftTopCornerRadius < 0.0f || mRightTopCornerRadius < 0.0f
|| mLeftBottomCornerRadius < 0.0f || mRightBottomCornerRadius < 0.0f) {
throw new IllegalArgumentException("radius values cannot be negative.");
}
mRadii = new float[]{
mLeftTopCornerRadius, mLeftTopCornerRadius,
mRightTopCornerRadius, mRightTopCornerRadius,
mRightBottomCornerRadius, mRightBottomCornerRadius,
mLeftBottomCornerRadius, mLeftBottomCornerRadius};
mBorderWidth = a.getDimensionPixelSize(
R.styleable.RadidsImageView_sriv_border_width, 0);
if (mBorderWidth < 0) {
throw new IllegalArgumentException("border width cannot be negative.");
}
mBorderColor = a
.getColorStateList(R.styleable.RadidsImageView_sriv_border_color);
if (mBorderColor == null) {
mBorderColor = ColorStateList.valueOf(DEFAULT_BORDER_COLOR);
}
isOval = a.getBoolean(R.styleable.RadidsImageView_sriv_oval, false);
a.recycle();
updateDrawable();
}
@Override
protected void drawableStateChanged() {
super.drawableStateChanged();
invalidate();
}
@Override
public ImageView.ScaleType getScaleType() {
return mScaleType;
}
@Override
public void setScaleType(ImageView.ScaleType scaleType) {
super.setScaleType(scaleType);
mScaleType = scaleType;
updateDrawable();
}
@Override
public void setImageDrawable(Drawable drawable) {
mResource = 0;
mDrawable = SelectableRoundedCornerDrawable.fromDrawable(drawable, getResources());
super.setImageDrawable(mDrawable);
updateDrawable();
}
@Override
public void setImageBitmap(Bitmap bm) {
mResource = 0;
mDrawable = SelectableRoundedCornerDrawable.fromBitmap(bm, getResources());
super.setImageDrawable(mDrawable);
updateDrawable();
}
@Override
public void setImageResource(int resId) {
if (mResource != resId) {
mResource = resId;
mDrawable = resolveResource();
super.setImageDrawable(mDrawable);
updateDrawable();
}
}
@Override
public void setImageURI(Uri uri) {
super.setImageURI(uri);
setImageDrawable(getDrawable());
}
private Drawable resolveResource() {
Resources rsrc = getResources();
if (rsrc == null) {
return null;
}
Drawable d = null;
if (mResource != 0) {
try {
d = rsrc.getDrawable(mResource);
} catch (Resources.NotFoundException e) {
// Don't try again.
mResource = 0;
}
}
return SelectableRoundedCornerDrawable.fromDrawable(d, getResources());
}
private void updateDrawable() {
if (mDrawable == null) {
return;
}
((SelectableRoundedCornerDrawable) mDrawable).setScaleType(mScaleType);
((SelectableRoundedCornerDrawable) mDrawable).setCornerRadii(mRadii);
((SelectableRoundedCornerDrawable) mDrawable).setBorderWidth(mBorderWidth);
((SelectableRoundedCornerDrawable) mDrawable).setBorderColor(mBorderColor);
((SelectableRoundedCornerDrawable) mDrawable).setOval(isOval);
}
public float getCornerRadius() {
return mLeftTopCornerRadius;
}
/**
* Set radii for each corner.
*
* @param leftTop The desired radius for left-top corner in dip.
* @param rightTop The desired desired radius for right-top corner in dip.
* @param leftBottom The desired radius for left-bottom corner in dip.
* @param rightBottom The desired radius for right-bottom corner in dip.
*/
public void setCornerRadiiDP(float leftTop, float rightTop, float leftBottom, float rightBottom) {
final float density = getResources().getDisplayMetrics().density;
final float lt = leftTop * density;
final float rt = rightTop * density;
final float lb = leftBottom * density;
final float rb = rightBottom * density;
mRadii = new float[]{lt, lt, rt, rt, rb, rb, lb, lb};
updateDrawable();
}
public float getBorderWidth() {
return mBorderWidth;
}
/**
* Set border width.
*
* @param width The desired width in dip.
*/
public void setBorderWidthDP(float width) {
float scaledWidth = getResources().getDisplayMetrics().density * width;
if (mBorderWidth == scaledWidth) {
return;
}
mBorderWidth = scaledWidth;
updateDrawable();
invalidate();
}
public int getBorderColor() {
return mBorderColor.getDefaultColor();
}
public void setBorderColor(int color) {
setBorderColor(ColorStateList.valueOf(color));
}
public ColorStateList getBorderColors() {
return mBorderColor;
}
public void setBorderColor(ColorStateList colors) {
if (mBorderColor.equals(colors)) {
return;
}
mBorderColor = (colors != null) ? colors : ColorStateList
.valueOf(DEFAULT_BORDER_COLOR);
updateDrawable();
if (mBorderWidth > 0) {
invalidate();
}
}
public boolean isOval() {
return isOval;
}
public void setOval(boolean oval) {
isOval = oval;
updateDrawable();
invalidate();
}
static class SelectableRoundedCornerDrawable extends Drawable {
private static final String TAG = "SelectableRoundedCornerDrawable";
private static final int DEFAULT_BORDER_COLOR = Color.BLACK;
private RectF mBounds = new RectF();
private RectF mBorderBounds = new RectF();
private final RectF mBitmapRect = new RectF();
private final int mBitmapWidth;
private final int mBitmapHeight;
private final Paint mBitmapPaint;
private final Paint mBorderPaint;
private BitmapShader mBitmapShader;
private float[] mRadii = new float[]{0, 0, 0, 0, 0, 0, 0, 0};
private float[] mBorderRadii = new float[]{0, 0, 0, 0, 0, 0, 0, 0};
private boolean mOval = false;
private float mBorderWidth = 0;
private ColorStateList mBorderColor = ColorStateList.valueOf(DEFAULT_BORDER_COLOR);
// Set default scale type to FIT_CENTER, which is default scale type of
// original ImageView.
private ImageView.ScaleType mScaleType = ImageView.ScaleType.FIT_CENTER;
private Path mPath = new Path();
private Bitmap mBitmap;
private boolean mBoundsConfigured = false;
public SelectableRoundedCornerDrawable(Bitmap bitmap, Resources r) {
mBitmap = bitmap;
mBitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
if (bitmap != null) {
mBitmapWidth = bitmap.getScaledWidth(r.getDisplayMetrics());
mBitmapHeight = bitmap.getScaledHeight(r.getDisplayMetrics());
} else {
mBitmapWidth = mBitmapHeight = -1;
}
mBitmapRect.set(0, 0, mBitmapWidth, mBitmapHeight);
mBitmapPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mBitmapPaint.setStyle(Paint.Style.FILL);
mBitmapPaint.setShader(mBitmapShader);
mBorderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mBorderPaint.setStyle(Paint.Style.STROKE);
mBorderPaint.setColor(mBorderColor.getColorForState(getState(), DEFAULT_BORDER_COLOR));
mBorderPaint.setStrokeWidth(mBorderWidth);
}
public static SelectableRoundedCornerDrawable fromBitmap(Bitmap bitmap, Resources r) {
if (bitmap != null) {
return new SelectableRoundedCornerDrawable(bitmap, r);
} else {
return null;
}
}
public static Drawable fromDrawable(Drawable drawable, Resources r) {
if (drawable != null) {
if (drawable instanceof SelectableRoundedCornerDrawable) {
return drawable;
} else if (drawable instanceof LayerDrawable) {
LayerDrawable ld = (LayerDrawable) drawable;
final int num = ld.getNumberOfLayers();
for (int i = 0; i < num; i++) {
Drawable d = ld.getDrawable(i);
ld.setDrawableByLayerId(ld.getId(i), fromDrawable(d, r));
}
return ld;
}
Bitmap bm = drawableToBitmap(drawable);
if (bm != null) {
return new SelectableRoundedCornerDrawable(bm, r);
} else {
Log.w(TAG, "Failed to create bitmap from drawable!");
}
}
return drawable;
}
public static Bitmap drawableToBitmap(Drawable drawable) {
if (drawable == null) {
return null;
}
if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
}
Bitmap bitmap;
int width = Math.max(drawable.getIntrinsicWidth(), 2);
int height = Math.max(drawable.getIntrinsicHeight(), 2);
try {
bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
} catch (IllegalArgumentException e) {
e.printStackTrace();
bitmap = null;
}
return bitmap;
}
@Override
public boolean isStateful() {
return mBorderColor.isStateful();
}
@Override
protected boolean onStateChange(int[] state) {
int newColor = mBorderColor.getColorForState(state, 0);
if (mBorderPaint.getColor() != newColor) {
mBorderPaint.setColor(newColor);
return true;
} else {
return super.onStateChange(state);
}
}
private void configureBounds(Canvas canvas) {
// I have discovered a truly marvelous explanation of this,
// which this comment space is too narrow to contain. :)
// If you want to understand what's going on here,
// See http://www.joooooooooonhokim.com/?p=289
Rect clipBounds = canvas.getClipBounds();
Matrix canvasMatrix = canvas.getMatrix();
if (ImageView.ScaleType.CENTER == mScaleType) {
mBounds.set(clipBounds);
} else if (ImageView.ScaleType.CENTER_CROP == mScaleType) {
applyScaleToRadii(canvasMatrix);
mBounds.set(clipBounds);
} else if (ImageView.ScaleType.FIT_XY == mScaleType) {
Matrix m = new Matrix();
m.setRectToRect(mBitmapRect, new RectF(clipBounds), Matrix.ScaleToFit.FILL);
mBitmapShader.setLocalMatrix(m);
mBounds.set(clipBounds);
} else if (ImageView.ScaleType.FIT_START == mScaleType || ImageView.ScaleType.FIT_END == mScaleType
|| ImageView.ScaleType.FIT_CENTER == mScaleType || ImageView.ScaleType.CENTER_INSIDE == mScaleType) {
applyScaleToRadii(canvasMatrix);
mBounds.set(mBitmapRect);
} else if (ImageView.ScaleType.MATRIX == mScaleType) {
applyScaleToRadii(canvasMatrix);
mBounds.set(mBitmapRect);
}
}
private void applyScaleToRadii(Matrix m) {
float[] values = new float[9];
m.getValues(values);
for (int i = 0; i < mRadii.length; i++) {
mRadii[i] = mRadii[i] / values[0];
}
}
private void adjustCanvasForBorder(Canvas canvas) {
Matrix canvasMatrix = canvas.getMatrix();
final float[] values = new float[9];
canvasMatrix.getValues(values);
final float scaleFactorX = values[0];
final float scaleFactorY = values[4];
final float translateX = values[2];
final float translateY = values[5];
final float newScaleX = mBounds.width()
/ (mBounds.width() + mBorderWidth + mBorderWidth);
final float newScaleY = mBounds.height()
/ (mBounds.height() + mBorderWidth + mBorderWidth);
canvas.scale(newScaleX, newScaleY);
if (ImageView.ScaleType.FIT_START == mScaleType || ImageView.ScaleType.FIT_END == mScaleType
|| ImageView.ScaleType.FIT_XY == mScaleType || ImageView.ScaleType.FIT_CENTER == mScaleType
|| ImageView.ScaleType.CENTER_INSIDE == mScaleType || ImageView.ScaleType.MATRIX == mScaleType) {
canvas.translate(mBorderWidth, mBorderWidth);
} else if (ImageView.ScaleType.CENTER == mScaleType || ImageView.ScaleType.CENTER_CROP == mScaleType) {
// First, make translate values to 0
canvas.translate(
-translateX / (newScaleX * scaleFactorX),
-translateY / (newScaleY * scaleFactorY));
// Then, set the final translate values.
canvas.translate(-(mBounds.left - mBorderWidth), -(mBounds.top - mBorderWidth));
}
}
private void adjustBorderWidthAndBorderBounds(Canvas canvas) {
Matrix canvasMatrix = canvas.getMatrix();
final float[] values = new float[9];
canvasMatrix.getValues(values);
final float scaleFactor = values[0];
float viewWidth = mBounds.width() * scaleFactor;
mBorderWidth = (mBorderWidth * mBounds.width()) / (viewWidth - (2 * mBorderWidth));
mBorderPaint.setStrokeWidth(mBorderWidth);
mBorderBounds.set(mBounds);
mBorderBounds.inset(-mBorderWidth / 2, -mBorderWidth / 2);
}
private void setBorderRadii() {
for (int i = 0; i < mRadii.length; i++) {
if (mRadii[i] > 0) {
mBorderRadii[i] = mRadii[i];
mRadii[i] = mRadii[i] - mBorderWidth;
}
}
}
@Override
public void draw(Canvas canvas) {
canvas.save();
if (!mBoundsConfigured) {
configureBounds(canvas);
if (mBorderWidth > 0) {
adjustBorderWidthAndBorderBounds(canvas);
setBorderRadii();
}
mBoundsConfigured = true;
}
if (mOval) {
if (mBorderWidth > 0) {
adjustCanvasForBorder(canvas);
mPath.addOval(mBounds, Path.Direction.CW);
canvas.drawPath(mPath, mBitmapPaint);
mPath.reset();
mPath.addOval(mBorderBounds, Path.Direction.CW);
canvas.drawPath(mPath, mBorderPaint);
} else {
mPath.addOval(mBounds, Path.Direction.CW);
canvas.drawPath(mPath, mBitmapPaint);
}
} else {
if (mBorderWidth > 0) {
adjustCanvasForBorder(canvas);
mPath.addRoundRect(mBounds, mRadii, Path.Direction.CW);
canvas.drawPath(mPath, mBitmapPaint);
mPath.reset();
mPath.addRoundRect(mBorderBounds, mBorderRadii, Path.Direction.CW);
canvas.drawPath(mPath, mBorderPaint);
} else {
mPath.addRoundRect(mBounds, mRadii, Path.Direction.CW);
canvas.drawPath(mPath, mBitmapPaint);
}
}
canvas.restore();
}
public void setCornerRadii(float[] radii) {
if (radii == null)
return;
if (radii.length != 8) {
throw new ArrayIndexOutOfBoundsException("radii[] needs 8 values");
}
for (int i = 0; i < radii.length; i++) {
mRadii[i] = radii[i];
}
}
@Override
public int getOpacity() {
return (mBitmap == null || mBitmap.hasAlpha() || mBitmapPaint.getAlpha() < 255) ? PixelFormat.TRANSLUCENT
: PixelFormat.OPAQUE;
}
@Override
public void setAlpha(int alpha) {
mBitmapPaint.setAlpha(alpha);
invalidateSelf();
}
@Override
public void setColorFilter(ColorFilter cf) {
mBitmapPaint.setColorFilter(cf);
invalidateSelf();
}
@Override
public void setDither(boolean dither) {
mBitmapPaint.setDither(dither);
invalidateSelf();
}
@Override
public void setFilterBitmap(boolean filter) {
mBitmapPaint.setFilterBitmap(filter);
invalidateSelf();
}
@Override
public int getIntrinsicWidth() {
return mBitmapWidth;
}
@Override
public int getIntrinsicHeight() {
return mBitmapHeight;
}
public float getBorderWidth() {
return mBorderWidth;
}
public void setBorderWidth(float width) {
mBorderWidth = width;
mBorderPaint.setStrokeWidth(width);
}
public int getBorderColor() {
return mBorderColor.getDefaultColor();
}
public void setBorderColor(int color) {
setBorderColor(ColorStateList.valueOf(color));
}
public ColorStateList getBorderColors() {
return mBorderColor;
}
/**
* Controls border color of this ImageView.
*
* @param colors The desired border color. If it's null, no border will be
* drawn.
*/
public void setBorderColor(ColorStateList colors) {
if (colors == null) {
mBorderWidth = 0;
mBorderColor = ColorStateList.valueOf(Color.TRANSPARENT);
mBorderPaint.setColor(Color.TRANSPARENT);
} else {
mBorderColor = colors;
mBorderPaint.setColor(mBorderColor.getColorForState(getState(),
DEFAULT_BORDER_COLOR));
}
}
public boolean isOval() {
return mOval;
}
public void setOval(boolean oval) {
mOval = oval;
}
public ImageView.ScaleType getScaleType() {
return mScaleType;
}
public void setScaleType(ImageView.ScaleType scaleType) {
if (scaleType == null) {
return;
}
mScaleType = scaleType;
}
}
}
资源文件attrs
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="RadidsImageView">
<attr name="left_top_radius" format="dimension" />
<attr name="right_top_radius" format="dimension" />
<attr name="left_bottom_radius" format="dimension" />
<attr name="right_bottom_radius" format="dimension" />
<attr name="sriv_border_width" format="dimension" />
<attr name="sriv_border_color" format="color" />
<attr name="sriv_oval" format="boolean" />
<attr name="android:scaleType" />
</declare-styleable>
</resources>
引入资源文件便于对图片更好的设置 这是一个自定的RadiusImageWidget 控件
有以下功能
可以设置各个角的弧度
可以给图片设置边框颜色
设置边框宽度 等。。。
他的用法如下
1,XML中使用
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<com.example.gzl.myapplication.widget.RadiusImageWidget
android:id="@+id/redius_img"
android:layout_width="320dp"
android:layout_height="200dp"
android:scaleType="centerCrop"
android:src="@drawable/image"
app:left_bottom_radius="70dip"
app:left_top_radius="16dip"
app:right_bottom_radius="16dip"
app:right_top_radius="70dip" />
</LinearLayout>
2,代码中使用
package com.example.gzl.myapplication.activity;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import com.bumptech.glide.Glide;
import com.example.gzl.myapplication.R;
import com.example.gzl.myapplication.widget.RadiusImageWidget;
/**
* Created by 智光 on 2016/4/5.
*/
public class RadiusImage extends Activity {
private RadiusImageWidget redius_img;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.radiuslmage_layout);
redius_img = (RadiusImageWidget) findViewById(R.id.redius_img);
setRadiusImage();
}
private void setRadiusImage() {
//在布局中引用
Glide.with(this)
.load("http://tc.sinaimg.cn/maxwidth.2048/tc.service.weibo.com/p/mmbiz_qpic_cn/0dbdb8ca21725696a14d484e02f98a5a.jpg")
.error(R.drawable.image)
.placeholder(R.drawable.image)
.dontAnimate()
.centerCrop()
.into(redius_img);
redius_img.setBorderColor(Color.GREEN);//设置边框颜色
redius_img.setBorderWidthDP(5);//设置边框的宽度
redius_img.setCornerRadiiDP(5, 100, 5, 100);//设置左上右下的圆角弧度
//动态设置
RadiusImageWidget rediusview = new RadiusImageWidget(this);
redius_img.setBorderColor(Color.GREEN);//设置边框颜色
redius_img.setBorderWidthDP(5);//设置边框的宽度
redius_img.setCornerRadiiDP(5, 100, 5, 100);//设置左上右下的圆角弧度
Glide.with(this)
.load("http://tc.sinaimg.cn/maxwidth.2048/tc.service.weibo.com/p/mmbiz_qpic_cn/0dbdb8ca21725696a14d484e02f98a5a.jpg")
.error(R.drawable.image)
.placeholder(R.drawable.image)
.dontAnimate()
.centerCrop()
.into(redius_img);
}
}
效果图如下
希望能帮助到大家