Dessiner dans Canvas au doigt, Android

114

J'ai besoin de construire un projet pour dessiner sur toile avec les doigts,

pour obtenir l'événement tactile et l'événement de mouvement de mon doigt, et de là dessiner.

Tout le monde peut me conseiller comment démarrer un projet,

et quel est le meilleur composant pour faire une chose comme ça?

Sameer H. Ibra
la source
Une bonne bibliothèque pour cela: github.com/Orange-OpenSource/android-trail-drawing
Udayraj Deshmukh

Réponses:

275

Commencez par parcourir la démo Fingerpaint dans l'exemple sdk.

Un autre échantillon:

public class MainActivity extends Activity {

    DrawingView dv ;
    private Paint mPaint;    

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        dv = new DrawingView(this);
        setContentView(dv);
        mPaint = new Paint();
        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);
        mPaint.setStrokeWidth(12);
    }

    public class DrawingView extends View {

        public int width;
        public  int height;
        private Bitmap  mBitmap;
        private Canvas  mCanvas;
        private Path    mPath;
        private Paint   mBitmapPaint;
        Context context;
        private Paint circlePaint;
        private Path circlePath;

        public DrawingView(Context c) {
            super(c);
            context=c;
            mPath = new Path();
            mBitmapPaint = new Paint(Paint.DITHER_FLAG);
            circlePaint = new Paint();
            circlePath = new Path();
            circlePaint.setAntiAlias(true);
            circlePaint.setColor(Color.BLUE);
            circlePaint.setStyle(Paint.Style.STROKE);
            circlePaint.setStrokeJoin(Paint.Join.MITER);
            circlePaint.setStrokeWidth(4f);
        }

        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);

            mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
            mCanvas = new Canvas(mBitmap);
        }

        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);

            canvas.drawBitmap( mBitmap, 0, 0, mBitmapPaint);
            canvas.drawPath( mPath,  mPaint);
            canvas.drawPath( circlePath,  circlePaint);
        }

        private float mX, mY;
        private static final float TOUCH_TOLERANCE = 4;

        private void touch_start(float x, float y) {
            mPath.reset();
            mPath.moveTo(x, y);
            mX = x;
            mY = y;
        }

        private void touch_move(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;

                circlePath.reset();
                circlePath.addCircle(mX, mY, 30, Path.Direction.CW);
            }
        }

        private void touch_up() {
            mPath.lineTo(mX, mY);
            circlePath.reset();
            // commit the path to our offscreen
            mCanvas.drawPath(mPath,  mPaint);
            // kill this so we don't double draw
            mPath.reset();
        }

        @Override
        public boolean onTouchEvent(MotionEvent event) {
            float x = event.getX();
            float y = event.getY();

            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    touch_start(x, y);
                    invalidate();
                    break;
                case MotionEvent.ACTION_MOVE:
                    touch_move(x, y);
                    invalidate();
                    break;
                case MotionEvent.ACTION_UP:
                    touch_up();
                    invalidate();
                    break;
            }
            return true;
        }
    }
}

Instantané

entrez la description de l'image ici

Explication:

Vous créez une classe de vue puis étendez la vue. Vous remplacez le onDraw (). Vous ajoutez le chemin de l'endroit où le doigt touche et se déplace. Vous remplacez le onTouch () de cet objectif. Dans votre onDraw (), vous dessinez les chemins en utilisant la peinture de votre choix. Vous devez appeler invalidate () pour actualiser la vue.

Pour choisir les options, vous pouvez cliquer sur le menu et choisir les options.

Ce qui suit peut être utilisé comme référence. Vous pouvez modifier ce qui suit en fonction de vos besoins.

