将绘图从自定义视图保存到 SD 卡 android
saving drawing to sdcard from a custom view android
我正在开发一个可以在自定义视图上绘制的应用程序。我想用一个按钮保存绘图。我在其他线程上尝试了其他解决方案,但没有。请用下面的方法给我一个例子。实际上,这不是我的方法。来自 https://github.com/msiuts/FingerPaint
自定义视图
DrawView.java
public class DrawView extends View implements OnTouchListener {
private static final String TAG = "DrawView";
private final Random random = new Random();
private final int[] colors = new int[] {Color.BLACK, Color.BLACK, Color.BLACK, Color.BLACK, Color.BLACK,
Color.BLACK, Color.BLACK, Color.BLACK, Color.BLACK, Color.BLACK};
private final Paint paint = new Paint();
private Path path = new Path();
private Canvas canvas;
private Bitmap bitmap;
// deletes the screen by painting it black when the Menu Button is pressed
// this is a good method but how about save the drawing?
private OnKeyListener clearingOnKeyListener = new OnKeyListener() {
public boolean onKey(View view, int i, KeyEvent keyEvent) {
if (KeyEvent.KEYCODE_MENU == keyEvent.getKeyCode() && KeyEvent.ACTION_DOWN == keyEvent.getAction()) {
bitmap.eraseColor(Color.BLACK);
invalidate();
return true;
}
return false;
}
};
public DrawView(Context context, AttributeSet attrs) {
super(context, attrs);
setFocusable(true);
setFocusableInTouchMode(true);
this.setOnTouchListener(this);
this.setOnKeyListener(clearingOnKeyListener);
paint.setColor(randomColor());
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(3f);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
if (bitmap != null) {
if (bitmap.getHeight() == w && bitmap.getWidth() == h) {
Log.d(TAG, "rotating bitmap by 90 degree");
Matrix mtx = new Matrix();
mtx.postRotate(90, h/2, w/2);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, h, w, mtx, false);
canvas = new Canvas();
canvas.setBitmap(bitmap);
return;
} else {
bitmap.recycle();
}
}
canvas = new Canvas();
bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
canvas.setBitmap(bitmap);
}
@Override
public void onDraw(Canvas c) {
// draw to the screen
c.drawBitmap(bitmap, null, new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()), null);
}
public boolean onTouch(View view, MotionEvent event) {
// draw the new Points to our internal canvas / bitmap
if (event.getAction() == MotionEvent.ACTION_DOWN) {
paint.setColor(randomColor());
path = new Path();
path.moveTo(event.getX(), event.getY());
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
int historySize = event.getHistorySize();
for (int i=0; i < historySize; i++) {
path.lineTo(event.getHistoricalX(i), event.getHistoricalY(i));
}
path.lineTo(event.getX(), event.getY());
canvas.drawPath(path, paint);
} else {
return super.onTouchEvent(event);
}
invalidate();
return true;
}
public Bitmap getBitmap() {
return bitmap;
}
public void initBitmap(Bitmap bmap) {
bitmap = bmap;
}
/**
* Chooses a random color.
* @return the chosen color
*/
private int randomColor() {
return colors[random.nextInt(colors.length)];
}
}
Activity
绘图 Activity.java
public class DrawingActivity extends Activity {
private static final String TAG = "FingerPaint";
private DrawView drawView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_draw);
// restore view
drawView = (DrawView) findViewById(R.id.drawView);
Log.d(TAG, "DrawView from R is null? " + (drawView == null));
Bitmap lastDrawing = (Bitmap) getLastNonConfigurationInstance();
if (lastDrawing != null) {
Log.d(TAG, "lastDrawing is not null");
drawView.initBitmap(lastDrawing);
}
}
@Override
public Object onRetainNonConfigurationInstance() {
Bitmap bmap = null;
if (drawView != null) {
bmap = drawView.getBitmap();
Log.d(TAG, "onRetainNonConfigurationInstance returning a bitmap: " + (bmap != null));
}
return bmap;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
假设您想将文件保存到设备存储,这是我使用的解决方案...
添加清单权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
这是我的做法:
// Variables i needed
private String mFileName;
private Bitmap mBitmap;
// apply this listener to your button
private final View.OnClickListener ButtonListener = new View.OnCickListener(){
@Override
public void onClick(View v){
new SaveFile().execute();
}
}
private class SaveFile extends AsyncTask<Void, Void, File>{
@Override
protected File doInBackground(Void... params) {
View rootView = findViewById(R.id.drawView);
File newBackgroundBitmap = saveFileToStorage(rootView);
return newBackgroundBitmap;
}
@Override
protected void onPostExecute(File bitmapFile) {
super.onPostExecute(bitmapFile);
if(bitmapFile != null){
Toast.makeText(getBaseContext(), "Saved drawView to storage", Toast.LENGTH_SHORT).show();
}
}
}
那么这是完成所有工作的方法:
/**
* Saves the Bitmap File to Storage and returns the new File
* @param rootView - the View we want to capture
* @return returns the new FileName of the image.
*/
private File saveFileToStorage(View rootView){
rootView.setDrawingCacheEnabled(true);
mBitmap = rootView.getDrawingCache();
File fileDirectory = new File(Environment.getExternalStorageDirectory() + "FOLDER_NAME_YOU_WANT_TO_USE");
fileDirectory.mkdirs();
// Filename to store, Probably want to add some time stamp to make this unique
mFileName = "YOUR_FILE_NAME"+ ".png";
final File newBackgroundBitmap = new File(fileDirectory, mFileName);
try{
newBackgroundBitmap.createNewFile();
FileOutputStream outputStream = new FileOutputStream(newBackgroundBitmap);
mBitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
outputStream.close();
Log.d(TAG, "File saved..." + " " + mFileName);
}catch(Exception e){
e.printStackTrace();
}
return newBackgroundBitmap;
}
我正在开发一个可以在自定义视图上绘制的应用程序。我想用一个按钮保存绘图。我在其他线程上尝试了其他解决方案,但没有。请用下面的方法给我一个例子。实际上,这不是我的方法。来自 https://github.com/msiuts/FingerPaint
自定义视图
DrawView.java
public class DrawView extends View implements OnTouchListener {
private static final String TAG = "DrawView";
private final Random random = new Random();
private final int[] colors = new int[] {Color.BLACK, Color.BLACK, Color.BLACK, Color.BLACK, Color.BLACK,
Color.BLACK, Color.BLACK, Color.BLACK, Color.BLACK, Color.BLACK};
private final Paint paint = new Paint();
private Path path = new Path();
private Canvas canvas;
private Bitmap bitmap;
// deletes the screen by painting it black when the Menu Button is pressed
// this is a good method but how about save the drawing?
private OnKeyListener clearingOnKeyListener = new OnKeyListener() {
public boolean onKey(View view, int i, KeyEvent keyEvent) {
if (KeyEvent.KEYCODE_MENU == keyEvent.getKeyCode() && KeyEvent.ACTION_DOWN == keyEvent.getAction()) {
bitmap.eraseColor(Color.BLACK);
invalidate();
return true;
}
return false;
}
};
public DrawView(Context context, AttributeSet attrs) {
super(context, attrs);
setFocusable(true);
setFocusableInTouchMode(true);
this.setOnTouchListener(this);
this.setOnKeyListener(clearingOnKeyListener);
paint.setColor(randomColor());
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(3f);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
if (bitmap != null) {
if (bitmap.getHeight() == w && bitmap.getWidth() == h) {
Log.d(TAG, "rotating bitmap by 90 degree");
Matrix mtx = new Matrix();
mtx.postRotate(90, h/2, w/2);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, h, w, mtx, false);
canvas = new Canvas();
canvas.setBitmap(bitmap);
return;
} else {
bitmap.recycle();
}
}
canvas = new Canvas();
bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
canvas.setBitmap(bitmap);
}
@Override
public void onDraw(Canvas c) {
// draw to the screen
c.drawBitmap(bitmap, null, new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()), null);
}
public boolean onTouch(View view, MotionEvent event) {
// draw the new Points to our internal canvas / bitmap
if (event.getAction() == MotionEvent.ACTION_DOWN) {
paint.setColor(randomColor());
path = new Path();
path.moveTo(event.getX(), event.getY());
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
int historySize = event.getHistorySize();
for (int i=0; i < historySize; i++) {
path.lineTo(event.getHistoricalX(i), event.getHistoricalY(i));
}
path.lineTo(event.getX(), event.getY());
canvas.drawPath(path, paint);
} else {
return super.onTouchEvent(event);
}
invalidate();
return true;
}
public Bitmap getBitmap() {
return bitmap;
}
public void initBitmap(Bitmap bmap) {
bitmap = bmap;
}
/**
* Chooses a random color.
* @return the chosen color
*/
private int randomColor() {
return colors[random.nextInt(colors.length)];
}
}
Activity
绘图 Activity.java
public class DrawingActivity extends Activity {
private static final String TAG = "FingerPaint";
private DrawView drawView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_draw);
// restore view
drawView = (DrawView) findViewById(R.id.drawView);
Log.d(TAG, "DrawView from R is null? " + (drawView == null));
Bitmap lastDrawing = (Bitmap) getLastNonConfigurationInstance();
if (lastDrawing != null) {
Log.d(TAG, "lastDrawing is not null");
drawView.initBitmap(lastDrawing);
}
}
@Override
public Object onRetainNonConfigurationInstance() {
Bitmap bmap = null;
if (drawView != null) {
bmap = drawView.getBitmap();
Log.d(TAG, "onRetainNonConfigurationInstance returning a bitmap: " + (bmap != null));
}
return bmap;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
假设您想将文件保存到设备存储,这是我使用的解决方案...
添加清单权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
这是我的做法:
// Variables i needed
private String mFileName;
private Bitmap mBitmap;
// apply this listener to your button
private final View.OnClickListener ButtonListener = new View.OnCickListener(){
@Override
public void onClick(View v){
new SaveFile().execute();
}
}
private class SaveFile extends AsyncTask<Void, Void, File>{
@Override
protected File doInBackground(Void... params) {
View rootView = findViewById(R.id.drawView);
File newBackgroundBitmap = saveFileToStorage(rootView);
return newBackgroundBitmap;
}
@Override
protected void onPostExecute(File bitmapFile) {
super.onPostExecute(bitmapFile);
if(bitmapFile != null){
Toast.makeText(getBaseContext(), "Saved drawView to storage", Toast.LENGTH_SHORT).show();
}
}
}
那么这是完成所有工作的方法:
/**
* Saves the Bitmap File to Storage and returns the new File
* @param rootView - the View we want to capture
* @return returns the new FileName of the image.
*/
private File saveFileToStorage(View rootView){
rootView.setDrawingCacheEnabled(true);
mBitmap = rootView.getDrawingCache();
File fileDirectory = new File(Environment.getExternalStorageDirectory() + "FOLDER_NAME_YOU_WANT_TO_USE");
fileDirectory.mkdirs();
// Filename to store, Probably want to add some time stamp to make this unique
mFileName = "YOUR_FILE_NAME"+ ".png";
final File newBackgroundBitmap = new File(fileDirectory, mFileName);
try{
newBackgroundBitmap.createNewFile();
FileOutputStream outputStream = new FileOutputStream(newBackgroundBitmap);
mBitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
outputStream.close();
Log.d(TAG, "File saved..." + " " + mFileName);
}catch(Exception e){
e.printStackTrace();
}
return newBackgroundBitmap;
}