📜  如何在Android中创建Paint应用程序?

📅  最后修改于: 2021-05-13 17:49:34             🧑  作者: Mango

我们每个人都曾经在童年时代使用过MS-Paint,当系统从书桌转移到掌上电脑时,我们开始在Instagram Stories,Hike,WhatsApp以及更多此类应用程序上涂鸦。但是您是否考虑过这些功能是如何实现的?因此,在本文中,我们将讨论此类应用程序使用的基本方法,并将创建此类应用程序的基本副本。下面提供了一个示例视频,以使您对我们在本文中将要做的事情有个大概的了解。注意,我们将使用Java语言实现该项目。

该方法

  1. 在日常生活中,如果要创建图形,我们首先需要使用Canvas进行处理。因此,在我们的应用程序中,我们将首先创建一个画布,用户可以在其中绘制其图纸。为此,我们需要创建一个自定义视图,用户可以在其中简单地拖动手指以绘制笔触。为了实现这一点,我们创建了一个DrawView类,该类从标准的Android SDK扩展了View类。
  2. 然后,我们将需要用作工具的画笔来帮助我们在画布上绘画。现在,由于我们需要用于不同颜色和笔触宽度的不同笔刷,因此我们将创建一个蓝图,即名为Stroke的类,该类具有笔触的颜色,笔触的宽度,笔触的可见性等属性。该类将代表一个独特的画笔,在画布上绘制一个独特的笔触。
  3. 为了记录用户在画布上绘制的每个笔触,我们将创建一个Stroke类型的ArrayList。此ArrayList将帮助我们撤消用户在画布上错误绘制的Stroke。
  4. 现在,在用户完成图形处理后,他可能希望保存该图形以备将来使用。因此,我们提供了“保存”选项,该选项允许用户以PNG或JPEG的形式保存当前画布。

方法清单

在跳转到代码之前,这里有一些我们将在构建应用程序时使用的方法:

Type

Method

Description

void setDither(boolean dither)

Dithering affects the down-sampling of colors that are of

higher precision than the device’s accuracy.

void setAntiAlias (boolean aa)

AntiAliasing smooths out the edges of what is drawn but

has little effect on the shape’s interior.

void setStyle(Paint.Style style) This method controls the 
void setStrokeCap (Paint.Cap cap)

This method changes the geometry of the endpoint of the

line as per the argument For example, ROUND, SQUARE, BUTT.

void void setStrokeJoin (Paint.Join join) This method sets the paint to join to either ROUND, BEVEL, MITTER
void setAlpha (int a)

It is a helper method that only assigns the color’s 

alpha value, leaving its r,g,b values unchanged. 

Results are undefined if the alpha value is outside of the range [0..255]

void invalidate()

This method calls the overridden onDraw() method. 

Whenever we want to update the screen, in our case the Canvas,

we call invalidate() which further internally calls the onDraw() method.

int Canvas.save()

This method saves the current state of the Canvas 

so that we can go back to it later

void Canvas.restore()

This method reverts the Canvas’s adjustments back to 

the last time the was cavas.save() called.

void Path.quadTo (float x1,float y1, float x2, float y2)

This method smoothens the curves using a quadratic line.

(x1,y1) is the control point on a quadratic curve and (x2,y2) 

are the endpoint on a quadratic curve.

现在,让我们开始构建该应用程序。这个应用程式不需要任何特殊权限。因此,将AndroidManifest.xml保留为默认设置。

分步实施

步骤1:创建一个新项目

要在Android Studio中创建新项目,请参阅如何在Android Studio中创建/启动新项目。请注意,选择Java作为编程语言。

步骤2:在gradle.build中添加依赖项

该库用于向我们的应用添加调色板,以便用户可以选择自己选择的任何颜色

步骤3:使用activity_main.xml文件

导航到应用程序> res>布局> activity_main.xml,然后将以下代码添加到该文件中。以下是activity_main.xml文件的代码。

XML


      
    
  
        
  
            
  
            
  
            
  
            
        
  
        
  
            
            
        
        
    
  
    
      


Java
import android.graphics.Path;
  
public class Stroke {
  
    // color of the stroke
    public int color;
      
    // width of the stroke
    public int strokeWidth;
      
    // a Path object to 
    // represent the path drawn
    public Path path;
  
    // constructor to initialise the attributes
    public Stroke(int color, int strokeWidth, Path path) {
        this.color = color;
        this.strokeWidth = strokeWidth;
        this.path = path;
    }
}


Java
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
  
import java.util.ArrayList;
  
public class DrawView extends View {
  