public class FingerPaintActivity extends Activity
        implements ColorPickerDialog.OnColorChangedListener {

    MyView mv;
    AlertDialog dialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mv= new MyView(this);
        mv.setDrawingCacheEnabled(true);
        mv.setBackgroundResource(R.drawable.afor);//set the back ground if you wish to
        setContentView(mv);
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        mPaint.setColor(0xFFFF0000);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeJoin(Paint.Join.ROUND);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setStrokeWidth(20);
        mEmboss = new EmbossMaskFilter(new float[] { 1, 1, 1 },
                0.4f, 6, 3.5f);
        mBlur = new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL);
    }

    private Paint       mPaint;
    private MaskFilter  mEmboss;
    private MaskFilter  mBlur;

    public void colorChanged(int color) {
        mPaint.setColor(color);
    }

    public class MyView extends View {

        private static final float MINP = 0.25f;
        private static final float MAXP = 0.75f;
        private Bitmap  mBitmap;
        private Canvas  mCanvas;
        private Path    mPath;
        private Paint   mBitmapPaint;
        Context context;

        public MyView(Context c) {
            super(c);
            context=c;
            mPath = new Path();
            mBitmapPaint = new Paint(Paint.DITHER_FLAG);

        }

        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
            mCanvas = new Canvas(mBitmap);

        }

        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);

            canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
            canvas.drawPath(mPath, mPaint);
        }

        private float mX, mY;
        private static final float TOUCH_TOLERANCE = 4;

        private void touch_start(float x, float y) {
            //showDialog(); 
            mPath.reset();
            mPath.moveTo(x, y);
            mX = x;
            mY = y;

        }
        private void touch_move(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;
            }
        }

        private void touch_up() {
            mPath.lineTo(mX, mY);
            // commit the path to our offscreen
            mCanvas.drawPath(mPath, mPaint);
            // kill this so we don't double draw
            mPath.reset();
            mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SCREEN));
            //mPaint.setMaskFilter(null);
        }

        @Override
        public boolean onTouchEvent(MotionEvent event) {
            float x = event.getX();
            float y = event.getY();

            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    touch_start(x, y);
                    invalidate();
                    break;
                case MotionEvent.ACTION_MOVE:

                    touch_move(x, y);
                    invalidate();
                    break;
                case MotionEvent.ACTION_UP:
                    touch_up();
                    invalidate();
                    break;
            }
            return true;
        }
    }

    private static final int COLOR_MENU_ID = Menu.FIRST;
    private static final int EMBOSS_MENU_ID = Menu.FIRST + 1;
    private static final int BLUR_MENU_ID = Menu.FIRST + 2;
    private static final int ERASE_MENU_ID = Menu.FIRST + 3;
    private static final int SRCATOP_MENU_ID = Menu.FIRST + 4;
    private static final int Save = Menu.FIRST + 5;

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);

        menu.add(0, COLOR_MENU_ID, 0, "Color").setShortcut('3', 'c');
        menu.add(0, EMBOSS_MENU_ID, 0, "Emboss").setShortcut('4', 's');
        menu.add(0, BLUR_MENU_ID, 0, "Blur").setShortcut('5', 'z');
        menu.add(0, ERASE_MENU_ID, 0, "Erase").setShortcut('5', 'z');
        menu.add(0, SRCATOP_MENU_ID, 0, "SrcATop").setShortcut('5', 'z');
        menu.add(0, Save, 0, "Save").setShortcut('5', 'z');

        return true;
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        super.onPrepareOptionsMenu(menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        mPaint.setXfermode(null);
        mPaint.setAlpha(0xFF);

        switch (item.getItemId()) {
            case COLOR_MENU_ID:
                new ColorPickerDialog(this, this, mPaint.getColor()).show();
                return true;
            case EMBOSS_MENU_ID:
                if (mPaint.getMaskFilter() != mEmboss) {
                    mPaint.setMaskFilter(mEmboss);
                } else {
                    mPaint.setMaskFilter(null);
                }
                return true;
            case BLUR_MENU_ID:
                if (mPaint.getMaskFilter() != mBlur) {
                    mPaint.setMaskFilter(mBlur);
                } else {
                    mPaint.setMaskFilter(null);
                }
                return true;
            case ERASE_MENU_ID:
                mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
                mPaint.setAlpha(0x80);
                return true;
            case SRCATOP_MENU_ID:

                mPaint.setXfermode(new PorterDuffXfermode(
                        PorterDuff.Mode.SRC_ATOP));
                mPaint.setAlpha(0x80);
                return true;
            case Save:
                AlertDialog.Builder editalert = new AlertDialog.Builder(FingerPaintActivity.this);
                editalert.setTitle("Please Enter the name with which you want to Save");
                final EditText input = new EditText(FingerPaintActivity.this);
                LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
                        LinearLayout.LayoutParams.FILL_PARENT,
                        LinearLayout.LayoutParams.FILL_PARENT);
                input.setLayoutParams(lp);
                editalert.setView(input);
                editalert.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {

                        String name= input.getText().toString();
                        Bitmap bitmap = mv.getDrawingCache();

                        String path = Environment.getExternalStorageDirectory().getAbsolutePath();
                        File file = new File("/sdcard/"+name+".png");
                        try
                        {
                            if(!file.exists())
                            {
                                file.createNewFile();
                            }
                            FileOutputStream ostream = new FileOutputStream(file);
                            bitmap.compress(CompressFormat.PNG, 10, ostream);
                            ostream.close();
                            mv.invalidate();
                        }
                        catch (Exception e)
                        {
                            e.printStackTrace();
                        }finally
                        {

                            mv.setDrawingCacheEnabled(false);
                        }
                    }
                });

                editalert.show();
                return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

