自定义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
原创粉丝点击