1. 程式人生 > >Canvas配合MotionEvent實現畫板功能

Canvas配合MotionEvent實現畫板功能

      最近在學習Android中關於控制元件滑動以及2D繪製圖形API,所以就簡單的結合了兩者做了一個簡易的畫板功能,很多畫板都是通過自定義View或者SurfaceView來實現,在後續我也會做,但是今天就簡單的用Bitmap建立Canvas然後通過ImageView的形式展示一下。下面先來看一下效果:

 

1,實現思路

我們的這裡的思路很簡單,主要分為以下幾個步驟:

第一步:建立一個裝載畫板的控制元件(ImageView);

第二步:建立一個和控制元件一樣大小的畫布(Bitmap)並裝載在畫板(Canvas)上

第三步:實現兩者座標完全一致

第四步:監聽控制元件(ImageView)的MotionEvent事件,獲取座標資訊在畫布(Bitmap)上作畫;

第五步:繪製完成放在控制元件上,感覺就像在控制元件上繪製一樣的效果

可見,這是一種模擬實現自定義View 的效果。

 

2,示例程式碼

MainActivity程式碼:

package com.hfut.simpledrawer;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.Spinner;


/**
 * @author why
 * @date 2018-8-28 20:24:16
 */
public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";
    ImageView displayWindow;
    Bitmap bitmap;
    Spinner colorSpinner;
    Spinner widthSpinner;
    float lastX = 0.0f;
    float lastY = 0.0f;

    int color;
    int width;
    Handler handler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initUI();
        bitmap = Bitmap.createBitmap(getScreenWidth(), 600, Bitmap.Config.ARGB_8888);
        final Canvas canvas = new Canvas(bitmap);
        final Paint paint = new Paint();

        handler=new Handler(){
            @Override
            public void handleMessage(Message msg) {
                canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
            }
        };

        colorSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                //Toast.makeText(MainActivity.this,""+position,Toast.LENGTH_SHORT).show();
                switch (position){
                    case 0:
                        color=Color.RED;
                        break;
                    case 1:
                        color=Color.RED;
                        break;
                    case 2:
                        color=Color.BLUE;
                        break;
                    case 3:
                        color=Color.YELLOW;
                        break;
                    case 4:
                        color=Color.BLACK;
                        break;
                    default:
                        break;
                }
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });
        widthSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                if(position!=0) {
                    width = position + 1;
                }
                else{
                    width=1;
                }
                }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });

        displayWindow.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                int x = (int) event.getX();
                int y = (int) event.getY();
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        paint.setColor(color);
                        paint.setStrokeWidth(width);
                        x = (int) event.getX();
                        y = (int) event.getY();
                        lastX = x;
                        lastY = y;
                        break;
                    case MotionEvent.ACTION_MOVE:
                        Log.d(TAG, "onTouch: " + System.currentTimeMillis());
                        canvas.drawLine(lastX, lastY, x, y, paint);
                        lastX = x;
                        lastY = y;
                        displayWindow.setImageBitmap(bitmap);
                        break;
                    case MotionEvent.ACTION_UP:
                        break;
                    default:
                        break;
                }
                return true;
            }
        });
    }

    private void initUI() {
        displayWindow = findViewById(R.id.display_window);
        colorSpinner = findViewById(R.id.paint_color);
        widthSpinner = findViewById(R.id.paint_width);
    }


    //清除畫布
    public void clearDrawer(View view){
        displayWindow.setImageBitmap(null);
        Message message=new Message();
        handler.sendMessage(message);
    }

    //獲取顯示屏寬度
    public int getScreenWidth(){
        WindowManager manager = getWindowManager();
        DisplayMetrics metrics = new DisplayMetrics();
        manager.getDefaultDisplay().getMetrics(metrics);
        return metrics.widthPixels;
    }
}



activity_main.xml程式碼:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.hfut.simpledrawer.MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:background="#DCDCDC"
        android:padding="10px">

        <ImageView
            android:id="@+id/display_window"
            android:layout_width="match_parent"
            android:layout_height="600px" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:orientation="horizontal"
        android:weightSum="3">

        <Spinner
            android:id="@+id/paint_color"
            android:layout_width="0dip"
            android:layout_height="30dp"
            android:layout_marginLeft="20dp"
            android:layout_weight="1"
            android:background="#FFC0CB"
            android:entries="@array/paintcolor" />

        <Spinner
            android:id="@+id/paint_width"
            android:layout_width="0dip"
            android:layout_height="30dp"
            android:layout_marginLeft="10dp"
            android:layout_weight="1"
            android:background="#B0E0E6"
            android:entries="@array/paintwidth" />

        <Button
            android:layout_width="0dip"
            android:layout_height="wrap_content"
            android:layout_marginLeft="50dp"
            android:layout_weight="0.5"
            android:onClick="clearDrawer"
            android:text="清除" />

    </LinearLayout>

</LinearLayout>

 

values資料夾下畫筆屬性引數檔案paintattr.xml程式碼:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="paintcolor">
        <item>顏色</item>>
        <item>紅色</item>
        <item>藍色</item>
        <item>黃色</item>
        <item>黑色</item>
    </string-array>

    <string-array name="paintwidth">
        <item>粗細</item>
        <item>1</item>
        <item>2</item>
        <item>3</item>
        <item>4</item>
        <item>5</item>
        <item>6</item>
        <item>7</item>
        <item>8</item>
        <item>9</item>
        <item>10</item>
    </string-array>
</resources>

 

這樣,一個簡易的畫板功能就實現了。