Pipette à couleurs

public class ColorPickerDialog extends Dialog {

    public interface OnColorChangedListener {
        void colorChanged(int color);
    }

    private OnColorChangedListener mListener;
    private int mInitialColor;

    private static class ColorPickerView extends View {
        private Paint mPaint;
        private Paint mCenterPaint;
        private final int[] mColors;
        private OnColorChangedListener mListener;

        ColorPickerView(Context c, OnColorChangedListener l, int color) {
            super(c);
            mListener = l;
            mColors = new int[] {
                    0xFFFF0000, 0xFFFF00FF, 0xFF0000FF, 0xFF00FFFF, 0xFF00FF00,
                    0xFFFFFF00, 0xFFFF0000
            };
            Shader s = new SweepGradient(0, 0, mColors, null);

            mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mPaint.setShader(s);
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setStrokeWidth(32);

            mCenterPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mCenterPaint.setColor(color);
            mCenterPaint.setStrokeWidth(5);
        }

        private boolean mTrackingCenter;
        private boolean mHighlightCenter;

        @Override
        protected void onDraw(Canvas canvas) {
            float r = CENTER_X - mPaint.getStrokeWidth()*0.5f;

            canvas.translate(CENTER_X, CENTER_X);

            canvas.drawOval(new RectF(-r, -r, r, r), mPaint);
            canvas.drawCircle(0, 0, CENTER_RADIUS, mCenterPaint);

            if (mTrackingCenter) {
                int c = mCenterPaint.getColor();
                mCenterPaint.setStyle(Paint.Style.STROKE);

                if (mHighlightCenter) {
                    mCenterPaint.setAlpha(0xFF);
                } else {
                    mCenterPaint.setAlpha(0x80);
                }
                canvas.drawCircle(0, 0,
                        CENTER_RADIUS + mCenterPaint.getStrokeWidth(),
                        mCenterPaint);

                mCenterPaint.setStyle(Paint.Style.FILL);
                mCenterPaint.setColor(c);
            }
        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            setMeasuredDimension(CENTER_X*2, CENTER_Y*2);
        }

        private static final int CENTER_X = 100;
        private static final int CENTER_Y = 100;
        private static final int CENTER_RADIUS = 32;

        private int floatToByte(float x) {
            int n = java.lang.Math.round(x);
            return n;
        }

        private int pinToByte(int n) {
            if (n < 0) {
                n = 0;
            } else if (n > 255) {
                n = 255;
            }
            return n;
        }

        private int ave(int s, int d, float p) {
            return s + java.lang.Math.round(p * (d - s));
        }

        private int interpColor(int colors[], float unit) {
            if (unit <= 0) {
                return colors[0];
            }
            if (unit >= 1) {
                return colors[colors.length - 1];
            }

            float p = unit * (colors.length - 1);
            int i = (int)p;
            p -= i;

            // now p is just the fractional part [0...1) and i is the index
            int c0 = colors[i];
            int c1 = colors[i+1];
            int a = ave(Color.alpha(c0), Color.alpha(c1), p);
            int r = ave(Color.red(c0), Color.red(c1), p);
            int g = ave(Color.green(c0), Color.green(c1), p);
            int b = ave(Color.blue(c0), Color.blue(c1), p);

            return Color.argb(a, r, g, b);
        }

