在上一篇博客,Android-图像原理/绘制原理,讲解到绘图原理中,画布 + 画笔🖌️ 需要最基本的两个要素,才能绘制出图像;
在上一篇博客,Android-系统绘图真相,讲解到系统内部是如何控制图片的变化,例如:图片缩放/图片旋转/图片平移/等等,以及通过绘图规则 操作图片 旋转 缩放 平移
而这篇博客,和以上两篇博客都有关系,也需要理解Android绘图原理 和 Android系统绘图真相;
知道了 画布 + 画笔🖌️ 这两个要素能够绘制图像后,还需要明白绘图规则:
绘图规则:
1.在指定的图片上操作,必须要指定好在哪张图片上操作;
2.必须要给一张空白的图片,然后操作图片;
3.操作图片完成✅后,需要获取结果,操作后的结果就是空白图片
先画一个线:MyBoardActivity.java
package liudeli.my_media1; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.os.Bundle; import android.os.Environment; import android.view.View; import android.widget.ImageView; import android.widget.Toast; import java.io.File; public class MyBoardActivity extends Activity { private ImageView imageView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_board); imageView = findViewById(R.id.image_view); /** * 加载Sdcard的图片给ImageView显示 */ File file = new File(Environment.getExternalStorageDirectory(), "mm.jpg"); if (file.exists() == false) { Toast.makeText(this, file.getName() + "文件不存在", Toast.LENGTH_SHORT).show(); return; } // 原始图片 final Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath()); imageView.setImageBitmap(bitmap); // --------------------------------- /** * 知道了 画布 + 画笔🖌️ 这两个要素能够绘制图像后,还需要明白绘图规则: * 绘图规则: * * 1.在指定的图片上操作,必须要指定好在哪张图片上操作; * * 2.必须要给一张空白的图片,然后操作图片; * * 3.操作图片完成✅后,需要获取结果,操作后的结果就是空白图片 */ /** * 2.必须要给一张空白的图片,然后操作图片; * 参数一:空白图片的宽度,就拿原始图片的宽度 * 参数二:空白图片的高度,就拿原始图片的高度 * 参数三:空白图片的配置信息,就拿原始图片的配置信息 */ final Bitmap newBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig()); // 拿一块新的画布,把空白图片和画布关联 final Canvas canvas = new Canvas(newBitmap); // 设置画布的背景 canvas.drawColor(Color.WHITE); // 拿一只新的画笔 final Paint paint = new Paint(); // 给画笔设置红色 paint.setColor(Color.RED); // 设置画笔的粗和细 paint.setStrokeWidth(5); /** * 1.在指定的图片上操作,必须要指定好在哪张图片上操作; * 参数一:原始的 之前的 bitmap * 参数二:注意:⚠ Matrix集结了非常复杂的高等数学运算,操作图片的 图片缩放/图片旋转/图片平移/等等 都是Matrix来计算运算的 * 参数三:画笔🖌️ */ canvas.drawBitmap(bitmap, new Matrix(), paint); /* * 画线 * 开始X轴0 结束X轴0 代表是最左上角方开始画 */ canvas.drawLine(0, 0, 30, 60, paint); /** * 3.操作图片完成✅后,需要获取结果,操作后的结果就是空白图片 */ imageView.setImageBitmap(newBitmap); } /** * 保存绘制后的图片 */ public void drawActio(View view) { } }

