Android 绘图进阶(二):Xfermode(画笔风格)绘制涂层
来源:互联网 发布:ubuntu输入法乱码 编辑:程序博客网 时间:2024/05/16 22:06
如果你对PorterDuff与Xfermode不够了解可以参看我之前的博客Android 绘图进阶(一),上篇博客介绍了Xfermode的SRC_IN的画笔风格的使用实例,这篇博客介绍一下它的一种涂层效果(XOR)。
方案一:圆形画板擦
一、思路
根据graphic图我们可以使用看出Xor效果实现的就是相交部分会露出底部图片。因此我们需要设置一个底部的背景(BitmapBackground),我是赵丽颖粉丝,就选择了她的图片作为背景,之后还需要绘制DST与SRC涂层,由于Xfermode的使用必须基于一张Bitmap,因此我们需要给要绘制的DST与SRC涂层创建一个Bitmap,并为它创建一个新的画布,将该Bitmap绘制到新建的画布上面,并将DST与SRC绘图绘制在上面。最后添加上手势监听就可以了。
二、代码示例
1、跟之前一样先创建用于绘制DST与SRC的Bitmap与它Canvas
//width、height是在onMeasure方法中获得的因此要在onMeasure创建bitmap//并设置Bitmap的大小充满屏幕mBitmap=Bitmap.createBitmap(width, height, Config.ARGB_8888); //创建Bitmap图的画布 BitmapCanvas=new Canvas(mBitmap);
2、DST与SRC
//系统默认先画的为DST BitmapCanvas.drawRect(0, 0, width, height, mpaintcircle); //后绘制的为SRC BitmapCanvas.drawPath(mpath, mpaintrect); //将bitmap图片绘制到画布上面 canvas.drawBitmap(mBitmap, 0, 0, null);
3、设置xfermode
//给画笔设置Xfermode PorterDuffXfermode mode=new PorterDuffXfermode(PorterDuff.Mode.XOR); mpaintrect.setXfermode(mode);
4、添加上手势监听
//手势监听 @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN:{ x=event.getX(); y=event.getY(); //为了不是单纯的绘制一个圆,使用Path路径 mpath.addCircle(x, y, 50, Direction.CW); invalidate(); return true; } case MotionEvent.ACTION_MOVE: x=event.getX(); y=event.getY(); mpath.addCircle(x, y, 50, Direction.CW); invalidate(); return true; default: break; } return super.onTouchEvent(event); }
5、完整代码
布局
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <com.example.myview.MyBitmapView2 android:id="@+id/slider" android:layout_width="match_parent" android:layout_height="match_parent" /> </RelativeLayout>
创建继承View的class
public class MyBitmapView2 extends View{ private int width; private int height; private Paint mpaintcircle; private Paint mpaintrect; //用于绘制DST与SRC的Bitmap private Bitmap mBitmap; //背景 private Bitmap mBitmapBackground; //DST与SRC的画布 private Canvas BitmapCanvas; private Bitmap back; //用于绘制圆路径 private Path mpath; public MyBitmapView2(Context context) { super(context); } public MyBitmapView2(Context context, AttributeSet attrs) { super(context, attrs); //设置dst画笔 mpaintcircle=new Paint(); mpaintcircle.setColor(Color.YELLOW); //设置src画笔的颜色 mpaintrect=new Paint(); mpaintrect.setColor(Color.GREEN); //给画笔设置Xfermode PorterDuffXfermode mode=new PorterDuffXfermode(PorterDuff.Mode.XOR); mpaintrect.setXfermode(mode); mpath=new Path(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //画布的背景图片,矩形区域由back确定 canvas.drawBitmap(mBitmapBackground, new Rect(0,0,back.getWidth(),back.getHeight()), new Rect(0,0,width,height), null);//系统默认先画的为DST BitmapCanvas.drawRect(0, 0, width, height, mpaintcircle); //后绘制的为SRC BitmapCanvas.drawPath(mpath, mpaintrect); //将bitmap图片绘制到画布上面 canvas.drawBitmap(mBitmap, 0, 0, null); } private float x; private float y; //手势监听 @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN:{ x=event.getX(); y=event.getY(); //为了不是单纯的绘制一个圆,使用Path路径 mpath.addCircle(x, y, 50, Direction.CW); invalidate(); return true; } case MotionEvent.ACTION_MOVE: x=event.getX(); y=event.getY(); mpath.addCircle(x, y, 50, Direction.CW); invalidate(); return true; default: break; } return super.onTouchEvent(event); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); // width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec); height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec); //告知父布局该View的大小 setMeasuredDimension(width, height); mBitmap=Bitmap.createBitmap(width, height, Config.ARGB_8888); //创建Bitmap图的画布 BitmapCanvas=new Canvas(mBitmap); //创建Bitmap背景图片mBitmapBackground=BitmapFactory.decodeResource(getResources(), R.drawable.zly);//创建它的原因是为了绘制mBitmapBackground时,确定矩形区域(全屏) back=Bitmap.createBitmap(width, height, Config.ARGB_8888); }}
这样我们的涂层效果就制作好了!
方案二:线型画板擦
可以看到我们上面的图片的画板擦的形状是圆形的,这里想要把它进一步修改为线型的板擦,我们只需要修改我们手势监听部分的mpath和画笔的线型圆角与中间连线的圆形连接以及非填充Style就可以了。
下面将修改的中点代码提取出来
画笔
//注:使用setStrokeCap与setStrokeJoin必须先设置style mpaintrect.setStyle(Style.STROKE); mpaintrect.setStrokeCap(Cap.ROUND); mpaintrect.setStrokeJoin(Join.ROUND);
手势监听
private float old_x; private float old_y; @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN:{ x=event.getX(); y=event.getY(); //mpath.addCircle(x, y, 50, Direction.CW); mpath.moveTo(x, y); invalidate(); old_x=x; old_y=y; return true; } case MotionEvent.ACTION_MOVE: x=event.getX(); y=event.getY(); //每次移动都从落下位置划线到移动位置 mpath.moveTo(old_x,old_y); //这里可以使用lineto也可以使用正余弦曲线 mpath.lineTo(x,y); //mpath.rQuadTo((x+old_x)/2,(y+old_y), x, y); //刷新UI invalidate(); old_x=x; old_y=y; return true; default: break; } return super.onTouchEvent(event); }
下面是完整代码
public class MyBitmapView2 extends View{ private int width; private int height; private Paint mpaintcircle; private Paint mpaintrect; private Bitmap mBitmap; private Bitmap mBitmapBackground; private Canvas BitmapCanvas; private Bitmap back; private Path mpath; public MyBitmapView2(Context context) { super(context); } public MyBitmapView2(Context context, AttributeSet attrs) { super(context, attrs); //设置圆形画笔 mpaintcircle=new Paint(); mpaintcircle.setColor(Color.YELLOW); //设置矩形画笔的颜色 mpaintrect=new Paint(); mpaintrect.setColor(Color.GREEN); //给画笔设置mode PorterDuffXfermode mode=new PorterDuffXfermode(PorterDuff.Mode.XOR); mpaintrect.setXfermode(mode); //注:使用setStrokeCap与setStrokeJoin必须先设置style mpaintrect.setStyle(Style.STROKE); mpaintrect.setStrokeCap(Cap.ROUND); mpaintrect.setStrokeJoin(Join.ROUND); mpaintrect.setStrokeWidth(30); mpath=new Path(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //画布的背景色 canvas.drawBitmap(mBitmapBackground,0,0, null); //在bitmap图的画布上绘制圆形与矩形 // BitmapCanvas.drawCircle(width/2, height/2, width/2, mpaintcircle);//dst BitmapCanvas.drawRect(0, 0, width, height, mpaintcircle);//src BitmapCanvas.drawPath(mpath, mpaintrect); //将bitmap图片绘制到画布上面 canvas.drawBitmap(mBitmap, 0, 0, null); } private float x; private float y; private float old_x; private float old_y; @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN:{ x=event.getX(); y=event.getY(); //mpath.addCircle(x, y, 50, Direction.CW); mpath.moveTo(x, y); invalidate(); old_x=x; old_y=y; return true; } case MotionEvent.ACTION_MOVE: x=event.getX(); y=event.getY(); mpath.moveTo(old_x,old_y); mpath.lineTo(x,y); //mpath.rQuadTo((x+old_x)/2,(y+old_y), x, y); invalidate(); old_x=x; old_y=y; return true; default: break; } return super.onTouchEvent(event); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec); height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec); setMeasuredDimension(width, height); mBitmap=Bitmap.createBitmap(width, height, Config.ARGB_8888); //创建Bitmap图的画布 BitmapCanvas=new Canvas(mBitmap); mBitmapBackground=BitmapFactory.decodeResource(getResources(), R.drawable.zly); back=Bitmap.createBitmap(width, height, Config.ARGB_8888);// Canvas canva=new Canvas(mBitmapBackground);// canva.drawBitmap(mBitmapBackground, new Rect(0,0,mBitmapBackground.getWidth(),mBitmapBackground.getHeight()), new Rect(0,0,width,height), null); }}
package com.example.myview;public class MainActivity_bitmap2 extends Activity implements OnClickListener{ private Button mbtn_bitmap2; private MyBitmapView2 bitmap2; protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.bitmap_view2); mbtn_bitmap2=(Button) findViewById(R.id.btn_bitmapview2); bitmap2=(MyBitmapView2) findViewById(R.id.bitmap2); mbtn_bitmap2.setOnClickListener(this); } @Override public void onClick(View v) { File file=new File(Environment.getExternalStorageDirectory(),System.currentTimeMillis()+".jpg"); bitmap2.invalidate(); bitmap2.setDrawingCacheEnabled(true); Bitmap bitmapnew=bitmap2.getDrawingCache(); if(!file.exists()){ try { file.createNewFile(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } try { Log.d("路径", file.getAbsolutePath()); bitmapnew.compress(CompressFormat.JPEG,100, new FileOutputStream(file)); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } }}
0 0
- Android 绘图进阶(二):Xfermode(画笔风格)绘制涂层
- Android 绘图进阶(一):PorterDuff与Xfermode(画笔风格)仿QQ圆形头像
- Android 绘图进阶(三):Xfermode绘制图片的保存
- Android 绘图进阶:仿360水纹进度球(可动正余弦曲线+xfermode)
- android绘图处理系列(一):bitmapShader和Xfermode
- 绘图(三,进阶之绘制表盘)
- HTML5 canvas 在线画笔绘图工具(二)
- 画笔使用(二)
- 绘图二 框图 画笔 画刷
- Android绘图(二)
- Android绘图机制与处理技巧(五)Android图像处理之画笔特效处理
- 浅谈画笔Xfermode
- 圆形ImageView系列(二)-----Xfermode+ImageView
- Android绘图基础之xfermode & layer
- Android Design -- 风格(二)
- Android:视图绘制(二) ------Paint进阶
- PorterDuff.Mode与Xfermode(android 6.0)
- Android 圆形图片 CircleImageView(Xfermode方式)
- 关于delegate 与 protocol 的理解 iOS
- 程序设计vs 写作
- 图像局部特征学习(笔记1之斑点检测)
- Codeforces Round #320 (Div. 2) [Bayan Thanks-Round] C. A Problem about Polyline 精度控制
- Python快速入手
- Android 绘图进阶(二):Xfermode(画笔风格)绘制涂层
- java获得当前时间和当前时间前30秒时间
- Android使用百度地图SDK获得当前设备位置所在的省、市
- Metis输入格式
- Git 简易使用教程
- 数据库之——timestamp中的update和insert
- Flex使用Scroller组件实现以鼠标为中心的缩放
- 升级Xcode7后,旧工程编译出现directory not found for option '-F...错误
- IOS知识小集 第二期 (2015.9.14)