设置ImageView圆角及边框问题

来源:互联网 发布:网络棋牌游戏开发教程 编辑:程序博客网 时间:2024/06/13 07:46

RoundedDrawable.java

package com.llkj.carfocus.myview.makeramen;import android.content.res.ColorStateList;import android.graphics.Bitmap;import android.graphics.Bitmap.Config;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.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.util.Log;import android.widget.ImageView.ScaleType;@SuppressWarnings("UnusedDeclaration")public class RoundedDrawable extends Drawable {public static final String TAG = "RoundedDrawable";public static final int DEFAULT_BORDER_COLOR = Color.BLACK;private final RectF mBounds = new RectF();private final RectF mDrawableRect = new RectF();private final RectF mBitmapRect = new RectF();private final BitmapShader mBitmapShader;private final Paint mBitmapPaint;private final int mBitmapWidth;private final int mBitmapHeight;private final RectF mBorderRect = new RectF();private final Paint mBorderPaint;private final Matrix mShaderMatrix = new Matrix();private float mCornerRadius = 0;private boolean mOval = false;private float mBorderWidth = 0;private ColorStateList mBorderColor = ColorStateList.valueOf(DEFAULT_BORDER_COLOR);private ScaleType mScaleType = ScaleType.FIT_CENTER;public RoundedDrawable(Bitmap bitmap) {mBitmapWidth = bitmap.getWidth();mBitmapHeight = bitmap.getHeight();mBitmapRect.set(0, 0, mBitmapWidth, mBitmapHeight);mBitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP,Shader.TileMode.CLAMP);mBitmapShader.setLocalMatrix(mShaderMatrix);mBitmapPaint = new Paint();mBitmapPaint.setStyle(Paint.Style.FILL);mBitmapPaint.setAntiAlias(true);mBitmapPaint.setShader(mBitmapShader);mBorderPaint = new Paint();mBorderPaint.setStyle(Paint.Style.STROKE);mBorderPaint.setAntiAlias(true);mBorderPaint.setColor(mBorderColor.getColorForState(getState(),DEFAULT_BORDER_COLOR));mBorderPaint.setStrokeWidth(mBorderWidth);}public static RoundedDrawable fromBitmap(Bitmap bitmap) {if (bitmap != null) {return new RoundedDrawable(bitmap);} else {return null;}}public static Drawable fromDrawable(Drawable drawable) {if (drawable != null) {if (drawable instanceof RoundedDrawable) {// just return if it's already a RoundedDrawablereturn drawable;} else if (drawable instanceof LayerDrawable) {LayerDrawable ld = (LayerDrawable) drawable;int num = ld.getNumberOfLayers();// loop through layers to and change to RoundedDrawables if// possiblefor (int i = 0; i < num; i++) {Drawable d = ld.getDrawable(i);ld.setDrawableByLayerId(ld.getId(i), fromDrawable(d));}return ld;}// try to get a bitmap from the drawable andBitmap bm = drawableToBitmap(drawable);if (bm != null) {return new RoundedDrawable(bm);} else {Log.w(TAG, "Failed to create bitmap from drawable!");}}return drawable;}public static Bitmap drawableToBitmap(Drawable drawable) {if (drawable instanceof BitmapDrawable) {return ((BitmapDrawable) drawable).getBitmap();}Bitmap bitmap;int width = Math.max(drawable.getIntrinsicWidth(), 1);int height = Math.max(drawable.getIntrinsicHeight(), 1);try {bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);Canvas canvas = new Canvas(bitmap);drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());drawable.draw(canvas);} catch (Exception e) {e.printStackTrace();bitmap = null;}return bitmap;}@Overridepublic boolean isStateful() {return mBorderColor.isStateful();}@Overrideprotected 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 updateShaderMatrix() {float scale;float dx;float dy;switch (mScaleType) {case CENTER:mBorderRect.set(mBounds);mBorderRect.inset((mBorderWidth) / 2, (mBorderWidth) / 2);mShaderMatrix.set(null);mShaderMatrix.setTranslate((int) ((mBorderRect.width() - mBitmapWidth) * 0.5f + 0.5f),(int) ((mBorderRect.height() - mBitmapHeight) * 0.5f + 0.5f));break;case CENTER_CROP:mBorderRect.set(mBounds);mBorderRect.inset((mBorderWidth) / 2, (mBorderWidth) / 2);mShaderMatrix.set(null);dx = 0;dy = 0;if (mBitmapWidth * mBorderRect.height() > mBorderRect.width()* mBitmapHeight) {scale = mBorderRect.height() / (float) mBitmapHeight;dx = (mBorderRect.width() - mBitmapWidth * scale) * 0.5f;} else {scale = mBorderRect.width() / (float) mBitmapWidth;dy = (mBorderRect.height() - mBitmapHeight * scale) * 0.5f;}mShaderMatrix.setScale(scale, scale);mShaderMatrix.postTranslate((int) (dx + 0.5f) + mBorderWidth,(int) (dy + 0.5f) + mBorderWidth);break;case CENTER_INSIDE:mShaderMatrix.set(null);if (mBitmapWidth <= mBounds.width()&& mBitmapHeight <= mBounds.height()) {scale = 1.0f;} else {scale = Math.min(mBounds.width() / (float) mBitmapWidth,mBounds.height() / (float) mBitmapHeight);}dx = (int) ((mBounds.width() - mBitmapWidth * scale) * 0.5f + 0.5f);dy = (int) ((mBounds.height() - mBitmapHeight * scale) * 0.5f + 0.5f);mShaderMatrix.setScale(scale, scale);mShaderMatrix.postTranslate(dx, dy);mBorderRect.set(mBitmapRect);mShaderMatrix.mapRect(mBorderRect);mBorderRect.inset((mBorderWidth) / 2, (mBorderWidth) / 2);mShaderMatrix.setRectToRect(mBitmapRect, mBorderRect,Matrix.ScaleToFit.FILL);break;default:case FIT_CENTER:mBorderRect.set(mBitmapRect);mShaderMatrix.setRectToRect(mBitmapRect, mBounds,Matrix.ScaleToFit.CENTER);mShaderMatrix.mapRect(mBorderRect);mBorderRect.inset((mBorderWidth) / 2, (mBorderWidth) / 2);mShaderMatrix.setRectToRect(mBitmapRect, mBorderRect,Matrix.ScaleToFit.FILL);break;case FIT_END:mBorderRect.set(mBitmapRect);mShaderMatrix.setRectToRect(mBitmapRect, mBounds,Matrix.ScaleToFit.END);mShaderMatrix.mapRect(mBorderRect);mBorderRect.inset((mBorderWidth) / 2, (mBorderWidth) / 2);mShaderMatrix.setRectToRect(mBitmapRect, mBorderRect,Matrix.ScaleToFit.FILL);break;case FIT_START:mBorderRect.set(mBitmapRect);mShaderMatrix.setRectToRect(mBitmapRect, mBounds,Matrix.ScaleToFit.START);mShaderMatrix.mapRect(mBorderRect);mBorderRect.inset((mBorderWidth) / 2, (mBorderWidth) / 2);mShaderMatrix.setRectToRect(mBitmapRect, mBorderRect,Matrix.ScaleToFit.FILL);break;case FIT_XY:mBorderRect.set(mBounds);mBorderRect.inset((mBorderWidth) / 2, (mBorderWidth) / 2);mShaderMatrix.set(null);mShaderMatrix.setRectToRect(mBitmapRect, mBorderRect,Matrix.ScaleToFit.FILL);break;}mDrawableRect.set(mBorderRect);mBitmapShader.setLocalMatrix(mShaderMatrix);}@Overrideprotected void onBoundsChange(Rect bounds) {super.onBoundsChange(bounds);mBounds.set(bounds);updateShaderMatrix();}@Overridepublic void draw(Canvas canvas) {if (mOval) {if (mBorderWidth > 0) {canvas.drawOval(mDrawableRect, mBitmapPaint);canvas.drawOval(mBorderRect, mBorderPaint);} else {canvas.drawOval(mDrawableRect, mBitmapPaint);}} else {if (mBorderWidth > 0) {canvas.drawRoundRect(mDrawableRect, Math.max(mCornerRadius, 0),Math.max(mCornerRadius, 0), mBitmapPaint);canvas.drawRoundRect(mBorderRect, mCornerRadius, mCornerRadius,mBorderPaint);} else {canvas.drawRoundRect(mDrawableRect, mCornerRadius,mCornerRadius, mBitmapPaint);}}}@Overridepublic int getOpacity() {return PixelFormat.TRANSLUCENT;}@Overridepublic void setAlpha(int alpha) {mBitmapPaint.setAlpha(alpha);invalidateSelf();}@Overridepublic void setColorFilter(ColorFilter cf) {mBitmapPaint.setColorFilter(cf);invalidateSelf();}@Overridepublic void setDither(boolean dither) {mBitmapPaint.setDither(dither);invalidateSelf();}@Overridepublic void setFilterBitmap(boolean filter) {mBitmapPaint.setFilterBitmap(filter);invalidateSelf();}@Overridepublic int getIntrinsicWidth() {return mBitmapWidth;}@Overridepublic int getIntrinsicHeight() {return mBitmapHeight;}public float getCornerRadius() {return mCornerRadius;}public RoundedDrawable setCornerRadius(float radius) {mCornerRadius = radius;return this;}public float getBorderWidth() {return mBorderWidth;}public RoundedDrawable setBorderWidth(float width) {mBorderWidth = width;mBorderPaint.setStrokeWidth(mBorderWidth);return this;}public int getBorderColor() {return mBorderColor.getDefaultColor();}public RoundedDrawable setBorderColor(int color) {return setBorderColor(ColorStateList.valueOf(color));}public ColorStateList getBorderColors() {return mBorderColor;}public RoundedDrawable setBorderColor(ColorStateList colors) {mBorderColor = colors != null ? colors : ColorStateList.valueOf(0);mBorderPaint.setColor(mBorderColor.getColorForState(getState(),DEFAULT_BORDER_COLOR));return this;}public boolean isOval() {return mOval;}public RoundedDrawable setOval(boolean oval) {mOval = oval;return this;}public ScaleType getScaleType() {return mScaleType;}public RoundedDrawable setScaleType(ScaleType scaleType) {if (scaleType == null) {scaleType = ScaleType.FIT_CENTER;}if (mScaleType != scaleType) {mScaleType = scaleType;updateShaderMatrix();}return this;}public Bitmap toBitmap() {return drawableToBitmap(this);}}
RoundedImageView.java

package com.llkj.carfocus.myview.makeramen;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.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.roundtest.R;public class RoundedImageView extends ImageView {public static final String TAG = "RoundedImageView";public static final float DEFAULT_RADIUS = 0f;public static final float DEFAULT_BORDER_WIDTH = 0f;private static final ScaleType[] SCALE_TYPES = { ScaleType.MATRIX,ScaleType.FIT_XY, ScaleType.FIT_START, ScaleType.FIT_CENTER,ScaleType.FIT_END, ScaleType.CENTER, ScaleType.CENTER_CROP,ScaleType.CENTER_INSIDE };private float cornerRadius = DEFAULT_RADIUS;private float borderWidth = DEFAULT_BORDER_WIDTH;private ColorStateList borderColor = ColorStateList.valueOf(RoundedDrawable.DEFAULT_BORDER_COLOR);private boolean isOval = false;private boolean mutateBackground = false;private int mResource;private Drawable mDrawable;private Drawable mBackgroundDrawable;private ScaleType mScaleType;public RoundedImageView(Context context) {super(context);}public RoundedImageView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public RoundedImageView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.RoundedImageView, defStyle, 0);int index = a.getInt(R.styleable.RoundedImageView_android_scaleType, -1);if (index >= 0) {setScaleType(SCALE_TYPES[index]);} else {// default scaletype to FIT_CENTERsetScaleType(ScaleType.FIT_CENTER);}cornerRadius = a.getDimensionPixelSize(R.styleable.RoundedImageView_corner_radius, -1);borderWidth = a.getDimensionPixelSize(R.styleable.RoundedImageView_border_width, -1);// don't allow negative values for radius and borderif (cornerRadius < 0) {cornerRadius = DEFAULT_RADIUS;}if (borderWidth < 0) {borderWidth = DEFAULT_BORDER_WIDTH;}borderColor = a.getColorStateList(R.styleable.RoundedImageView_border_color);if (borderColor == null) {borderColor = ColorStateList.valueOf(RoundedDrawable.DEFAULT_BORDER_COLOR);}mutateBackground = a.getBoolean(R.styleable.RoundedImageView_mutate_background, false);isOval = a.getBoolean(R.styleable.RoundedImageView_oval, false);updateDrawableAttrs();updateBackgroundDrawableAttrs(true);a.recycle();}@Overrideprotected void drawableStateChanged() {super.drawableStateChanged();invalidate();}/** * Return the current scale type in use by this ImageView. *  * @attr ref android.R.styleable#ImageView_scaleType * @see android.widget.ImageView.ScaleType */@Overridepublic ScaleType getScaleType() {return mScaleType;}/** * Controls how the image should be resized or moved to match the size of * this ImageView. *  * @param scaleType *            The desired scaling mode. * @attr ref android.R.styleable#ImageView_scaleType */@Overridepublic void setScaleType(ScaleType scaleType) {assert scaleType != null;if (mScaleType != scaleType) {mScaleType = scaleType;switch (scaleType) {case CENTER:case CENTER_CROP:case CENTER_INSIDE:case FIT_CENTER:case FIT_START:case FIT_END:case FIT_XY:super.setScaleType(ScaleType.FIT_XY);break;default:super.setScaleType(scaleType);break;}updateDrawableAttrs();updateBackgroundDrawableAttrs(false);invalidate();}}@Overridepublic void setImageDrawable(Drawable drawable) {mResource = 0;mDrawable = RoundedDrawable.fromDrawable(drawable);updateDrawableAttrs();super.setImageDrawable(mDrawable);}@Overridepublic void setImageBitmap(Bitmap bm) {mResource = 0;mDrawable = RoundedDrawable.fromBitmap(bm);updateDrawableAttrs();super.setImageDrawable(mDrawable);}@Overridepublic void setImageResource(int resId) {if (mResource != resId) {mResource = resId;mDrawable = resolveResource();updateDrawableAttrs();super.setImageDrawable(mDrawable);}}@Overridepublic 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 (Exception e) {Log.w(TAG, "Unable to find resource: " + mResource, e);// Don't try again.mResource = 0;}}return RoundedDrawable.fromDrawable(d);}@Overridepublic void setBackground(Drawable background) {setBackgroundDrawable(background);}private void updateDrawableAttrs() {updateAttrs(mDrawable);}private void updateBackgroundDrawableAttrs(boolean convert) {if (mutateBackground) {if (convert) {mBackgroundDrawable = RoundedDrawable.fromDrawable(mBackgroundDrawable);}updateAttrs(mBackgroundDrawable);}}private void updateAttrs(Drawable drawable) {if (drawable == null) {return;}if (drawable instanceof RoundedDrawable) {((RoundedDrawable) drawable).setScaleType(mScaleType).setCornerRadius(cornerRadius).setBorderWidth(borderWidth).setBorderColor(borderColor).setOval(isOval);} else if (drawable instanceof LayerDrawable) {// loop through layers to and set drawable attrsLayerDrawable ld = ((LayerDrawable) drawable);for (int i = 0, layers = ld.getNumberOfLayers(); i < layers; i++) {updateAttrs(ld.getDrawable(i));}}}@Override@Deprecatedpublic void setBackgroundDrawable(Drawable background) {mBackgroundDrawable = background;updateBackgroundDrawableAttrs(true);super.setBackgroundDrawable(mBackgroundDrawable);}public float getCornerRadius() {return cornerRadius;}public void setCornerRadius(int resId) {setCornerRadius(getResources().getDimension(resId));}public void setCornerRadius(float radius) {if (cornerRadius == radius) {return;}cornerRadius = radius;updateDrawableAttrs();updateBackgroundDrawableAttrs(false);}public float getBorderWidth() {return borderWidth;}public void setBorderWidth(int resId) {setBorderWidth(getResources().getDimension(resId));}public void setBorderWidth(float width) {if (borderWidth == width) {return;}borderWidth = width;updateDrawableAttrs();updateBackgroundDrawableAttrs(false);invalidate();}public int getBorderColor() {return borderColor.getDefaultColor();}public void setBorderColor(int color) {setBorderColor(ColorStateList.valueOf(color));}public ColorStateList getBorderColors() {return borderColor;}public void setBorderColor(ColorStateList colors) {if (borderColor.equals(colors)) {return;}borderColor = (colors != null) ? colors : ColorStateList.valueOf(RoundedDrawable.DEFAULT_BORDER_COLOR);updateDrawableAttrs();updateBackgroundDrawableAttrs(false);if (borderWidth > 0) {invalidate();}}public boolean isOval() {return isOval;}public void setOval(boolean oval) {isOval = oval;updateDrawableAttrs();updateBackgroundDrawableAttrs(false);invalidate();}public boolean isMutateBackground() {return mutateBackground;}public void setMutateBackground(boolean mutate) {if (mutateBackground == mutate) {return;}mutateBackground = mutate;updateBackgroundDrawableAttrs(true);invalidate();}}

RoundedTransformationBuilder.java

package com.llkj.carfocus.myview.makeramen;import android.content.res.ColorStateList;import android.content.res.Resources;import android.graphics.Bitmap;import android.util.DisplayMetrics;import android.util.TypedValue;import android.widget.ImageView;public final class RoundedTransformationBuilder {// private final Resources mResources;private final DisplayMetrics mDisplayMetrics;private float mCornerRadius = 0;private boolean mOval = false;private float mBorderWidth = 0;private ColorStateList mBorderColor = ColorStateList.valueOf(RoundedDrawable.DEFAULT_BORDER_COLOR);private ImageView.ScaleType mScaleType = ImageView.ScaleType.FIT_CENTER;public RoundedTransformationBuilder() {mDisplayMetrics = Resources.getSystem().getDisplayMetrics();}public RoundedTransformationBuilder scaleType(ImageView.ScaleType scaleType) {mScaleType = scaleType;return this;}/** * set corner radius in px */public RoundedTransformationBuilder cornerRadius(float radiusPx) {mCornerRadius = radiusPx;return this;}/** * set corner radius in dip */public RoundedTransformationBuilder cornerRadiusDp(float radiusDp) {mCornerRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,radiusDp, mDisplayMetrics);return this;}/** * set border width in px */public RoundedTransformationBuilder borderWidth(float widthPx) {mBorderWidth = widthPx;return this;}/** * set border width in dip */public RoundedTransformationBuilder borderWidthDp(float widthDp) {mBorderWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,widthDp, mDisplayMetrics);return this;}/** * set border color */public RoundedTransformationBuilder borderColor(int color) {mBorderColor = ColorStateList.valueOf(color);return this;}public RoundedTransformationBuilder borderColor(ColorStateList colors) {mBorderColor = colors;return this;}public RoundedTransformationBuilder oval(boolean oval) {mOval = oval;return this;}public Transformation build() {return new Transformation() {@Overridepublic Bitmap transform(Bitmap source) {Bitmap transformed = RoundedDrawable.fromBitmap(source).setScaleType(mScaleType).setCornerRadius(mCornerRadius).setBorderWidth(mBorderWidth).setBorderColor(mBorderColor).setOval(mOval).toBitmap();if (!source.equals(transformed)) {source.recycle();}return transformed;}@Overridepublic String key() {return "r:" + mCornerRadius + "b:" + mBorderWidth + "c:"+ mBorderColor + "o:" + mOval;}};}}

Transformation.java

package com.llkj.carfocus.myview.makeramen;/* * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */import android.graphics.Bitmap;/** Image transformation. */public interface Transformation {/** * Transform the source bitmap into a new bitmap. If you create a new bitmap * instance, you must call {@link android.graphics.Bitmap#recycle()} on * {@code source}. You may return the original if no transformation is * required. */Bitmap transform(Bitmap source);/** * Returns a unique key for the transformation, used for caching purposes. * If the transformation has parameters (e.g. size, scale factor, etc) then * these should be part of the key. */String key();}

attrs.xml

<?xml version="1.0" encoding="utf-8"?><resources>  <declare-styleable name="RoundedImageView">    <attr name="corner_radius" format="dimension" />    <attr name="border_width" format="dimension" />    <attr name="border_color" format="color" />    <attr name="mutate_background" format="boolean" />    <attr name="oval" format="boolean" />    <attr name="android:scaleType" />  </declare-styleable></resources>


  <com.llkj.carfocus.myview.makeramen.RoundedImageView        android:layout_width="100dp"        android:layout_height="100dp"        android:src="@drawable/img_review_pic"        app:border_color="#000000"        app:border_width="2dp"        app:corner_radius="60dp" />



0 0