【安卓开发】Android实现画板

简介: 【安卓开发】Android实现画板

普通画板

添加权限

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
package Draw;
import androidx.appcompat.app.AppCompatActivity;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import com.example.myapp_b.R;
public class CanvasActivity extends AppCompatActivity {
    private ImageView iv;
    private Bitmap bitmap;
    private Canvas canvas;
    private Paint paint;
    private float startX=0f;
    private float startY=0f;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_canvas);
        iv=findViewById(R.id.iv);
        bitmap=Bitmap.createBitmap(1000,1000,Bitmap.Config.ARGB_8888);
        paint=new Paint();
        canvas=new Canvas(bitmap);
        iv.setImageBitmap(bitmap);
        iv.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                int action = event.getAction();
                switch (action){
                    case MotionEvent.ACTION_DOWN:
                        //按下时记录点击位置
                        startX = event.getX();
                        startY = event.getY();
                        break;
                    case MotionEvent.ACTION_MOVE:
                        //移动时获取当前位置,并绘制直线
                        float endX = event.getX();
                        float endY = event.getY();
                        canvas.drawLine(startX,startY,endX,endY,paint);
                        iv.setImageBitmap(bitmap);
                        //将直线终点设置为下一次的起点
                        startX = endX;
                        startY = endY;
                        break;
                    case MotionEvent.ACTION_UP:
                        break;
                }
                return true;
            }
        });
    }
    public void setColor(View view) {
        paint.setColor(Color.RED);
    }
    public void setWidth(View view) {
        paint.setStrokeWidth(10);
    }
}
<?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="Draw.CanvasActivity">
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="设置画笔颜色"
        android:onClick="setColor"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="设置画笔宽度"
        android:onClick="setWidth"/>
    <ImageView
        android:background="@drawable/bg_border"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/iv"/>
</LinearLayout>

可以选择颜色、宽度、橡皮擦,可以保存文件到本地

添加权限

 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

file_path.xml

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="my_images" path="DRAW" />
</paths>
package Draw;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.icu.text.SimpleDateFormat;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import com.example.myapp_b.R;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.Date;
public class PaintActivity extends AppCompatActivity {
    private ImageView iv;
    private Bitmap bitmap;
    private Canvas canvas;
    private Paint paint;
    private float startX=0f;
    private float startY=0f;
    private Button bt_back,bt_sure;
    private ImageView res;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_paint);
        iv=findViewById(R.id.iv);
        res=findViewById(R.id.res);
        bt_back=findViewById(R.id.bt_back);
        bt_sure=findViewById(R.id.paint_sure);
        bitmap=Bitmap.createBitmap(1000,1000,Bitmap.Config.ARGB_8888);
        paint=new Paint();
        canvas=new Canvas(bitmap);
        iv.setImageBitmap(bitmap);
        iv.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                int action = event.getAction();
                switch (action){
                    case MotionEvent.ACTION_DOWN:
                        //按下时记录点击位置
                        startX = event.getX();
                        startY = event.getY();
                        break;
                    case MotionEvent.ACTION_MOVE:
                        //移动时获取当前位置,并绘制直线
                        float endX = event.getX();
                        float endY = event.getY();
                        canvas.drawLine(startX,startY,endX,endY,paint);
                        iv.setImageBitmap(bitmap);
                        //将直线终点设置为下一次的起点
                        startX = endX;
                        startY = endY;
                        break;
                    case MotionEvent.ACTION_UP:
                        break;
                }
                return true;
            }
        });
    }
    int id;
    public void setColor(View view) {
        //paint.setColor(Color.RED);
        id=0;
        final int [] col={Color.RED,Color.YELLOW,Color.GREEN,Color.BLUE,Color.WHITE,Color.BLACK};
        final String []s={"红色","黄色","绿色","蓝色","白色","黑色"};
        AlertDialog.Builder DanItem = new AlertDialog.Builder(PaintActivity.this);
        DanItem.setTitle("选择想要使用的颜色");
        DanItem.setSingleChoiceItems(s, -1, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                id =which;
            }
        });
        DanItem.setPositiveButton("确定", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which){
                ShowMessage("恭喜你选择了"+s[id].toString());
                paint.setColor(col[id]);
            }
        });
        DanItem.create().show();
    }
    private void ShowMessage(String str) {
        Toast.makeText(PaintActivity.this, str, Toast.LENGTH_LONG).show();
    }
    public void setWidth(View view) {
        id=0;
        final int [] w={5,10,15,20,25,30,35,40};
        final String []s={"5","10","15","20","25","30"};
        AlertDialog.Builder DanItem = new AlertDialog.Builder(PaintActivity.this);
        DanItem.setTitle("选择想要使用的宽度");
        DanItem.setSingleChoiceItems(s, -1, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                id =which;
            }
        });
        DanItem.setPositiveButton("确定", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which){
                ShowMessage("恭喜你选择了"+s[id]);
                paint.setStrokeWidth(w[id]);
            }
        });
        DanItem.create().show();
    }
    public void setErase(View view) {
        paint.setColor(Color.WHITE);
        paint.setStrokeWidth(30);
    }
    @RequiresApi(api = Build.VERSION_CODES.N)
    public void savePng(View view) throws FileNotFoundException {
        System.out.println(saveBitmap(bitmap));
    }
    @RequiresApi(api = Build.VERSION_CODES.N)
    public String saveBitmap(Bitmap bitmap) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
        Date curDate = new Date(System.currentTimeMillis());//获取当前时间
        String str = formatter.format(curDate);
        String paintPath = "";
        str = str + "paint.png";
        String imagePath = Environment.getExternalStorageDirectory()+"/DRAW";
        File file = new File(imagePath, str);
        try {
            FileOutputStream out = new FileOutputStream(file);
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
            //保存绘图文件路径
            paintPath =file.getAbsolutePath();
///  /storage/emulated/0/DRAW/20211202195458paint.png
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return paintPath;
    }
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
    tools:context="Draw.PaintActivity">
    <RelativeLayout
        android:layout_width="match_parent"
        android:orientation="horizontal"
        android:id="@+id/paint_sum"
        android:layout_height="wrap_content"
        tools:ignore="InvalidId">
        <Button
            android:id="@+id/paint_back"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="返回"
            android:textSize="30dp"></Button>
        <Button
            android:id="@+id/paint_sure"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:paddingLeft="40dp"
            android:onClick="savePng"
            android:text="确定"
            android:textSize="30dp"></Button>
    </RelativeLayout>
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/paint_sum">
        <Button
            android:id="@+id/bnt_color"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="setColor"
            android:text="设置画笔颜色" />
        <Button
            android:id="@+id/bnt_width"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/bnt_color"
            android:onClick="setWidth"
            android:text="设置画笔宽度"
            tools:ignore="UnknownId" />
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/erase"
            android:text="橡皮擦"
            android:onClick="setErase"
            android:layout_toRightOf="@id/bnt_color"
            ></Button>
        <ImageView
            android:id="@+id/iv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/bnt_width" />
    </RelativeLayout>
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_alignParentBottom="true"
        android:id="@+id/res"
        ></ImageView>