设置setOnTouchListener,模仿画板功能:MyBoardActivity.java
1 package liudeli.my_media1; 2 3 import android.app.Activity; 4 import android.graphics.Bitmap; 5 import android.graphics.BitmapFactory; 6 import android.graphics.Canvas; 7 import android.graphics.Color; 8 import android.graphics.Matrix; 9 import android.graphics.Paint; 10 import android.os.Bundle; 11 import android.os.Environment; 12 import android.util.Log; 13 import android.view.MotionEvent; 14 import android.view.View; 15 import android.widget.ImageView; 16 import android.widget.Toast; 17 18 import java.io.File; 19 import java.io.FileNotFoundException; 20 import java.io.FileOutputStream; 21 22 public class MyBoardActivity extends Activity { 23 24 private final String TAG = MyBoardActivity.class.getSimpleName(); 25 26 private ImageView imageView; 27 28 private Canvas canvas; 29 private Bitmap newBitmap; 30 31 @Override 32 protected void onCreate(Bundle savedInstanceState) { 33 super.onCreate(savedInstanceState); 34 35 setContentView(R.layout.activity_board); 36 37 imageView = findViewById(R.id.image_view); 38 39 /** 40 * 加载Sdcard的图片给ImageView显示 41 */ 42 File file = new File(Environment.getExternalStorageDirectory(), "mm.jpg"); 43 if (!file.exists() || !file.isFile() ) { 44 Toast.makeText(this, file.getName() + "文件不存在", Toast.LENGTH_SHORT).show(); 45 return; 46 } 47 // 原始图片 48 final Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath()); 49 imageView.setImageBitmap(bitmap); 50 51 // --------------------------------- 52 53 /** 54 * 知道了 画布 + 画笔🖌️ 这两个要素能够绘制图像后,还需要明白绘图规则: 55 * 绘图规则: 56 * 57 * 1.在指定的图片上操作,必须要指定好在哪张图片上操作; 58 * 59 * 2.必须要给一张空白的图片,然后操作图片; 60 * 61 * 3.操作图片完成✅后,需要获取结果,操作后的结果就是空白图片 62 */ 63 64 /** 65 * 2.必须要给一张空白的图片,然后操作图片; 66 * 参数一:空白图片的宽度,就拿原始图片的宽度 67 * 参数二:空白图片的高度,就拿原始图片的高度 68 * 参数三:空白图片的配置信息,就拿原始图片的配置信息 69 */ 70 newBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig()); 71 72 // 拿一块新的画布,把空白图片和画布关联 73 canvas = new Canvas(newBitmap); 74 // 设置画布的背景 75 canvas.drawColor(Color.WHITE); 76 77 // 拿一只新的画笔 78 final Paint paint = new Paint(); 79 80 // 给画笔设置红色 81 paint.setColor(Color.WHITE); 82 83 // 设置画笔的粗和细 84 paint.setStrokeWidth(10); 85 86 /** 87 * 1.在指定的图片上操作,必须要指定好在哪张图片上操作; 88 * 参数一:原始的 之前的 bitmap 89 * 参数二:注意:⚠ Matrix集结了非常复杂的高等数学运算,操作图片的 图片缩放/图片旋转/图片平移/等等 都是Matrix来计算运算的 90 * 参数三:画笔🖌️ 91 */ 92 canvas.drawBitmap(bitmap, new Matrix(), paint); 93 94 /* 95 * 画线 96 * 开始X轴0 结束X轴0 代表是最左上角方开始画 97 */ 98 // 这里注释掉,//canvas.drawLine(0, 0, 60, 90, paint); 99 100 /** 101 * 3.操作图片完成✅后,需要获取结果,操作后的结果就是空白图片 102 */ 103 imageView.setImageBitmap(newBitmap); 104 105 106 /** 107 * ImageView触摸事件监听器,监听到变化就往图片上去涂鸦 108 */ 109 imageView.setOnTouchListener(new View.OnTouchListener() { 110 111 private float startX; 112 private float startY; 113 114 @Override 115 public boolean onTouch(View v, MotionEvent event) { 116 MyBoardActivity.super.onTouchEvent(event); 117 switch (event.getAction()) { 118 case MotionEvent.ACTION_DOWN: // 当手指按下屏幕 119 // Log.d(TAG, "按下"); 120 startX = event.getX(); 121 startY = event.getY(); 122 break; 123 case MotionEvent.ACTION_MOVE: // 手指在触摸着屏幕 124 // Log.d(TAG, "移动"); 125 float stopX = event.getX(); 126 float stopY = event.getY(); 127 128 /** 129 * 画布 提供了可以划线的方法 130 * 参数一:开始X轴,意思就是:从这里开画 131 * 参数二:开始Y轴,意思就是:从这里开画 132 * 参数三:结束X轴,意思就是:画到这里停止 133 * 参数四:结束Y轴,意思就是:画到这里停止 134 */ 135 Log.d(TAG, "startX:" + startX + " startY:" + startY + " stopX:" + stopX + " stopY:" + stopY); 136 canvas.drawLine(startX, startY, stopX, stopY, paint); 137 138 /** 139 * 3.操作图片完成✅后,需要获取结果,操作后的结果就是空白图片 140 */ 141 imageView.setImageBitmap(newBitmap); 142 143 // 把开始位置更新下 144 startX = stopX; 145 startY = stopY; 146 break; 147 case MotionEvent.ACTION_UP: // 手指离开了屏幕 148 Log.d(TAG, "弹起"); 149 break; 150 default: 151 break; 152 } 153 154 return true; // 代表我这了处理啦 155 } 156 }); 157 158 } 159 160 /** 161 * 保存绘制后的图片 162 */ 163 public void drawActio(View view) { 164 File file = new File(Environment.getExternalStorageDirectory(), "newSaveImage.jpg"); 165 try { 166 FileOutputStream fos = new FileOutputStream(file); 167 /** 168 * Bitmap 提供了 保存图片 的方法 169 * 参数一:保存的图片格式 170 * 参数二:百分比压缩 171 * 参数三:保存需要用到的字节输出流(字节输出流要去绑定file文件路径) 172 * 操作写入Sdcard需要权限 173 */ 174 newBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos); 175 } catch (FileNotFoundException e) { 176 e.printStackTrace(); 177 Toast.makeText(this, "保存失败!!!", Toast.LENGTH_SHORT).show(); 178 } 179 } 180 }
activity_board.xml布局文件
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="保存绘制后的图片" android:onClick="drawActio" /> <!-- 注意:千万千万千万千万千万千万千万千万千万千万不要这样写,一定要包裹内容才可以 我就是因为这样写,搞得我调试了一下午来找错误,结果是这里的问题,操你麻痹 android:layout_width="match_parent" android:layout_height="300" --> <ImageView android:id="@+id/image_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" /> </RelativeLayout>
在AndroidManifest.xml加入外部写入的权限:
<!-- Sdcard外部存储的权限 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
结果:

保存的图片文件:

浙公网安备 33010602011771号