    private static final float TOUCH_TOLERANCE = 4;
    private float mX, mY;
    private Path mPath;
      
    // the Paint class encapsulates the color
    // and style information about
    // how to draw the geometries,text and bitmaps
    private Paint mPaint;
     
    // ArrayList to store all the strokes 
    // drawn by the user on the Canvas
    private ArrayList paths = new ArrayList<>();
    private int currentColor;
    private int strokeWidth;
    private Bitmap mBitmap;
    private Canvas mCanvas;
    private Paint mBitmapPaint = new Paint(Paint.DITHER_FLAG);
  
    // Constructors to initialise all the attributes
    public DrawView(Context context) {
        this(context, null);
    }
  
    public DrawView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mPaint = new Paint();
          
        // the below methods smoothens
        // the drawings of the user
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        mPaint.setColor(Color.GREEN);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeJoin(Paint.Join.ROUND);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
         
        // 0xff=255 in decimal
        mPaint.setAlpha(0xff);
  
    }
  
    // this method instantiate the bitmap and object
    public void init(int height, int width) {
  
        mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        mCanvas = new Canvas(mBitmap);
  
        // set an initial color of the brush
        currentColor = Color.GREEN;
          
        // set an initial brush size
        strokeWidth = 20;
    }
  
    // sets the current color of stroke
    public void setColor(int color) {
        currentColor = color;
    }
  
    // sets the stroke width
    public void setStrokeWidth(int width) {
        strokeWidth = width;
    }
  
    public void undo() {
        // check whether the List is empty or not
        // if empty, the remove method will return an error
        if (paths.size() != 0) {
            paths.remove(paths.size() - 1);
            invalidate();
        }
    }
  
    // this methods returns the current bitmap
    public Bitmap save() {
        return mBitmap;
    }
  
    // this is the main method where 
    // the actual drawing takes place
    @Override
    protected void onDraw(Canvas canvas) {
        // save the current state of the canvas before,
        // to draw the background of the canvas
        canvas.save();
          
        // DEFAULT color of the canvas
        int backgroundColor = Color.WHITE;
        mCanvas.drawColor(backgroundColor);
  
        // now, we iterate over the list of paths
        // and draw each path on the canvas
        for (Stroke fp : paths) {
            mPaint.setColor(fp.color);
            mPaint.setStrokeWidth(fp.strokeWidth);
            mCanvas.drawPath(fp.path, mPaint);
        }
        canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
        canvas.restore();
    }
  
    // the below methods manages the touch 
    // response of the user on the screen
  
    // firstly, we create a new Stroke 
    // and add it to the paths list
    private void touchStart(float x, float y) {
        mPath = new Path();
        Stroke fp = new Stroke(currentColor, strokeWidth, mPath);
        paths.add(fp);
  
        // finally remove any curve 
        // or line from the path
        mPath.reset();
          
        // this methods sets the starting 
        // point of the line being drawn
        mPath.moveTo(x, y);
         
        // we save the current 
        // coordinates of the finger
        mX = x;
        mY = y;
    }
  
    // in this method we check 
    // if the move of finger on the
    // screen is greater than the 
    // Tolerance we have previously defined,
    // then we call the quadTo() method which
    // actually smooths the turns we create,
    // by calculating the mean position between
    // the previous position and current position
    private void touchMove(float x, float y) {
        float dx = Math.abs(x - mX);
        float dy = Math.abs(y - mY);
  
        if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
            mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
            mX = x;
            mY = y;
        }
    }
  
    // at the end, we call the lineTo method 
    // which simply draws the line until
    // the end position
    private void touchUp() {
        mPath.lineTo(mX, mY);
    }
  
    // the onTouchEvent() method provides us with
    // the information about the type of motion
    // which has been taken place, and according
    // to that we call our desired methods
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();
  
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                touchStart(x, y);
                invalidate();
                break;
            case MotionEvent.ACTION_MOVE:
                touchMove(x, y);
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                touchUp();
                invalidate();
                break;
        }
        return true;
    }
}


Java
import android.content.ContentValues;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.ImageButton;
  
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
  
import com.google.android.material.slider.RangeSlider;
  
import java.io.OutputStream;
  
import petrov.kristiyan.colorpicker.ColorPicker;
  
public class MainActivity extends AppCompatActivity {
      
    // creating the object of type DrawView
    // in order to get the reference of the View
    private DrawView paint;
      
    // creating objects of type button
    private ImageButton save, color, stroke, undo;
      
    // creating a RangeSlider object, which will
    // help in selecting the width of the Stroke
    private RangeSlider rangeSlider;
  
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
  
