Android 圆角图片控件
来源:互联网 发布:杭州橙速网络怎么样 编辑:程序博客网 时间:2024/06/06 09:47
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); }}效果图如下
希望能帮助到大家
0 0
- Android 圆角图片控件
- Android图片圆角控件
- 【Android】控件引用图片
- Android 图片控件ImageView
- Android自定义控件之自定义圆形图片和圆角图片
- 圆角图片展示控件
- Android基本界面控件四-图片控件
- Android 控件之ImageViewSwitcher图片切换控件
- Android 控件之GridView图片表格控件
- android图片倒影控件ReflectionImage
- Android 异步图片加载控件
- Android控件 >Gallery 切换图片
- Android实现图片滚动控件
- Android圆形图片控件RoundedImageView
- android 控件 图片视图(ImageView)
- Android实现图片滚动控件
- Android圆形图片--自定义控件
- android 圆形图片控件(方法)
- 欢迎使用CSDN-markdown编辑器
- php在范围中取值并使和为100
- 地图篇之百度地图各种自定义需求
- 使用命令行签名Android 应用程序
- Android Low memory killer
- Android 圆角图片控件
- Apache与Nginx优缺点比较
- spring @Qualifier 注解
- mysql中触发器的使用
- java jvm 参数 -Xms -Xmx -Xmn -Xss 调优总结
- S5P4418调试串口做为普通串口使用
- 态度
- Apache与Nginx网络模型
- 用Xmanager连接红旗linux的远程桌面