标签:
苹果都放弃自己的棱角了。。。
看惯了方方正正的图片,乍一看到圆角图片觉得挺漂亮的。可当满世界都是圆角图片的时候,我又开始怀念那些棱角了~之前仓促的写过一个,今天拿过来又修改了一下,现在贴在这里,以方便以后ctrl+c、ctrl+v~~~~~
自定义一个图片控件,有圆形和圆角两种选择。控件的行为和ImageView一致!
扩展ImageView控件,重写其onDraw方法。一开始还想重写onMeasure方法,如果显示圆形图片强制宽高相等,没能行得通(代码中会说明)。圆角图片以Xfermode方式实现,关于这个知识点大家可以参考这篇文章《setXfermode属性》。
控件类RoundImageView:
/** * 圆角或者圆形图片控件扩展自ImageView<br/> * 说明:<br/> * 1.仅重写了绘制流程,即onDraw()方法<br/> * 2.如果使用圆形图片需要设置固定的尺寸 * 3.支持普通、圆形、圆角三种样式 * 4.可设置圆角半径 默认是10dp * 5.无法为背景添加圆角 * Created by 95 on 2016/1/11. */ public class RoundImageView extends ImageView { private static final String TAG = RoundImageView.class.getSimpleName(); private Paint mPaint; private WeakReference<Bitmap> mWeakBitmap; /** * 图片的类型,圆形or圆角 */ private int type; public static final int TYPE_NORMAL = 0; public static final int TYPE_CIRCLE = 1; public static final int TYPE_ROUND = 2; /** * 圆角大小的默认值 */ private static final int DEFAULT_RADIUS = 10; /** * 圆角的大小 */ private int mRadius; public RoundImageView(Context context) { this(context, null); } public RoundImageView(Context context, AttributeSet attrs) { super(context, attrs); mPaint = new Paint(); mPaint.setAntiAlias(true); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RoundImageView); mRadius = a.getDimensionPixelSize(R.styleable.RoundImageView_radius, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, DEFAULT_RADIUS, getResources().getDisplayMetrics()));// 默认为10dp type = a.getInt(R.styleable.RoundImageView_type, TYPE_NORMAL);// 默认为normal a.recycle(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); /** * 如果类型是圆形,则强制改变view的宽高一致,以小值为准 * 这种写法是有问题的 * 我们本来是想在正常测量的基础上取最短边 * 可下面的操作插入到了正常执行的流程当中 致使最终的结果出了问题 */ // if (type == TYPE_CIRCLE) // { // int min = Math.min(getMeasuredWidth(), getMeasuredHeight()); // setMeasuredDimension(min, min); // } } @Override protected void onDraw(Canvas canvas) { //普通模式 调用原生的绘制方法 if (type == TYPE_NORMAL) { super.onDraw(canvas); return; } //如果当前未设置图片 直接返回 if (getDrawable() == null) return; //在缓存中取出bitmap Bitmap bitmap = mWeakBitmap == null ? null : mWeakBitmap.get(); //如果bitmap已经被回收,就重新创建 if (bitmap == null || bitmap.isRecycled()) { bitmap = createDesiredBitmap(drawableToBitmap(getDrawable()), type, getMeasuredWidth(), getMeasuredHeight(), mRadius); mWeakBitmap = new WeakReference<Bitmap>(bitmap); } //以为我们所有的绘制使用了同一个Paint 所以每次使用之前都要考虑这个状态 mPaint.setXfermode(null); //把最终结果绘制到画布上 canvas.drawBitmap(bitmap, 0.0f, 0.0f, mPaint); } /** * 生成圆角图片 使用Xfermode方式 * * @param src 原图 * @param type round or circle * @param desiredWidth 控件的宽 * @param desiredHeight 控件的高 * @param radius 圆角半径 * @return */ private Bitmap createDesiredBitmap(Bitmap src, int type, int desiredWidth, int desiredHeight, int radius) { Bitmap target = Bitmap.createBitmap(desiredWidth, desiredHeight, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(target); mPaint.setXfermode(null); if (TYPE_CIRCLE == type) { canvas.drawCircle(desiredWidth * 1.0f / 2, desiredWidth * 1.0f / 2, desiredWidth * 1.0f / 2, mPaint); } else { RectF rectF = new RectF(0.0f, 0.0f, desiredWidth, desiredHeight); canvas.drawRoundRect(rectF, radius * 1.0f, radius * 1.0f, mPaint); } //缩放比例 保证图片的宽和高大于控件的宽和高 float ratio = Math.max(desiredWidth * 1.0f / src.getWidth(), desiredHeight * 1.0f / src.getHeight()); Bitmap tem = getScaledBitmap(src, ratio); //设置Xfermode mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); //保证控件展示的位置即为图片正中间的内容 canvas.drawBitmap(tem, (desiredWidth - tem.getWidth()) * 1.0f / 2, (desiredHeight - tem.getHeight()) * 1.0f / 2, mPaint); //释放内存 tem.recycle(); return target; } /** * 缩放图片 * * @param src 原图 * @param ratio 缩放比例 * @return */ private Bitmap getScaledBitmap(Bitmap src, float ratio) { Matrix matrix = new Matrix(); matrix.setScale(ratio, ratio, 0.0f, 0.0f); Bitmap target = Bitmap.createBitmap((int) (src.getWidth() * ratio), (int) (src.getHeight() * ratio), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(target); canvas.drawBitmap(src, matrix, mPaint); return target; } /** * drawable 转 bitmap * * @param drawable * @return */ private Bitmap drawableToBitmap(Drawable drawable) { if (drawable instanceof BitmapDrawable) { return ((BitmapDrawable) drawable).getBitmap(); } Bitmap target = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(target); drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); drawable.draw(canvas); return target; } }
自定义属性:
<declare-styleable name="RoundImageView"> <attr name="type" format="enum"> <enum name="normal" value="0"/> <enum name="circle" value="1"/> <enum name="round" value="2"/> </attr> <attr name="radius" format="dimension"/> </declare-styleable>
直接在布局文件当中使用:
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal" android:orientation="vertical"> <!--原图--> <com.hsji.testptr.widget.RoundImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/lena"/> <!--圆角效果,圆角半径是15dp--> <com.hsji.testptr.widget.RoundImageView android:layout_width="80dp" android:layout_height="80dp" android:layout_marginTop="10dp" android:src="@drawable/lena" app:radius="15dp" app:type="round"/> <!--非正方形圆角效果,圆角半径60dp--> <com.hsji.testptr.widget.RoundImageView android:layout_width="120dp" android:layout_height="80dp" android:layout_marginTop="10dp" android:src="@drawable/lena" app:radius="60dp" app:type="round"/> <!--圆形效果--> <com.hsji.testptr.widget.RoundImageView android:layout_width="120dp" android:layout_height="120dp" android:layout_marginTop="10dp" android:src="@drawable/lena" app:type="circle"/> </LinearLayout>
下面是效果图:
标签:
原文地址:http://www.cnblogs.com/hsji/p/5121698.html