来自:http://blog.csdn.net/ywl5320/article/details/38450021
我们在Android应用中经常要绘制圆角的图片来展示一些背景图,但是每次都制作圆角的图片很麻烦,而且重复使用率不高。所以我们最好的就是在应用中根据已有的图片,动态的绘制所需要的圆角图片用于显示。话不多说,让我们先看看效果图:
这是例子中使用到的图片:
怎么样,效果很好吧。
实现绘制圆角图片的原理很简单,就是在程序中动态生成一张Bitmap,然后再用Paint在这张Bitmap中绘制所需的图形(如圆形),再根据paint的setXfermode(new PorterDuffXfermode(android.graphics.PorterDuff.Mode.SRC_IN))属性设置在Bitmap中画的圆形和所要显示的图片的交集,并取图片部分,那样就生成了圆形的图片。“
其中Mode取值有如下一些值:
- 1.PorterDuff.Mode.CLEAR
- 所绘制不会提交到画布上。
- 2.PorterDuff.Mode.SRC
- 显示上层绘制图片
- 3.PorterDuff.Mode.DST
- 显示下层绘制图片
- 4.PorterDuff.Mode.SRC_OVER
- 正常绘制显示,上下层绘制叠盖。
- 5.PorterDuff.Mode.DST_OVER
- 上下层都显示。下层居上显示。
- 6.PorterDuff.Mode.SRC_IN
- 取两层绘制交集。显示上层。
- 7.PorterDuff.Mode.DST_IN
- 取两层绘制交集。显示下层。
- 8.PorterDuff.Mode.SRC_OUT
- 取上层绘制非交集部分。
- 9.PorterDuff.Mode.DST_OUT
- 取下层绘制非交集部分。
- 10.PorterDuff.Mode.SRC_ATOP
- 取下层非交集部分与上层交集部分
- 11.PorterDuff.Mode.DST_ATOP
- 取上层非交集部分与下层交集部分
- 12.PorterDuff.Mode.XOR
- 取两层绘制非交集。两层绘制非交集。
- 13.PorterDuff.Mode.DARKEN
- 上下层都显示。变暗
- 14.PorterDuff.Mode.LIGHTEN
- 上下层都显示。变量
- 15.PorterDuff.Mode.MULTIPLY
- 取两层绘制交集
- 16.PorterDuff.Mode.SCREEN
- 上下层都显示。
原理就是这样,接下来我们看看示例代码怎么应用:
第一:先看布局文件activity_main.xml
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent" >
- <ImageView
- android:id="@+id/source"
- android:layout_width="100dip"
- android:layout_height="100dip"
- android:layout_centerHorizontal="true"
- android:layout_marginBottom="20dip"
- android:layout_marginTop="20dip"
- android:src="@drawable/demo"/>
- <ImageView
- android:id="@+id/circle"
- android:layout_width="100dip"
- android:layout_height="100dip"
- android:layout_centerHorizontal="true"
- android:layout_below="@id/source"
- android:layout_marginBottom="20dip"/>
- <ImageView
- android:id="@+id/rect"
- android:layout_width="100dip"
- android:layout_height="100dip"
- android:layout_below="@id/circle"
- android:layout_centerHorizontal="true"
- android:layout_marginBottom="20dip"/>
- <ImageView
- android:id="@+id/squre"
- android:layout_width="100dip"
- android:layout_height="100dip"
- android:layout_below="@id/rect"
- android:layout_centerHorizontal="true"/>
- </RelativeLayout>
这里定义了四个Imageview,第一个为原图,第二个为圆形图片,第三个为圆角矩形,第四个为圆角正方形。
第二:为了节省空间,我就把生成图片的代码写在了MainActivity中,如下,注释都很清楚:
- package com.demo.imagetype;
- import android.app.Activity;
- import android.graphics.Bitmap;
- import android.graphics.Bitmap.Config;
- import android.graphics.Canvas;
- import android.graphics.Paint;
- import android.graphics.PorterDuffXfermode;
- import android.graphics.RectF;
- import android.graphics.drawable.BitmapDrawable;
- import android.graphics.drawable.Drawable;
- import android.os.Bundle;
- import android.widget.ImageView;
- public class MainActivity extends Activity {
- private ImageView circle;
- private ImageView rect;
- private ImageView squre;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- circle = (ImageView)findViewById(R.id.circle);
- rect = (ImageView)findViewById(R.id.rect);
- squre = (ImageView)findViewById(R.id.squre);
- /** 获取图片资源并转换为 Bitmap类型 */
- Drawable drawable = getResources().getDrawable(R.drawable.demo);
- BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
- Bitmap bitmap = bitmapDrawable.getBitmap();
- circle.setImageBitmap(getCircleBitmap(bitmap));
- rect.setImageBitmap(drawRect(bitmap, 80));
- squre.setImageBitmap(drawSqureRect(bitmap, 80));
- }
- /**
- * 绘制圆形
- * @param source
- * @return
- */
- public static Bitmap getCircleBitmap(Bitmap source)
- {
- // 以最小的边为圆的半径
- int min = 0;
- if(source.getWidth() < source.getHeight())
- {
- min = source.getWidth();
- }
- else
- {
- min = source.getHeight();
- }
- // 获取图片的中心点,使之与圆形的中心点重合,才不会让图片出现偏移
- int x = 0;
- int y = 0;
- if(source.getWidth() > min)
- {
- x = -(source.getWidth() - min);
- }
- else
- {
- x = min - source.getWidth();
- }
- if(source.getHeight() > min)
- {
- y = -(source.getHeight() - min);
- }
- else
- {
- y = min - source.getHeight();
- }
- // 创建画笔
- final Paint paint = new Paint();
- paint.setAntiAlias(true);
- // 以新建的bitmap创建画布
- Bitmap bitmap = Bitmap.createBitmap(min, min, Config.ARGB_8888);
- Canvas canvas = new Canvas(bitmap);
- // 以图片最小边为直径绘制圆形区域
- canvas.drawCircle(min / 2, min / 2, min / 2, paint);
- // 设置圆形区域与要显示的图片相交,并取相交区域的图片为结果图片
- // Mode.SRC_IN:取两层绘制交集。显示上层。
- paint.setXfermode(new PorterDuffXfermode(android.graphics.PorterDuff.Mode.SRC_IN));
- canvas.drawBitmap(source, x/2, y/2, paint);
- // 返回生成的bitmap,bitmap就是圆形图片
- return bitmap;
- }
- /**
- * 绘制圆角矩形
- * @param source
- * @param radius
- * @return
- */
- public Bitmap drawRect(Bitmap source, int radius)
- {
- // 得到要绘制的图片的长和宽,用来绘制圆角矩形的长和宽
- int width = source.getWidth();
- int height = source.getHeight();
- final Paint paint = new Paint();
- paint.setAntiAlias(true);
- Bitmap bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
- Canvas canvas = new Canvas(bitmap);
- RectF rect = new RectF(0, 0, width, height);
- canvas.drawRoundRect(rect, radius, radius, paint);
- paint.setXfermode(new PorterDuffXfermode(android.graphics.PorterDuff.Mode.SRC_IN));
- canvas.drawBitmap(source, 0, 0, paint);
- return bitmap;
- }
- /**
- * 绘制圆角正方形
- * @param source
- * @param radius
- * @return
- */
- public Bitmap drawSqureRect(Bitmap source, int radius)
- {
- int min = 0;//获取最小的边长
- if(source.getWidth() < source.getHeight())
- {
- min = source.getWidth();
- }
- else
- {
- min = source.getHeight();
- }
- int x = 0;//绘制中心的x坐标
- int y = 0;//绘制中心的y坐标
- if(source.getWidth() > min)
- {
- x = -(source.getWidth() - min);
- }
- else
- {
- x = min - source.getWidth();
- }
- if(source.getHeight() > min)
- {
- y = -(source.getHeight() - min);
- }
- else
- {
- y = min - source.getHeight();
- }
- final Paint paint = new Paint();
- paint.setAntiAlias(true);
- Bitmap bitmap = Bitmap.createBitmap(min, min, Config.ARGB_8888);
- Canvas canvas = new Canvas(bitmap);
- RectF rect = new RectF(0, 0, min, min);
- canvas.drawRoundRect(rect, radius, radius, paint);
- paint.setXfermode(new PorterDuffXfermode(android.graphics.PorterDuff.Mode.SRC_IN));
- canvas.drawBitmap(source, x/2, y/2, paint);//将要绘制的图片中心移动到画布中心
- return bitmap;
- }
- }
- /**
- * 1.PorterDuff.Mode.CLEAR
- 所绘制不会提交到画布上。
- 2.PorterDuff.Mode.SRC
- 显示上层绘制图片
- 3.PorterDuff.Mode.DST
- 显示下层绘制图片
- 4.PorterDuff.Mode.SRC_OVER
- 正常绘制显示,上下层绘制叠盖。
- 5.PorterDuff.Mode.DST_OVER
- 上下层都显示。下层居上显示。
- 6.PorterDuff.Mode.SRC_IN
- 取两层绘制交集。显示上层。
- 7.PorterDuff.Mode.DST_IN
- 取两层绘制交集。显示下层。
- 8.PorterDuff.Mode.SRC_OUT
- 取上层绘制非交集部分。
- 9.PorterDuff.Mode.DST_OUT
- 取下层绘制非交集部分。
- 10.PorterDuff.Mode.SRC_ATOP
- 取下层非交集部分与上层交集部分
- 11.PorterDuff.Mode.DST_ATOP
- 取上层非交集部分与下层交集部分
- 12.PorterDuff.Mode.XOR
- 取两层绘制非交集。两层绘制非交集。
- 13.PorterDuff.Mode.DARKEN
- 上下层都显示。变暗
- 14.PorterDuff.Mode.LIGHTEN
- 上下层都显示。变量
- 15.PorterDuff.Mode.MULTIPLY
- 取两层绘制交集
- 16.PorterDuff.Mode.SCREEN
- 上下层都显示。
- **/
其中在绘制圆角矩形的方法中第二个参数就是圆角的弧度,大家可以自己修改试试,看效果如何。好了,虽然代码不多也不复杂,但是确实很实用。