        // getting the reference of the views from their ids
        paint = (DrawView) findViewById(R.id.draw_view);
        rangeSlider = (RangeSlider) findViewById(R.id.rangebar);
        undo = (ImageButton) findViewById(R.id.btn_undo);
        save = (ImageButton) findViewById(R.id.btn_save);
        color = (ImageButton) findViewById(R.id.btn_color);
        stroke = (ImageButton) findViewById(R.id.btn_stroke);
  
        // creating a OnClickListener for each button,
        // to perform certain actions
  
        // the undo button will remove the most
        // recent stroke from the canvas
        undo.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                paint.undo();
            }
        });
          
        // the save button will save the current
        // canvas which is actually a bitmap
        // in form of PNG, in the storage
        save.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                  
                // getting the bitmap from DrawView class
                Bitmap bmp = paint.save();
                  
                // opening a OutputStream to write into the file
                OutputStream imageOutStream = null;
  
                ContentValues cv = new ContentValues();
                  
                // name of the file
                cv.put(MediaStore.Images.Media.DISPLAY_NAME, "drawing.png");
                  
                // type of the file
                cv.put(MediaStore.Images.Media.MIME_TYPE, "image/png");
                  
                // location of the file to be saved
                cv.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES);
  
                // get the Uri of the file which is to be created in the storage
                Uri uri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, cv);
                try {
                    // open the output stream with the above uri
                    imageOutStream = getContentResolver().openOutputStream(uri);
                      
                    // this method writes the files in storage
                    bmp.compress(Bitmap.CompressFormat.PNG, 100, imageOutStream);
                      
                    // close the output stream after use
                    imageOutStream.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        // the color button will allow the user
        // to select the color of his brush
        color.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                final ColorPicker colorPicker = new ColorPicker(MainActivity.this);
                colorPicker.setOnFastChooseColorListener(new ColorPicker.OnFastChooseColorListener() {
                    @Override
                    public void setOnFastChooseColorListener(int position, int color) {
                        // get the integer value of color 
                        // selected from the dialog box and
                        // set it as the stroke color
                        paint.setColor(color);
                    }
                    @Override
                    public void onCancel() {
                        colorPicker.dismissDialog();
                    }
                })
                        // set the number of color columns
                        // you want  to show in dialog.
                        .setColumns(5)
                        // set a default color selected 
                        // in the dialog
                        .setDefaultColorButton(Color.parseColor("#000000"))
                        .show();
            }
        });
        // the button will toggle the visibility of the RangeBar/RangeSlider
        stroke.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (rangeSlider.getVisibility() == View.VISIBLE)
                    rangeSlider.setVisibility(View.GONE);
                else
                    rangeSlider.setVisibility(View.VISIBLE);
            }
        });
  
        // set the range of the RangeSlider
        rangeSlider.setValueFrom(0.0f);
        rangeSlider.setValueTo(100.0f);
          
        // adding a OnChangeListener which will
        // change the stroke width
        // as soon as the user slides the slider
        rangeSlider.addOnChangeListener(new RangeSlider.OnChangeListener() {
            @Override
            public void onValueChange(@NonNull RangeSlider slider, float value, boolean fromUser) {
                paint.setStrokeWidth((int) value);
            }
        });
  
        // pass the height and width of the custom view 
        // to the init method of the DrawView object
        ViewTreeObserver vto = paint.getViewTreeObserver();
        vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                paint.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                int width = paint.getMeasuredWidth();
                int height = paint.getMeasuredHeight();
                paint.init(height, width);
            }
        });
    }
}


步骤4:创建Stroke类

请参阅如何在Android Studio中创建类。并将该类命名为Stroke以下是中风代码。 Java文件。

Java

import android.graphics.Path;
  
public class Stroke {
  
    // color of the stroke
    public int color;
      
    // width of the stroke
    public int strokeWidth;
      
    // a Path object to 
    // represent the path drawn
    public Path path;
  
    // constructor to initialise the attributes
    public Stroke(int color, int strokeWidth, Path path) {
        this.color = color;
        this.strokeWidth = strokeWidth;
        this.path = path;
    }
}

步骤5:创建DrawView类

同样,创建一个新的Java类并将该类命名为DrawView下面是DrawView的代码。 Java文件。

Java

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
  
import java.util.ArrayList;
  
public class DrawView extends View {
  
    private static final float TOUCH_TOLERANCE = 4;
    private float mX, mY;
    private Path mPath;
      
    // the Paint class encapsulates the color
    // and style information about
    // how to draw the geometries,text and bitmaps
    private Paint mPaint;
     
