Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android圖形圖像之自定義控件屬性(demo:刮刮樂與打碼以及圖片的緩存)

Android圖形圖像之自定義控件屬性(demo:刮刮樂與打碼以及圖片的緩存)

編輯:關於Android編程

概述:

此部分內容涉及到android的自定義View、自定義屬性和Android圖形圖像處理的綜合應用:Bitmap、Path、Matrix、Canvas。
圖片打碼以及如何緩存打碼後的圖片都是日常極有可能用到的,而刮圖也並不是用不到。
下面的demo寫的是一個的刮刮樂例程,裡面涉及到如何自定義控件屬性,以及如何存儲處理後的圖片,注釋很詳細,看注釋即可。
結果演示:
這裡寫圖片描述

文件保存後的結果:<喎?/kf/ware/vc/" target="_blank" class="keylink">vc3Ryb25nPjxiciAvPg0KPGltZyBhbHQ9"這裡寫圖片描述" src="/uploadfile/Collfiles/20150921/2015092108594641.gif" title="\" />

Demo

新建一個自定義View:

public class MyBitMapViewSec extends View {

    private int width;
    private int height;
    private float x;
    private float y;
    private float old_x;
    private float old_y;

    private Paint mPaintCircle;
    private Paint mPaintRect;
    private Bitmap mBitmap;
    private Bitmap mBitmapGround;

    private Matrix matrix;
    private Path mPath;
    private Canvas mCanvasBm;
    public MyBitMapViewSec(Context context) {
        super(context);
    }
    //
    public MyBitMapViewSec(Context context, AttributeSet attrs) {
        //attrs是這個View在xml布局中的所有屬性的集合
        super(context, attrs);
        //將attrs解析為TypedArray類的對象
        final TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.selfish);
        //得到xml中本自定義View的self_background屬性的內容,並強制轉換為BitmapDrawable類型
        BitmapDrawable dra = (BitmapDrawable) a.getDrawable(R.styleable.selfish_self_background);
        if(dra!=null){
            //如果dra不為空,就將dra賦值給mBitmapGround
            mBitmapGround = dra.getBitmap();
        }else {
            //mBitmapGround裡傳入的是一張圖片
            mBitmapGround = BitmapFactory.decodeResource(getResources(),R.mipmap.qingxin);
        }
        //得到xml中本自定義View的self_paintWidth屬性中的內容,如果得不到就給個默認值30
        float paintWidth = a.getDimension(R.styleable.selfish_self_paintWidth,30);

        mPaintCircle = new Paint();
        mPaintCircle.setColor(Color.YELLOW);

        mPaintRect = new Paint();
        //XOR:交疊和被交疊部分均不顯示;DST_OVER:自身交疊部分不顯示;SRC_OVER交疊部分只顯示自己
        PorterDuffXfermode mode = new PorterDuffXfermode(PorterDuff.Mode.XOR);
        mPaintRect.setXfermode(mode);
        mPaintRect.setStrokeWidth(paintWidth);
        mPaintRect.setStrokeJoin(Paint.Join.ROUND);//設置聯接部分樣式
        mPaintRect.setStrokeCap(Paint.Cap.ROUND);//設置中間部分樣式:圓形
        mPaintRect.setStyle(Paint.Style.FILL_AND_STROKE);

        mPath = new Path();
        matrix = new Matrix();

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
        setMeasuredDimension(width, height);

