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>
这样,一个简易的画板功能就实现了。