    // ArrayList to store all the strokes 
    // drawn by the user on the Canvas
    private ArrayList paths = new ArrayList<>();
    private int currentColor;
    private int strokeWidth;
    private Bitmap mBitmap;
    private Canvas mCanvas;
    private Paint mBitmapPaint = new Paint(Paint.DITHER_FLAG);
  
    // Constructors to initialise all the attributes
    public DrawView(Context context) {
        this(context, null);
    }
  
    public DrawView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mPaint = new Paint();
          
        // the below methods smoothens
        // the drawings of the user
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        mPaint.setColor(Color.GREEN);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeJoin(Paint.Join.ROUND);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
         
        // 0xff=255 in decimal
        mPaint.setAlpha(0xff);
  
    }
  
    // this method instantiate the bitmap and object
    public void init(int height, int width) {
  
        mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        mCanvas = new Canvas(mBitmap);
  
        // set an initial color of the brush
        currentColor = Color.GREEN;
          
        // set an initial brush size
        strokeWidth = 20;
    }
  
    // sets the current color of stroke
    public void setColor(int color) {
        currentColor = color;
    }
  
    // sets the stroke width
    public void setStrokeWidth(int width) {
        strokeWidth = width;
    }
  
    public void undo() {
        // check whether the List is empty or not
        // if empty, the remove method will return an error
        if (paths.size() != 0) {
            paths.remove(paths.size() - 1);
            invalidate();
        }
    }
  
    // this methods returns the current bitmap
    public Bitmap save() {
        return mBitmap;
    }
  
    // this is the main method where 
    // the actual drawing takes place
    @Override
    protected void onDraw(Canvas canvas) {
        // save the current state of the canvas before,
        // to draw the background of the canvas
        canvas.save();
          
        // DEFAULT color of the canvas
        int backgroundColor = Color.WHITE;
        mCanvas.drawColor(backgroundColor);
  
        // now, we iterate over the list of paths
        // and draw each path on the canvas
        for (Stroke fp : paths) {
            mPaint.setColor(fp.color);
            mPaint.setStrokeWidth(fp.strokeWidth);
            mCanvas.drawPath(fp.path, mPaint);
        }
        canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
        canvas.restore();
    }
  
    // the below methods manages the touch 
    // response of the user on the screen
  
    // firstly, we create a new Stroke 
    // and add it to the paths list
    private void touchStart(float x, float y) {
        mPath = new Path();
        Stroke fp = new Stroke(currentColor, strokeWidth, mPath);
        paths.add(fp);
  
        // finally remove any curve 
        // or line from the path
        mPath.reset();
          
        // this methods sets the starting 
        // point of the line being drawn
        mPath.moveTo(x, y);
         
        // we save the current 
        // coordinates of the finger
        mX = x;
        mY = y;
    }
  
    // in this method we check 
    // if the move of finger on the
    // screen is greater than the 
    // Tolerance we have previously defined,
    // then we call the quadTo() method which
    // actually smooths the turns we create,
    // by calculating the mean position between
    // the previous position and current position
    private void touchMove(float x, float y) {
        float dx = Math.abs(x - mX);
        float dy = Math.abs(y - mY);
  
        if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
            mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
            mX = x;
            mY = y;
        }
    }
  
    // at the end, we call the lineTo method 
    // which simply draws the line until
    // the end position
    private void touchUp() {
        mPath.lineTo(mX, mY);
    }
  
    // the onTouchEvent() method provides us with
    // the information about the type of motion
    // which has been taken place, and according
    // to that we call our desired methods
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();
  
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                touchStart(x, y);
                invalidate();
                break;
            case MotionEvent.ACTION_MOVE:
                touchMove(x, y);
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                touchUp();
                invalidate();
                break;
        }
        return true;
    }
}

步骤6:使用MainActivity。 Java文件

转到MainActivity。 Java文件并参考以下代码。下面是MainActivity的代码。 Java文件。在代码内部添加了注释,以更详细地了解代码。

Java

import android.content.ContentValues;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.ImageButton;
  
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
  
import com.google.android.material.slider.RangeSlider;
  
import java.io.OutputStream;
  
import petrov.kristiyan.colorpicker.ColorPicker;
  
public class MainActivity extends AppCompatActivity {
      
    // creating the object of type DrawView
    // in order to get the reference of the View
    private DrawView paint;
      
    // creating objects of type button
    private ImageButton save, color, stroke, undo;
      
    // creating a RangeSlider object, which will
    // help in selecting the width of the Stroke
    private RangeSlider rangeSlider;
  
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
  
