自定义View实现擦除蒙版显示图片功能/自定义View的存储/自定义View的属性
来源:互联网 发布:青柠软件密码 编辑:程序博客网 时间:2024/06/05 18:26
自定义View实现擦除蒙版显示图片功能
1.首先找到一张图片,利用BitmapFactory.decodeResource()方法得到它,作为画布的最底层将其绘制到画布的最底层
canvas.drawBitmap(mBitmapBackground,new Rect(0,0,mBitmapBackground.getWidth(),mBitmapBackground.getHeight()), new Rect(0,0,width,heigth),null);//将第一个Rect的图片作为来源,来填充第二个Rect的区域
2.创建一个和画布大小一模一样的Bitmap,但里面什么都没有,然后以这个Bitmap为新的画布创建一个新的画布
//创建一个位图 mBitmap=Bitmap.createBitmap(width,heigth, Bitmap.Config.ARGB_8888); mcanvasBit=new Canvas(mBitmap);//创建一个新的画布,是基于Bitmap即把Bitmap当做一个画布 //在Ondraw方法中 canvas.drawBitmap(mBitmap,0,0,null);
3.在Bitmap的画布上画上一层蒙版
mcanvasBit.drawRect(0, 0, width, heigth, mPaintCircle);//在Bitmap上画一个矩形。相当于一个蒙版//mPaintCircle只需要设置颜色即可
4.在Bitmap的画布上绘制一个路径,该路径代表用手点击屏幕,并在屏幕上移动的位置,该路径的画笔一定要设置成为XOR模型,同时还需要设置宽度(因为绘制的路径是线性的路径在第5部里)同时需要设置起始位置的形状(即点击屏幕不动时系统默认的形状,在这里设置为圆形)设置沿路径填充的形状(即手在屏幕上移动时,会不停的绘制该形状用来填充移动过的区域在这里设置为圆形,这样比方形好看的多)最后将画笔Style设置为FILL_AND_STROKE(填充和描边)
mPaintRect.setStrokeJoin(Paint.Join.ROUND);//起始位置的形状,设置为圆形 mPaintRect.setStrokeCap(Paint.Cap.ROUND);//绘制中间时使用的形状 mPaintRect.setStrokeWidth(60); mPaintRect.setStyle(Paint.Style.FILL_AND_STROKE);//将格式设置为填充并且空心 //PorterDuff.Mode为枚举类,一共有16个枚举值:每个枚举值代表不同的model PorterDuffXfermode mode=new PorterDuffXfermode(PorterDuff.Mode.XOR); mPaintRect.setXfermode(mode);
5.确定移动的位置和移动距离需要在onTouchEvent上面case:ACTION_DOWN和ACTION_MOVE,当ACTION_DOWN时需要记录当前这个点的位置,然后保存
当ACTION_MOVE时首先需要找到上个点的位置,然后得到最新点的位置,然后用mPath.lineTo来得到该路径,最后重新保存这个最新的点,这样就完成了不断更新触摸位置,同时能够记录该路径,最后调用 mcanvasBit.drawPath(mPath,mPaintRect);画出该路径
@Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN: X=event.getX();//得到当前点击的位置 Y=event.getY(); mPath.moveTo(X,Y);//将该位置设置为Path的起点 XOld=X;//将该位置保存 YOld=Y; invalidate(); return true;//必须要return true,否则不做处理 case MotionEvent.ACTION_MOVE: //得到移动到的位置 X=event.getX(); Y=event.getY(); mPath.moveTo(XOld,YOld);//首先移动到之前的那个点 mPath.lineTo(X,Y);//然后移动到新的位置 invalidate(); //重新保存这个点 XOld=X; YOld=Y; return true; } return super.onTouchEvent(event); }
自定义View的存储
1.首先在Activity中找到这个自定义的View,然后设置绘画缓存为true
2.创建一个Bitmap然后得到绘画的缓存
mBitPicture.setDrawingCacheEnabled(true);//设置自定义View可以当做缓存 Bitmap bit=mBitPicture.getDrawingCache(true);//创建一个Bitmap,得到自定义View的缓存
3.最后创建一个File将Bitmap写入该File文件里就能保存自定义View的图片了
//第一个参数设置文件压缩格式 //第二个参数设置文件压缩尺寸大小(0~100),PNG格式图片可以忽略这个设置 //第三个参数是输出的位置 bit.compress(Bitmap.CompressFormat.PNG,100,new FileOutputStream(file));//设置为Png格式
自定义View的属性
1.首先在res的values文件夹下创建一个xml文件,在文件里面创建declare-styleable,表示自定义的属性,然后创建属性,包括属性的name和format,其中format表示接受的数据类型,xml文件如下:
<declare-styleable name="customView"> <attr name="change_picture" format="reference"></attr> <attr name="change_paint" format="dimension|reference"></attr> </declare-styleable>
2.在布局xml文件下声明已经创建的属性集合,在Androidstudio中只需要在后面加上res-auto就可以自己去寻找了,但是在eclipse中需要加上包名
xmlns:customview="http://schemas.android.com/apk/res-auto"
3.声明之后就可以在自己创建的View上添加属性了
customview:change_picture="@mipmap/ali" customview:change_paint="50sp"
4.在View类中找到该属性
final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.customView); BitmapDrawable drawable= (BitmapDrawable) a.getDrawable(R.styleable.customView_change_picture); if (drawable!=null){ mBitmapBackground=drawable.getBitmap(); }else { mBitmapBackground= BitmapFactory.decodeResource(getResources(), R.mipmap.cluo);//为Bitmap设置来源 } int paintWidth=a.getDimensionPixelOffset(R.styleable.customView_change_paint,30);
所有代码
public class BitmapPicture extends View { private int width; private int heigth; private float X; private float Y; private float XOld; private float YOld; private Path mPath; private Bitmap mBitmap; private Bitmap mBitmapBackground; private Paint mPaintBackground; private Paint mPaintCircle; private Paint mPaintRect; private Canvas mcanvasBit; public BitmapPicture(Context context) { super(context); } public BitmapPicture(Context context, AttributeSet attrs) { super(context, attrs); final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.customView); BitmapDrawable drawable= (BitmapDrawable) a.getDrawable(R.styleable.customView_change_picture);//找到图片并强制造型成为BitmapDrawable if (drawable!=null){ mBitmapBackground=drawable.getBitmap(); }else { mBitmapBackground= BitmapFactory.decodeResource(getResources(), R.mipmap.cluo);//为Bitmap设置来源 } int paintWidth=a.getDimensionPixelOffset(R.styleable.customView_change_paint,30);//得到xml文档中chang_paint属性的值,第二个参数是默认值 mPath=new Path(); mPaintBackground=new Paint(); mPaintBackground.setColor(Color.GRAY); mPaintCircle=new Paint(); mPaintCircle.setColor(Color.CYAN); mPaintCircle.setAntiAlias(true); mPaintRect=new Paint(); mPaintRect.setColor(Color.GRAY); mPaintRect.setAntiAlias(true);//抗锯齿 mPaintRect.setStrokeJoin(Paint.Join.ROUND);//起始位置的形状,设置为圆形//设置画笔进入的形状,当画笔的Style设置为Stroke或者FillAndStroke时使用 mPaintRect.setStrokeCap(Paint.Cap.ROUND);//绘制中间时使用的形状//设置笔帽的形式,当画笔的Style设置为Stroke或者FillAndStroke时使用 mPaintRect.setStrokeWidth(paintWidth); mPaintRect.setStyle(Paint.Style.FILL_AND_STROKE);//将格式设置为填充并且空心 //PorterDuff.Mode为枚举类,一共有16个枚举值:每个枚举值代表不同的model PorterDuffXfermode mode=new PorterDuffXfermode(PorterDuff.Mode.XOR); mPaintRect.setXfermode(mode); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); width=getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec); heigth=getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec); setMeasuredDimension(width,heigth); //创建一个位图 mBitmap=Bitmap.createBitmap(width,heigth, Bitmap.Config.ARGB_8888); mcanvasBit=new Canvas(mBitmap);//创建一个新的画布,是基于Bitmap即把Bitmap当做一个画布 } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas);// canvas.drawColor(Color.GRAY);//设置一个背景色// canvas.drawBitmap(mBitmap,0,0,mPaintBackground);//将Bitmap画到画布上 canvas.drawBitmap(mBitmapBackground,new Rect(0,0,mBitmapBackground.getWidth(),mBitmapBackground.getHeight()), new Rect(0,0,width,heigth),null);//将第一个Rect的图片作为来源,来填充第二个Rect的区域 canvas.drawBitmap(mBitmap,0,0,null);// mcanvasBit.drawCircle(width/2,heigth/2,width/2,mPaintCircle);//Bitmap上画一个圆 mcanvasBit.drawRect(0, 0, width, heigth, mPaintCircle);//在Bitmap上画一个矩形。相当于一个蒙版 mcanvasBit.drawPath(mPath,mPaintRect);//画出路径,经路径上的设置为透明 } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN: X=event.getX();//得到当前点击的位置 Y=event.getY(); mPath.moveTo(X,Y);//将该位置设置为Path的起点 XOld=X;//将该位置保存 YOld=Y; invalidate(); return true;//必须要return true,否则不做处理 case MotionEvent.ACTION_MOVE: //得到移动到的位置 X=event.getX(); Y=event.getY(); mPath.moveTo(XOld,YOld);//首先移动到之前的那个点 mPath.lineTo(X,Y);//然后移动到新的位置 invalidate(); //重新保存这个点 XOld=X; YOld=Y; return true; } return super.onTouchEvent(event); }}
xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:customview="http://schemas.android.com/apk/res-auto" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"><com.my.mywidget.widget.BitmapPicture android:id="@+id/bitmap_picture" android:layout_width="match_parent" android:layout_height="0dip" android:layout_weight="1" customview:change_picture="@mipmap/ali" customview:change_paint="50sp" /> <Button android:id="@+id/button_save" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="保存"/></LinearLayout>
Acitvity
public class BitmapPictureActivity extends AppCompatActivity { private Button mBtnSave; private BitmapPicture mBitPicture; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.btimap_picture); mBitPicture= (BitmapPicture) findViewById(R.id.bitmap_picture); mBtnSave= (Button) findViewById(R.id.button_save); mBtnSave.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(BitmapPictureActivity.this, "成功保存图片", Toast.LENGTH_SHORT).show();// mBitPicture.setBackgroundResource(R.mipmap.aixi); //这两句话是将自定义View设置为可以保存 mBitPicture.setDrawingCacheEnabled(true);//设置自定义View可以当做缓存 Bitmap bit=mBitPicture.getDrawingCache(true);//创建一个Bitmap,得到自定义View的缓存 File file=new File(Environment.getExternalStorageDirectory(),System.currentTimeMillis()+".png");//文件保存路径 if (!file.exists()){ try { file.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } try { //第一个参数设置文件压缩格式 //第二个参数设置文件压缩尺寸大小(0~100),PNG格式图片可以忽略这个设置 //第三个参数是输出的位置 bit.compress(Bitmap.CompressFormat.PNG,100,new FileOutputStream(file));//设置为Png格式 } catch (FileNotFoundException e) { e.printStackTrace(); } } }); }}
customView
<?xml version="1.0" encoding="utf-8"?><resources> <declare-styleable name="customView"> <attr name="change_picture" format="reference"></attr> <attr name="change_paint" format="dimension|reference"></attr> </declare-styleable></resources>
- 自定义View实现擦除蒙版显示图片功能/自定义View的存储/自定义View的属性
- 实现自定义view的自定义属性
- 自定义view的自定义属性
- 自定义view的属性
- 自定义View的显示
- 自定义View的实现
- 实现自定义的View
- 自定义View的实现
- Android 自定义View——蒙版擦除效果实现
- Android 自定义View——蒙版擦除效果实现
- 自定义View(擦除蒙版得到背景,存储图片,更换背景)
- 自定义View 实现 TextView 的功能:
- android 自定义View的属性
- 自定义View属性的方法
- 自定义View属性的使用
- 自定义View的属性初步
- 自定义View控件的属性
- android自定义view的属性
- Linux 平台中十款播放器
- 2015-09-18 只有悲催的时候才会上来吧
- Nginx+Tomcat实现负载均衡小demo
- HDU 1035 Robot Motion
- Madplay移植到mini2440全过程详解
- 自定义View实现擦除蒙版显示图片功能/自定义View的存储/自定义View的属性
- Python批量重命名文件示例
- PHP之——CentOS下搭建 PHP 环境(最佳的LAMP环境)
- 一个实用的js window封装类
- iOS MKMapView简单介绍
- 昂贵的聘礼 510 (最短路 好题)
- FFMPEG视音频编解码零基础学习方法
- Python批量重命名文件示例(带演示功能)
- block语法