自定義View以及View的屬性的使用(重點,xml中定義屬性的值),包括Bitmap存爲jpg樣式(可以模仿修改照片不喜歡的地方)

程序的實現

主程序

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);

這裏寫圖片描述

效果圖

這裏寫圖片描述

發佈了83 篇原創文章 · 獲贊 0 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章