        // getting the reference of the views from their ids
        paint = (DrawView) findViewById(R.id.draw_view);
        rangeSlider = (RangeSlider) findViewById(R.id.rangebar);
        undo = (ImageButton) findViewById(R.id.btn_undo);
        save = (ImageButton) findViewById(R.id.btn_save);
        color = (ImageButton) findViewById(R.id.btn_color);
        stroke = (ImageButton) findViewById(R.id.btn_stroke);
  
        // creating a OnClickListener for each button,
        // to perform certain actions
  
        // the undo button will remove the most
        // recent stroke from the canvas
        undo.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                paint.undo();
            }
        });
          
        // the save button will save the current
        // canvas which is actually a bitmap
        // in form of PNG, in the storage
        save.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                  
                // getting the bitmap from DrawView class
                Bitmap bmp = paint.save();
                  
                // opening a OutputStream to write into the file
                OutputStream imageOutStream = null;
  
                ContentValues cv = new ContentValues();
                  
                // name of the file
                cv.put(MediaStore.Images.Media.DISPLAY_NAME, "drawing.png");
                  
                // type of the file
                cv.put(MediaStore.Images.Media.MIME_TYPE, "image/png");
                  
                // location of the file to be saved
                cv.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES);
  
                // get the Uri of the file which is to be created in the storage
                Uri uri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, cv);
                try {
                    // open the output stream with the above uri
                    imageOutStream = getContentResolver().openOutputStream(uri);
                      
                    // this method writes the files in storage
                    bmp.compress(Bitmap.CompressFormat.PNG, 100, imageOutStream);
                      
                    // close the output stream after use
                    imageOutStream.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        // the color button will allow the user
        // to select the color of his brush
        color.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                final ColorPicker colorPicker = new ColorPicker(MainActivity.this);
                colorPicker.setOnFastChooseColorListener(new ColorPicker.OnFastChooseColorListener() {
                    @Override
                    public void setOnFastChooseColorListener(int position, int color) {
                        // get the integer value of color 
                        // selected from the dialog box and
                        // set it as the stroke color
                        paint.setColor(color);
                    }
                    @Override
                    public void onCancel() {
                        colorPicker.dismissDialog();
                    }
                })
                        // set the number of color columns
                        // you want  to show in dialog.
                        .setColumns(5)
                        // set a default color selected 
                        // in the dialog
                        .setDefaultColorButton(Color.parseColor("#000000"))
                        .show();
            }
        });
        // the button will toggle the visibility of the RangeBar/RangeSlider
        stroke.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (rangeSlider.getVisibility() == View.VISIBLE)
                    rangeSlider.setVisibility(View.GONE);
                else
                    rangeSlider.setVisibility(View.VISIBLE);
            }
        });
  
        // set the range of the RangeSlider
        rangeSlider.setValueFrom(0.0f);
        rangeSlider.setValueTo(100.0f);
          
        // adding a OnChangeListener which will
        // change the stroke width
        // as soon as the user slides the slider
        rangeSlider.addOnChangeListener(new RangeSlider.OnChangeListener() {
            @Override
            public void onValueChange(@NonNull RangeSlider slider, float value, boolean fromUser) {
                paint.setStrokeWidth((int) value);
            }
        });
  
        // pass the height and width of the custom view 
        // to the init method of the DrawView object
        ViewTreeObserver vto = paint.getViewTreeObserver();
        vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                paint.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                int width = paint.getMeasuredWidth();
                int height = paint.getMeasuredHeight();
                paint.init(height, width);
            }
        });
    }
}

输出:

未来范围

您可以在此项目中添加很多东西,例如:

  1. 为绘制的对象添加蒙版,即在笔划上创建模糊或浮雕效果。
  2. 将动画添加到应用程序。
  3. 为画布添加颜色选择器,即根据用户要求从默认的白色更改画布的颜色。
  4. 添加共享按钮,以直接在各种应用程序上共享图形。
  5. 添加了橡皮擦功能,可清除拖动橡皮擦的特定路径/笔触。
  6. 添加形状选择器,用户可以通过该形状选择器直接从列表中选择任何特定形状,并可以在屏幕上拖动以创建该形状。
  7. 通过添加BottomSheet,向量等来增强UI。

“任何人都可以在画布上绘画,但只有真正的大师才能使绘画栩栩如生。”,我们完成了应用的构建,现在在此画布上绘制了一些很棒的画,成为了“真正的大师”。

想要一个节奏更快,更具竞争性的环境来学习Android的基础知识吗?
单击此处,前往由我们的专家精心策划的指南,以使您立即做好行业准备!