        private int rotateColor(int color, float rad) {
            float deg = rad * 180 / 3.1415927f;
            int r = Color.red(color);
            int g = Color.green(color);
            int b = Color.blue(color);

            ColorMatrix cm = new ColorMatrix();
            ColorMatrix tmp = new ColorMatrix();

            cm.setRGB2YUV();
            tmp.setRotate(0, deg);
            cm.postConcat(tmp);
            tmp.setYUV2RGB();
            cm.postConcat(tmp);

            final float[] a = cm.getArray();

            int ir = floatToByte(a[0] * r +  a[1] * g +  a[2] * b);
            int ig = floatToByte(a[5] * r +  a[6] * g +  a[7] * b);
            int ib = floatToByte(a[10] * r + a[11] * g + a[12] * b);

            return Color.argb(Color.alpha(color), pinToByte(ir),
                    pinToByte(ig), pinToByte(ib));
        }

        private static final float PI = 3.1415926f;

        @Override
        public boolean onTouchEvent(MotionEvent event) {
            float x = event.getX() - CENTER_X;
            float y = event.getY() - CENTER_Y;
            boolean inCenter = java.lang.Math.sqrt(x*x + y*y) <= CENTER_RADIUS;

            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    mTrackingCenter = inCenter;
                    if (inCenter) {
                        mHighlightCenter = true;
                        invalidate();
                        break;
                    }
                case MotionEvent.ACTION_MOVE:
                    if (mTrackingCenter) {
                        if (mHighlightCenter != inCenter) {
                            mHighlightCenter = inCenter;
                            invalidate();
                        }
                    } else {
                        float angle = (float)java.lang.Math.atan2(y, x);
                        // need to turn angle [-PI ... PI] into unit [0....1]
                        float unit = angle/(2*PI);
                        if (unit < 0) {
                            unit += 1;
                        }
                        mCenterPaint.setColor(interpColor(mColors, unit));
                        invalidate();
                    }
                    break;
                case MotionEvent.ACTION_UP:
                    if (mTrackingCenter) {
                        if (inCenter) {
                            mListener.colorChanged(mCenterPaint.getColor());
                        }
                        mTrackingCenter = false;    // so we draw w/o halo
                        invalidate();
                    }
                    break;
            }
            return true;
        }
    }

    public ColorPickerDialog(Context context,
                             OnColorChangedListener listener,
                             int initialColor) {
        super(context);

        mListener = listener;
        mInitialColor = initialColor;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        OnColorChangedListener l = new OnColorChangedListener() {
            public void colorChanged(int color) {
                mListener.colorChanged(color);
                dismiss();
            }
        };

        setContentView(new ColorPickerView(getContext(), l, mInitialColor));
        setTitle("Pick a Color");
    }
}
Raghunandan
la source
J'ajoute le premier dans eclipse, ajoute une classe java appelée DrawingView dans la classe principale, ajoute la fonction onCreate, mais mPaint définit dans MainActivity et DrawingView l'a appelé. est ce que je fais par classes séparées est-ce exact?
Sameer H.Ibra
Vous pouvez définir un objet de peinture dans le constructeur de la classe de dessin sans problème. Si vous utilisez le premier. il n'est pas nécessaire de modifier quoi que ce soit. Ça fonctionne bien. Ajoutez simplement des instructions d'importation.
Raghunandan
1
@apostleofzion aucune idée. il vaut mieux que vous postez une question avec des détails et vous pourriez obtenir une meilleure réponse. Désolé je ne connais pas la solution.
Raghunandan
3
pourquoi avez-vous besoin de plus Canvas mCanvas? parce que vous utilisezonDraw(Canvas canvas)
Mirodil
1
@FahadSaleem dépend du design que vous souhaitez. vous devez comprendre cela vous-même. Désolé!.
Raghunandan
40

Concernant le beau code de Raghunandan ci-dessus.

Beaucoup ont demandé comment «effacer» le dessin. Voici comment procéder:

