重写ImageView使用Xfermode遮罩实现圆角和圆形
2015-03-07 14:00
513 查看
重写ImageView,并且在画布上绘制出四个角,使用DST_OUT取图模式对图片取出;
网上各种案例都有给出上面的实现方法,那么就来说说怎么实现
首先绘制出4个角,然后叠加而成,叠加的时候使用DST_OUT取图模式把图片取出即可;
看一下布局:
先是zy.zh.view.View1控件绘出了4个角,然后合并即可;
关于zy.zh.view.View1的实现:
其中的4个函数方别绘制4个角。
Path函数在绘制的时候默认是实心的所有绘制了封闭图形后自动填充实心,何况还有path.close()方法的调用,使用的arcTo,这个接口的说明是:If the start of the path is different from the path's current last point, then an automatic lineTo()
is added to connect the current contour to the start of the arc.
那么就是说path最好是按顺序作画,否则缺口会自动接上;所以绘制的路径方向要一致,关于方向一致的问题,绘图过程中自己会明白。
下面看一下怎么使用DST_OUT取图模式把图取出来:
这里值得注意的是如果Paint在draw方法中进行实例化会***警告Avoid object allocations during draw/layout operations,就是提醒:避免在draw和layout中进行对象分配;
还有另外一种方法绘制圆角ImageView,那么就是使用安卓sdk给出的drawRoundRect绘制圆角矩形;
布局为:
View4:
同理我们也可以这个方法绘制圆形之后进行取图,就能取到圆形ImageView了。
这里增加了描边;
暂时总结上面两种使用遮罩的方法;
转载请注明:/article/2710220.html
网上各种案例都有给出上面的实现方法,那么就来说说怎么实现
首先绘制出4个角,然后叠加而成,叠加的时候使用DST_OUT取图模式把图片取出即可;
看一下布局:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <zy.zh.view.View1 android:layout_width="170dp" android:layout_height="100dp" android:layout_margin="10dp" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_android" android:contentDescription="@null" android:layout_marginLeft="10dp" /> <zy.zh.view.View2 android:id="@+id/view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_android" android:contentDescription="@null" android:layout_margin="10dp" /> </LinearLayout>
先是zy.zh.view.View1控件绘出了4个角,然后合并即可;
关于zy.zh.view.View1的实现:
package zy.zh.view; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.RectF; import android.util.AttributeSet; import android.view.View; public class View1 extends View { private int cornerSize = 30; private Paint paint; public View1(Context context, AttributeSet attrs) { super(context, attrs); paint = new Paint(); paint.setColor(Color.BLUE); paint.setAntiAlias(true);//消除锯齿 } @Override public void draw(Canvas canvas) { super.draw(canvas); drawLeftTop(canvas); drawRightTop(canvas); drawLeftBottom(canvas); drawRightBottom(canvas); } private void drawLeftTop(Canvas canvas) { Path path = new Path(); path.moveTo(0, cornerSize); path.lineTo(0, 0); path.lineTo(cornerSize, 0); path.arcTo(new RectF(0, 0, cornerSize * 2, cornerSize * 2), -90, -90); path.close(); canvas.drawPath(path, paint); } private void drawLeftBottom(Canvas canvas) { Path path = new Path(); path.moveTo(0, getHeight() - cornerSize); path.lineTo(0, getHeight()); path.lineTo(cornerSize, getHeight()); path.arcTo(new RectF(0, // x getHeight() - cornerSize * 2,// y cornerSize * 2,// x getHeight()// getWidth()// y ), 90, 90); path.close(); canvas.drawPath(path, paint); } private void drawRightBottom(Canvas canvas) { Path path = new Path(); path.moveTo(getWidth() - cornerSize, getHeight()); path.lineTo(getWidth(), getHeight()); path.lineTo(getWidth(), getHeight() - cornerSize); RectF oval = new RectF(getWidth() - cornerSize * 2, getHeight() - cornerSize * 2, getWidth(), getHeight()); path.arcTo(oval, 0, 90); path.close(); canvas.drawPath(path, paint); } private void drawRightTop(Canvas canvas) { Path path = new Path(); path.moveTo(getWidth(), cornerSize); path.lineTo(getWidth(), 0); path.lineTo(getWidth() - cornerSize, 0); path.arcTo(new RectF(getWidth() - cornerSize * 2, 0, getWidth(), 0 + cornerSize * 2), -90, 90); path.close(); canvas.drawPath(path, paint); } }
其中的4个函数方别绘制4个角。
Path函数在绘制的时候默认是实心的所有绘制了封闭图形后自动填充实心,何况还有path.close()方法的调用,使用的arcTo,这个接口的说明是:If the start of the path is different from the path's current last point, then an automatic lineTo()
is added to connect the current contour to the start of the arc.
那么就是说path最好是按顺序作画,否则缺口会自动接上;所以绘制的路径方向要一致,关于方向一致的问题,绘图过程中自己会明白。
下面看一下怎么使用DST_OUT取图模式把图取出来:
package zy.zh.view; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.RectF; import android.util.AttributeSet; import android.widget.ImageView; public class View2 extends ImageView { private int cornerSize = 30; private Paint paint; public View2(Context context, AttributeSet attrs) { super(context, attrs); paint = new Paint(); paint.setColor(Color.BLUE); paint.setAntiAlias(true); PorterDuff.Mode mode; mode = PorterDuff.Mode.SRC_OUT;// 正确截图 paint.setXfermode(new PorterDuffXfermode(mode));// 设置取图模式 } @Override public void draw(Canvas canvas) { Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Config.ARGB_8888); Canvas canvas2 = new Canvas(bitmap); super.draw(canvas2); drawLeftTop(canvas2);// 这样canvas2就带有了取图模式,那就是Src drawRightTop(canvas2); drawLeftBottom(canvas2); drawRightBottom(canvas2); canvas.drawBitmap(bitmap, 0, 0, null);// canvas作为Dst; bitmap.recycle(); } private void drawLeftTop(Canvas canvas) { Path path = new Path(); path.moveTo(0, cornerSize); path.lineTo(0, 0); path.lineTo(cornerSize, 0); path.arcTo(new RectF(0, 0, cornerSize * 2, cornerSize * 2), -90, -90); path.close(); canvas.drawPath(path, paint); } private void drawLeftBottom(Canvas canvas) { Path path = new Path(); path.moveTo(0, getHeight() - cornerSize); path.lineTo(0, getHeight()); path.lineTo(cornerSize, getHeight()); path.arcTo(new RectF(0, // x getHeight() - cornerSize * 2,// y cornerSize * 2,// x getHeight()// getWidth()// y ), 90, 90); path.close(); canvas.drawPath(path, paint); } private void drawRightBottom(Canvas canvas) { Path path = new Path(); path.moveTo(getWidth() - cornerSize, getHeight()); path.lineTo(getWidth(), getHeight()); path.lineTo(getWidth(), getHeight() - cornerSize); RectF oval = new RectF(getWidth() - cornerSize * 2, getHeight() - cornerSize * 2, getWidth(), getHeight()); path.arcTo(oval, 0, 90); path.close(); canvas.drawPath(path, paint); } private void drawRightTop(Canvas canvas) { Path path = new Path(); path.moveTo(getWidth(), cornerSize); path.lineTo(getWidth(), 0); path.lineTo(getWidth() - cornerSize, 0); path.arcTo(new RectF(getWidth() - cornerSize * 2, 0, getWidth(), 0 + cornerSize * 2), -90, 90); path.close(); canvas.drawPath(path, paint); } }
这里值得注意的是如果Paint在draw方法中进行实例化会***警告Avoid object allocations during draw/layout operations,就是提醒:避免在draw和layout中进行对象分配;
还有另外一种方法绘制圆角ImageView,那么就是使用安卓sdk给出的drawRoundRect绘制圆角矩形;
布局为:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <zy.zh.view.View3 android:layout_width="170dp" android:layout_height="100dp" android:layout_margin="10dp" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_android" android:contentDescription="@null" android:layout_marginLeft="10dp" /> <zy.zh.view.View4 android:id="@+id/view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_android" android:contentDescription="@null" android:layout_margin="10dp" /> </LinearLayout>其中的View3:
package zy.zh.view; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.RectF; import android.util.AttributeSet; import android.view.View; public class View3 extends View{ public View3(Context context, AttributeSet attrs) { super(context, attrs); } @Override public void draw(Canvas canvas) { super.draw(canvas); final Paint paint = new Paint(); final RectF rectF = new RectF(new Rect(0, 0, getWidth(), getHeight())); final float roundPx = 30; paint.setAntiAlias(true); canvas.drawARGB(0, 0, 0, 0); paint.setColor(Color.RED); canvas.drawRoundRect(rectF, roundPx, roundPx, paint); } }
View4:
package zy.zh.view; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.PorterDuff.Mode; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.RectF; import android.util.AttributeSet; import android.widget.ImageView; public class View4 extends ImageView { public View4(Context context, AttributeSet attrs) { super(context, attrs); } @Override public void draw(Canvas canvas) { Bitmap bitmap; bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Config.ARGB_8888); Canvas canvas2 = new Canvas(bitmap); super.draw(canvas2); bitmap = GetRoundedCornerBitmap(bitmap); canvas.drawBitmap(bitmap, 0, 0, null); } public static Bitmap GetRoundedCornerBitmap(Bitmap bitmap) { try { Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Config.ARGB_8888); Canvas canvas = new Canvas(output); final Paint paint = new Paint(); final RectF rectF = new RectF(new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight())); final float roundPx = 30; paint.setAntiAlias(true); canvas.drawARGB(0, 0, 0, 0); paint.setColor(Color.BLACK); canvas.drawRoundRect(rectF, roundPx, roundPx, paint); paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); final Rect src = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); canvas.drawBitmap(bitmap, src, rect, paint); return output; } catch (Exception e) { return bitmap; } } }
同理我们也可以这个方法绘制圆形之后进行取图,就能取到圆形ImageView了。
这里增加了描边;
package zy.zh.view; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.PorterDuff.Mode; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.util.AttributeSet; import android.widget.ImageView; public class View5 extends ImageView { public View5(Context context, AttributeSet attrs) { super(context, attrs); } @Override public void draw(Canvas canvas) { Bitmap bitmap; bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Config.ARGB_8888); Canvas canvas2 = new Canvas(bitmap); super.draw(canvas2); bitmap = GetRoundedCornerBitmap(bitmap); canvas.drawBitmap(bitmap, 0, 0, null); // bitmap.recycle(); addStroke(canvas);// 增加描边 } // 画一个正圆形 private Bitmap GetRoundedCornerBitmap(Bitmap bitmap) { Bitmap result = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Config.ARGB_8888); Canvas canvas = new Canvas(result); Paint paint = new Paint(); paint.setAntiAlias(true);// // 消除锯齿 canvas.drawARGB(0, 0, 0, 0); paint.setStrokeWidth(5);// 外宽高度 canvas.drawCircle(bitmap.getWidth() / 2, bitmap.getHeight() / 2, bitmap.getHeight() / 2, paint); paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); final Rect src = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); canvas.drawBitmap(bitmap, src, rect, paint); return result; } /**增加描边*/ private void addStroke(Canvas canvas) { Paint paint = new Paint(); paint.setAntiAlias(true);// // 消除锯齿 canvas.drawARGB(0, 0, 0, 0); paint.setStrokeWidth(5);// 外宽高度 paint.setColor(Color.RED); // 当然也可以设置为"实心"(Paint.Style.FILL) paint.setStyle(Paint.Style.STROKE); canvas.drawCircle(getWidth() / 2, getHeight() / 2, (float) (getHeight() / 2 - 2.5), paint); } }
暂时总结上面两种使用遮罩的方法;
转载请注明:/article/2710220.html
相关文章推荐
- Android使用Xfermode图形渲染方法实现自定义圆形、圆角和椭圆ImageView
- Android Xfermode 实战 实现圆形、圆角图片(重写ImageView)
- Android 自定义View修炼-实现自定义圆形、圆角和椭圆ImageView(使用Xfermode图形渲染方法)
- ImageView的圆角或圆形使用原生support v4中的RoundedBitmapDrawable实现
- Android BitmapShader 实战 实现圆形、圆角图片(重写ImageView)
- 自定义ImageView实现圆角图片和圆形图片
- Android 自己定义ImageView实现圆角/圆形 附加OnTouchListener具体凝视以及Button圆角
- Android 完美实现图片圆角和圆形(Xfermode,重写View)
- Android 自定义ImageView实现圆角/圆形 附加OnTouchListener详细注释以及Button圆角
- Android 自定义ImageView实现圆角/圆形 附加OnTouchListener详细注释以及Button圆角
- Android 圆角圆形ImageView(超简单实现)
- Android自定义ImageView实现图片圆形 ,椭圆和矩形圆角显示
- 使用 Canvas 的Xfermode 实现 ImageView 圆形图片的实际步骤
- Android使用BitmapShader图形渲染实现圆形、圆角和椭圆自定义图片View
- Android 自定义View修炼-Android实现圆形、圆角和椭圆自定义图片View(使用BitmapShader图形渲染方法)
- Android使用 CircleImageView 实现圆形头像的方法
- Android实现圆角矩形和圆形ImageView的方式
- Android实现自定义圆形/圆角ImageView
- Android使用CircleImageView实现圆形头像的方法