自定义View以及View的属性的使用(重点,xml中定义属性的值),包括Bitmap存为jpg样式(可以模仿修改照片不喜欢的地方)
来源:互联网 发布:java生成日志文件 编辑:程序博客网 时间:2024/04/27 20:40
- 程序的实现
- 主程序
- 继承View的类
- 主布局文件
- 自定义属性文件
- 另外注意
- 效果图
程序的实现
主程序
package com.test.mypathview;import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import android.app.Activity;import android.graphics.Bitmap;import android.os.Bundle;import android.os.Environment;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;public class MainActivity extends Activity { private MyBitmip2 myView; private Button mButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); myView = (MyBitmip2) findViewById(R.id.bitmap); mButton = (Button) findViewById(R.id.button); mButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // 获取cache通常会占用一定的内存,所以通常不需要的时候有必要对其进行清理, //通过destroyDrawingCache或setDrawingCacheEnabled(false)实现。 //这里并未对其进行处理 //一定要调用setDrawingCacheEnabled(false)方法来清空缓存区 myView.setDrawingCacheEnabled(true); Bitmap bitmap = myView.getDrawingCache(true); //设置文件的路径,对文件进行存储 File file = new File(Environment.getExternalStorageDirectory(), System.currentTimeMillis() + ".jpg"); if (!file.exists()) { try { file.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } try { //100是控制图片的压缩比率 bitmap.compress(Bitmap.CompressFormat.JPEG, 100, new FileOutputStream(file)); } catch (FileNotFoundException e) { e.printStackTrace(); } } }); }}
继承View的类
package com.test.mypathview;import android.annotation.TargetApi;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.CornerPathEffect;import android.graphics.Matrix;import android.graphics.Paint;import android.graphics.Path;import android.graphics.PorterDuff;import android.graphics.PorterDuffXfermode;import android.graphics.Rect;import android.graphics.drawable.BitmapDrawable;import android.os.Build;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;@TargetApi(Build.VERSION_CODES.HONEYCOMB)public class MyBitmip2 extends View { private int height; private int width; private Bitmap mBitmap; private Bitmap mBitmapPicture; private Canvas mBitmapCanvas; private Paint mPaintCircle; private Paint mPaintRec; private Path mPathPicture; public MyBitmip2(Context context, AttributeSet attrs) { super(context, attrs); mPaintCircle = new Paint(); mPaintCircle.setColor(Color.RED); /** * 必须自定义属性 */ //改变背景图片,根据样式中background的传入值 final TypedArray ta=context.obtainStyledAttributes(attrs,R.styleable.myview); //得到BitmapDrawable的myview_background BitmapDrawable drawable=(BitmapDrawable) ta.getDrawable(R.styleable.myview_myview_background); if(drawable!=null){ mBitmapPicture=drawable.getBitmap(); }else{ //当为空时传入默认图片 mBitmapPicture=BitmapFactory.decodeResource(getResources(), R.drawable.a); } /** * 在红色图层上描绘的线的设置,重叠部分则变为透明 */ mPaintRec = new Paint(); mPaintRec.setColor(Color.YELLOW); //设置重叠则变为透明 PorterDuffXfermode mode = new PorterDuffXfermode(PorterDuff.Mode.XOR); mPaintRec.setXfermode(mode); // 设置画笔画出的是什么样式的线 mPaintRec.setStrokeJoin(Paint.Join.ROUND); // 设置画笔起始点的形状 mPaintRec.setStrokeCap(Paint.Cap.ROUND); // 设置画笔宽度 int paintWidth=ta.getDimensionPixelOffset(R.styleable.myview_myview_paint_width, 30); mPaintRec.setStrokeWidth(paintWidth); //设置画笔的样式 mPaintRec.setStyle(Paint.Style.FILL_AND_STROKE); //设置画线的形式,具体参照http://www.cnblogs.com/tianzhijiexian/p/4297783.html mPaintRec.setPathEffect(new CornerPathEffect(90)); //设置是否去除锯齿 mPaintRec.setAntiAlias(true);// //得到背景图片// mBitmapPicture = BitmapFactory.decodeResource(getResources(), R.drawable.a); //设置记录在上面画线的路径 mPathPicture = new Path(); } public MyBitmip2(Context context) { super(context); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec); width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec); setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec)); //首先设置怎个屏幕为画板,并定义了画板的颜色样式 mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); mBitmapCanvas = new Canvas(mBitmap); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //mBitmapPicture既是背景图,也是要截取的图,第一个Rect是截取图的大小,第二个则是把这个截取图放在多大的画布上 canvas.drawBitmap(mBitmapPicture, new Rect(0, 0, mBitmapPicture.getWidth(), mBitmapPicture.getHeight()), new Rect(0, 0, width, height), null); // 注意画的顺序,这是进行蒙版的画制 mBitmapCanvas.drawRect(0, 0, width, height, mPaintCircle); //则是进行上面点触的重叠图层进行绘制 mBitmapCanvas.drawPath(mPathPicture, mPaintRec); canvas.drawBitmap(mBitmap, 0, 0, null); } private float downx; private float downy; private float oldx; private float oldy; @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: downx = event.getX(); downy = event.getY(); //中间用path记录点触位置的变化 mPathPicture.moveTo(downx, downy); invalidate(); oldx = downx; oldy = downy; invalidate(); return true; case MotionEvent.ACTION_MOVE: downx = event.getX(); downy = event.getY(); invalidate(); mPathPicture.moveTo(oldx, oldy); //quadto是画贝塞尔曲线 mPathPicture.quadTo((downx + oldx) / 2, (downy + oldy) / 2, downx, downy); invalidate(); //保存此次的坐标,以便之后直线的绘制 oldx = downx; oldy = downy; //通过返回true 结束本次事件 return true; default: break; } return super.onTouchEvent(event); }}
主布局文件
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:view="http://schemas.android.com/apk/res/com.test.mypathview" android:layout_width="match_parent" android:layout_height="match_parent" > <!-- 在上面导入自己的样式,跟自己的包名,并定义名字,然后根据名字使用自己定义的属性--> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="button"/> <!--在布局文件中使用自己定义的属性--> <com.test.mypathview.MyBitmip2 android:id="@+id/bitmap" android:layout_width="match_parent" android:layout_height="match_parent" view:myview_background="@drawable/c" view:myview_paint_width="100dp"/> <TextView android:id="@+id/textview" android:layout_width="200dp" android:layout_height="200dp" android:layout_centerInParent="true" android:gravity="center" android:text="A" android:textSize="100sp" /></RelativeLayout>
自定义属性文件
<?xml version="1.0" encoding="utf-8"?><resources> <!-- 这个名为样式名就是根据R.styleable.myview寻找的名字 --> <declare-styleable name="myview"> <!-- 设置其中各个属性的名字,以及属性的限定--> <attr name="myview_background" format="reference" ></attr> <attr name="myview_paint_width" format="dimension|reference"></attr> </declare-styleable></resources>
参考
<?xml version="1.0" encoding="utf-8"?> <resources> <attr name="rightPadding" format="dimension" /> <declare-styleable name="SlidingMenu"> <attr name="rightPadding" /> </declare-styleable> </resources>
另外注意
在本例中使用这个东东来使图片适应整个屏幕,但是我们也可以使用matrix来放大图片,使用时必须使用Matrix.reset()恢复正常,然后就可以放大图片了。
canvas.drawBitmap(mBitmapPicture, new Rect(0, 0, mBitmapPicture.getWidth(), mBitmapPicture.getHeight()), new Rect(0, 0, width, height), null);
效果图
0 0
- 自定义View以及View的属性的使用(重点,xml中定义属性的值),包括Bitmap存为jpg样式(可以模仿修改照片不喜欢的地方)
- Android自定义View在xml中定义样式可以定义的类型
- 自定义View属性的使用
- 自定义view的属性
- 自定义View如何定义和使用自己的属性
- 自定义view中自定义属性的用法.
- Android自定义View中的自定义属性(attrs.xml,TypedArray的使用)
- 自定义view的自定义属性
- Android中View自定义XML属性详解以及R.attr与R.styleable的区别
- Android中View自定义XML属性详解以及R.attr与R.styleable的区别
- Android中View自定义XML属性详解以及R.attr与R.styleable的区别
- VIEW当中自定义属性的使用
- VIEW当中自定义属性的使用
- VIEW当中自定义属性的使用
- VIEW当中自定义属性的使用
- Android View的xml属性
- Android View的xml属性
- android view的xml属性
- Cocos2d-js cc.director介绍
- Codeforces Round #320 (Div. 2) [Bayan Thanks-Round] C. A Problem about Polyline
- Linux中的STDIN_FILENO和STDOUT_FILENO
- python多线程编程:生成者和消费者
- 从头开始敲代码之《从BaseApplication/Activity开始(四)》
- 自定义View以及View的属性的使用(重点,xml中定义属性的值),包括Bitmap存为jpg样式(可以模仿修改照片不喜欢的地方)
- java生成范围内的纯数字随机数
- 二叉树中的那些常见的面试题
- 2 Add Two Numbers
- 小结(jquery,ui,flexgrid,数据库资源)
- 第11章 序列化
- 经常用到的代码段
- Activity启动模式图文详解:standard, singleTop, singleTask 以及 singleInstance
- c++ 抽象概念,内存格局,浅拷贝,深拷贝,临时对象,无名对象