</RelativeLayout>
目录
相关文章
|
Android开发
flutter中实现仿Android端的onResume和onPause方法
flutter中实现仿Android端的onResume和onPause方法
|
Android开发 容器
Android实现面包屑效果,支持Fragment联动
Android实现面包屑效果,支持Fragment联动
|
Android开发
Android实现连线题效果
Android实现连线题效果
|
Android开发
Android实现调用系统相机录像及实现录音
Android实现调用系统相机录像及实现录音
584 0
|
移动开发 JavaScript Android开发
通过howler.js实现在Android下的微信浏览器自动播放音频
通过howler.js实现在Android下的微信浏览器自动播放音频
403 0
通过howler.js实现在Android下的微信浏览器自动播放音频
|
传感器 消息中间件 JavaScript
安卓开发过程中的RatingBar、Handler以及GPS在大型项目中的使用【Android】
安卓开发过程中的RatingBar、Handler以及GPS在大型项目中的使用【Android】
163 0
|
存储 Dart Java
【Flutter】packages思维以及使用Java添加Android平台特定的实现在Flutter框架里的体现和运用
【Flutter】packages思维以及使用Java添加Android平台特定的实现在Flutter框架里的体现和运用
|
缓存 JSON Java
java 实现读取txt文件,反射创建对象,android 手机缓存文件目录
java 实现读取txt文件,反射创建对象,android 手机缓存文件目录
340 1
java 实现读取txt文件,反射创建对象,android 手机缓存文件目录
|
数据库 Android开发
android 多级下拉菜单实现教程 greendao使用
android 多级下拉菜单实现教程 greendao使用
169 0
android 多级下拉菜单实现教程 greendao使用
|
XML 开发工具 Android开发
Android自定义控件(十三)——实现CSDN搜索框文字提示容器
Android自定义控件(十三)——实现CSDN搜索框文字提示容器
264 0
Android自定义控件(十三)——实现CSDN搜索框文字提示容器