public void clearDrawing()
    {
    Utils.Log("RaghunandanDraw, how to clear....");

    setDrawingCacheEnabled(false);
    // don't forget that one and the match below,
    // or you just keep getting a duplicate when you save.

    onSizeChanged(width, height, width, height);
    invalidate();

    setDrawingCacheEnabled(true);
    }

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
    {
    super.onSizeChanged(w, h, oldw, oldh);

    width = w;      // don't forget these
    height = h;

    mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    mCanvas = new Canvas(mBitmap);
    }

Beaucoup ont demandé comment «enregistrer» le dessin. Voici comment procéder:

public DrawingView(Context c)
  {
  circlePaint.setStrokeJoin(Paint.Join.MITER);
  circlePaint.setStrokeWidth(4f); 
  etc...

  // in the class where you set up the view, add this:
  setDrawingCacheEnabled( true );
  }

public void saveDrawing()
  {
  Bitmap whatTheUserDrewBitmap = getDrawingCache();
  // don't forget to clear it (see above) or you just get duplicates

  // almost always you will want to reduce res from the very high screen res
  whatTheUserDrewBitmap =
         ThumbnailUtils.extractThumbnail(whatTheUserDrewBitmap, 256, 256);
  // NOTE that's an incredibly useful trick for cropping/resizing squares
  // while handling all memory problems etc
  // http://stackoverflow.com/a/17733530/294884

  // you can now save the bitmap to a file, or display it in an ImageView:
  ImageView testArea = ...
  testArea.setImageBitmap( whatTheUserDrewBitmap );

  // these days you often need a "byte array". for example,
  // to save to parse.com or other cloud services
  ByteArrayOutputStream baos = new ByteArrayOutputStream();
  whatTheUserDrewBitmap.compress(Bitmap.CompressFormat.PNG, 0, baos);
  byte[] yourByteArray;
  yourByteArray = baos.toByteArray();
  }

J'espère que cela aide quelqu'un car cela m'a aidé.

Fattie
la source
PS si vous êtes sur Mac si vous recherchez la démo d'empreintes digitales, stackoverflow.com/questions/24164334
Fattie
Où obtenez-vous la largeur et la hauteur parce que @Raghunandan n'a défini ces variables nulle part dans son code? S'agit-il des dimensions de la zone de signature?
Robertas Setkus
Hey Robertas, ils sont juste là dans la classe publique DrawingView étend la vue { ... les deux premiers éléments! N'hésitez pas à poser d'autres questions. À votre santé. Oui, ils sont définis «automatiquement» lorsque onSizeChanged est appelé pour la première fois par le système.
Fattie le
3
Oui, ils sont sur les deux premières lignes mais certains comment ils ont des valeurs 0 même si quelque chose est dessiné à la vue. Je viens de copier et coller le code de @Raghunandan qui fonctionne. Ensuite, votre clearDrawingméthode est incluse. J'obtiens une exception car la hauteur et la largeur doivent être> 0. Ensuite, j'ai regardé le code et j'ai vu que ces variables ne sont pas définies. Je vous ai donc demandé comment obtenir les valeurs de largeur et de hauteur. PS vous devez appeler invalidate()si vous voulez rafraîchir la zone de dessin!
Robertas Setkus
20

Vous pouvez utiliser cette classe simplement:

public class DoodleCanvas  extends View{

    private Paint mPaint;
    private Path mPath;

    public DoodleCanvas(Context context, AttributeSet attrs) {
        super(context, attrs);
        mPaint = new Paint();
        mPaint.setColor(Color.RED);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeJoin(Paint.Join.ROUND);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setStrokeWidth(10);
        mPath = new Path();
    }


    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawPath(mPath, mPaint);
        super.onDraw(canvas);
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {

        switch (event.getAction()){

            case MotionEvent.ACTION_DOWN:
                mPath.moveTo(event.getX(), event.getY());
                break;

            case MotionEvent.ACTION_MOVE:
                mPath.lineTo(event.getX(), event.getY());
                invalidate();
                break;

            case MotionEvent.ACTION_UP:
                break;
        }

        return true;
    }
}
Ishan
la source
Je voulais dessiner par programme sans interaction de l'utilisateur (également sur l'interaction de l'utilisateur, rien ne devrait se produire). supprimé le onTouchEvent et les méthodes publiques exposées pour dessiner et déplacer. Réponse parfaite!
Jaswant Singh le
8

tutoriel pour dessiner une ligne utilise la classe Bitmap, Canvas et Paint. draw-line-on-finger-touch et androiddraw

ici une classe simple pour dessiner une ligne en utilisant le canevas comme indiqué ci-dessous.

    public class TestLineView extends View {

    private Paint paint;
    private PointF startPoint, endPoint;
    private boolean isDrawing;

    public TestLineView(Context context)
    {
        super(context);
        init();
    }

    private void init()
    {
        paint = new Paint();
        paint.setColor(Color.RED);
        paint.setStyle(Style.STROKE);
        paint.setStrokeWidth(2);
        paint.setAntiAlias(true);
    }

    @Override
    protected void onDraw(Canvas canvas)
    {
        if(isDrawing)
        {
            canvas.drawLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y, paint);
        }
    }


    @Override
    public boolean onTouchEvent(MotionEvent event)
    {
        switch (event.getAction())
        {
            case MotionEvent.ACTION_DOWN:
                startPoint = new PointF(event.getX(), event.getY());
                endPoint = new PointF();
                isDrawing = true;
                break;
            case MotionEvent.ACTION_MOVE:
                if(isDrawing)
                {
                    endPoint.x = event.getX();
                    endPoint.y = event.getY();
                    invalidate();
                }
                break;
            case MotionEvent.ACTION_UP:
                if(isDrawing)
                {
                    endPoint.x = event.getX();
                    endPoint.y = event.getY();
                    isDrawing = false;
                    invalidate();
                }
                break;
            default:
                break;
        }
        return true;
    }
}
kyogs
la source
1
Et le dessin gratuit? Et la ligne à tracer lorsque vous bougez votre doigt?
Si8
1

Je pense qu'il est important d'ajouter une chose, si vous utilisez l'inflation de mise en page que le constructeur dans le drawview n'est pas correct, ajoutez ces constructeurs dans la classe:

public DrawingView(Context c, AttributeSet attrs) {
    super(c, attrs);
    ...
}

public DrawingView(Context c, AttributeSet attrs, int defStyle) {
    super(c, attrs, defStyle);
    ...
}

ou le système Android ne parvient pas à gonfler le fichier de mise en page. J'espère que cela pourra vous aider.

ghiltanas
la source
0

En plus de la réponse d'Ishan, si vous voulez dessiner par programme sans interaction de l'utilisateur, vous pouvez éditer la classe juste un peu comme ça.

public class DrawingCanvas extends View {

private Paint mPaint;
private Path mPath;
private boolean isUserInteractionEnabled = false;

public DrawingCanvas(Context context, AttributeSet attrs) {
    super(context, attrs);
    mPaint = new Paint();
    mPaint.setColor(Color.RED);
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setStrokeJoin(Paint.Join.ROUND);
    mPaint.setStrokeCap(Paint.Cap.ROUND);
    mPaint.setStrokeWidth(10);
    mPath = new Path();
}


@Override
protected void onDraw(Canvas canvas) {
    canvas.drawPath(mPath, mPaint);
    super.onDraw(canvas);
}


@Override
public boolean onTouchEvent(MotionEvent event) {
    if (isUserInteractionEnabled) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mPath.moveTo(event.getX(), event.getY());
                break;
            case MotionEvent.ACTION_MOVE:
                mPath.lineTo(event.getX(), event.getY());
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                break;
        }
    }

    return true;
}

public void moveCursorTo(float x, float y) {
    mPath.moveTo(x, y);
}

public void makeLine(float toX, float toY) {
    mPath.lineTo(toX, toY);
}

public void setUserInteractionEnabled(boolean userInteractionEnabled) {
    isUserInteractionEnabled = userInteractionEnabled;
}
}

Et puis utilisez-le comme

drawingCanvas.setUserInteractionEnabled(true) // to enable user interaction
drawingCanvas.setUserInteractionEnabled(true) // to disable user interaction

Pour dessiner par programme

drawingCanvas.moveCursorTo(70f, 70f) // Move the cursor (Define starting point)
drawingCanvas.makeLine(200f, 200f) // End point (To where you need to draw)
Jaswant Singh
la source