        //這一句不能放到構造方法中,是因為還沒有得到width和height的值
        mBitmap = Bitmap.createBitmap(width,height, Bitmap.Config.ARGB_8888);
        mCanvasBm = new Canvas(mBitmap);//自定義一個畫布,畫布材料是Bitmap對象
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        matrix.reset();
        //下面兩行的作用是放大圖片,並繪制出來
        matrix.postScale((float)width/mBitmapGround.getWidth(),(float)height/mBitmapGround.getHeight());
        canvas.drawBitmap(mBitmapGround,matrix,null);
        //畫一個蒙板
        mCanvasBm.drawRect(0,0,width,height,mPaintCircle);
        //將path畫出,因為mPaintRect的模式為PorterDuff.Mode.XOR,所以畫圖時會讓交疊部分都不顯示,從而顯示出底部圖片來
        mCanvasBm.drawPath(mPath,mPaintRect);
        //這一步的意義是:將mCanvasBm在mBitmap上繪制的內容畫出
        canvas.drawBitmap(mBitmap,0,0,null);

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                y = event.getY();
                x = event.getX();
                //CW是Path移動方向:順時針
                //mPath.addCircle(x,y,50,Path.Direction.CW);
                mPath.moveTo(x,y);
                //重新繪制,就是重新調用onDraw()方法
                invalidate();
                //更新old_x、old_y的值
                old_x = x;
                old_y = y;
                return true;
            case MotionEvent.ACTION_MOVE:
                y = event.getY();
                x = event.getX();
                //將mPath移動到上一個位置
                mPath.moveTo(old_x, old_y);
                //繪制貝塞爾曲線,((x + old_x) / 2, (y + old_y) / 2)作為控制點,(x, y)作為結束點
                mPath.quadTo((x + old_x) / 2, (y + old_y) / 2, x, y);
                invalidate();
                old_x = x;
                old_y = y;
                return true;
        }
        return super.onTouchEvent(event);
    }
}

如果用的是android studio,在res/value路徑下新建一個文件,命名隨意,我這裡叫selfish,內容如下:



    
        
        
    

上面的打碼中:attr代表我的自定View的屬性,我這裡添加了兩個屬性;declare-styleabl是給自定義控件添加自定義屬性用的,它是一個屬性集。

這個文件以及它的屬性會在布局文件中用到,用它之前必須要聲明:
xmlns:selfish=”http://schemas.android.com/apk/res-auto”
之後我就可以在我的自定義View——com.example.administrator.selfdefinedview.widget.MyBitMapViewSec中調用selfish屬性集中的兩個屬性:在代碼中可以看到他們:
*selfish:self_background=”@mipmap/aa”
selfish:self_paintWidth=”100dp”*




    

關於緩存View中的圖片的打碼,在主函數中寫出:

public class TimerActivity extends Activity {

    private Button mButtonResolve;
    private MyBitMapViewSec myBitMapViewSec;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_timer);

        mButtonResolve = (Button) findViewById(R.id.button_resolve);
        myBitMapViewSec = (MyBitMapViewSec) findViewById(R.id.my_slider);
        mButtonResolve.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //將緩存開啟
                myBitMapViewSec.setDrawingCacheEnabled(true);
                //getDrawingCache(true)得到當前myBitMapViewSec的緩存
                Bitmap bitmap = myBitMapViewSec.getDrawingCache(true);
                //得到存儲這個位圖文件bitmap的路徑
                File file = new File(Environment.getExternalStorageDirectory(),System.currentTimeMillis()+.jpg);
                if (!file.exists()){
                    try {
                        file.createNewFile();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                try {
                    //將bitmap轉為JPEG格式,保持原來大小寫入file文件
                    bitmap.compress(Bitmap.CompressFormat.JPEG,100,new FileOutputStream(file));
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

至於圖片打碼該怎麼寫呢?很簡單,只需修改onDraw()方法,把美女圖畫到自己聲明的畫布上,然後把黃色背景用onDraw()方法自帶的canvas上,最後位置互換即可,這樣,滑動頻幕的地方會顯示出底部的黃色,代碼如下:

protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //畫一個蒙板
        canvas.drawRect(0, 0, width, height, mPaintCircle);
        //將path畫出,因為mPaintRect的模式為PorterDuff.Mode.XOR,所以畫圖時會讓交疊部分都不顯示,從而顯示出底部圖片來
        matrix.reset();
        //下面兩行的作用是放大圖片,並繪制出來
        matrix.postScale((float) width / mBitmapGround.getWidth(), (float) height / mBitmapGround.getHeight());
        mCanvasBm.drawBitmap(mBitmapGround, matrix, null);

        mCanvasBm.drawPath(mPath, mPaintRect);
        //這一步的意義是:將mCanvasBm在mBitmap上繪制的內容畫出
        canvas.drawBitmap(mBitmap,0,0,null);

    }

結果演示:
這裡寫圖片描述

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved