Малюйте на полотні пальцем, Android


114

Мені потрібно створити проект малювання на полотні пальцями,

щоб отримати сенсорну подію та рух мого пальця, а звідти намалювати.

Кожен може порадити мені, як почати проект,

і який найкращий компонент робити подібне?


Хороша бібліотека для цього: github.com/Orange-OpenSource/android-trail-drawing
Udayraj Deshmukh

Відповіді:


275

Почніть з перегляду демонстрації Fingerpaint у зразку sdk.

Ще один зразок:

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;
        }
    }
}

Знімок постріл

введіть тут опис зображення

Пояснення:

Ви створюєте клас перегляду, а потім розширює Перегляд. Ви переосмислюєте onDraw (). Ви додаєте шлях, куди пальцем торкається і рухається. Ви перекриваєте onTouch () цієї мети. У малюнку onDraw () ви малюєте контури за допомогою обраної вами фарби. Вам слід зателефонувати invalidate (), щоб оновити подання.

Щоб вибрати параметри, ви можете натиснути меню та вибрати параметри.

Наведене нижче може бути використане в якості посилання. Ви можете змінити наведене нижче відповідно до своїх потреб.

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);
    }
}

Вибір кольорів

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");
    }
}

я додаю перший у затемнення, додаю клас java під назвою DrawingView в основний клас, додаємо функцію onCreate, але mPaint визначаємо в MainActivity і DrawingView називає це. це те, що я роблю окремими класами, це правильно?
Самєр Х. Ібра

Ви можете визначити об’єкт фарби в конструкторі класу малювання не проблема. Якщо ви використовуєте перший. не потрібно нічого змінювати. Це чудово працює. Просто додайте заяви про імпорт.
Рагунандан

1
@apostleofzion поняття не маю. краще ви опублікуєте питання з деталями, і ви можете отримати кращу відповідь. Вибачте, що не знаю рішення.
Рагунандан

3
навіщо вам потрібні додаткові Canvas mCanvas? тому що ти використовуєшonDraw(Canvas canvas)
Мироділь

1
@FahadSaleem залежить від того, який дизайн ви хочете. вам потрібно це зрозуміти самостійно. вибачте !.
Рагунандан

40

Щодо прекрасного коду Рагунандана вище.

Багато хто запитував, як «очистити» малюнок. Ось як це зробити:

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);
    }

Багато хто запитував, як «зберегти» малюнок. Ось як це зробити:

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();
  }

Сподіваюся, що це комусь допомагає, як це допомогло мені.


PS, якщо ви на Mac, якщо ви шукаєте демонстрацію відбитків пальців, stackoverflow.com/questions/24164334
Fattie

Звідки ви берете ширину та висоту, оскільки @Raghunandan не встановив ці змінні ніде у своєму коді? Це розміри площі підпису?
Робертас Сеткус

Ей, Робертас, вони прямо там, у публічному класі DrawingView розширює Перегляд { ... перші два пункти! Не соромтеся запитати більше запитань. Ура. Так, вони встановлюються "автоматично", коли система вперше викликає onSizeChanged.
Fattie

3
Так, вони знаходяться на перших двох рядках, але деякі, як вони мають 0 значень, навіть ніж щось намальовано на виду. Я просто скопіював і вставив код @Raghunandan, який працює. Тоді ваш clearDrawingметод включений, я отримую виняток через те, що висота і ширина повинні бути> 0. ніж я подивився на код і побачив, що ці змінні не встановлені. Тому я запитав вас, як ви отримуєте значення ширини та висоти. PS Ви повинні зателефонувати, invalidate()якщо ви хочете оновити зону малювання!
Робертас Сеткус

20

Ви можете використовувати цей клас просто:

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;
    }
}

Я хотів малювати програмно без взаємодії з користувачем (Також щодо взаємодії з користувачем нічого не повинно відбуватися). видалив onTouchEvent і відкрив публічні методи малювання та переміщення. Ідеальна відповідь!
Жасвант Сінгх

8

підручник для малювання ліній з використанням растрових зображень, полотна та класу Paint. малювати лінію-на-дотику-пальці та андроіддрука

ось один простий клас для малювання ліній за допомогою полотна, як показано нижче.

    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;
    }
}

1
Як щодо вільного малювання? А лінію намалювати, коли ви рухаєте пальцем?
Si8

1

Я думаю, що важливо додати щось, якщо ви використовуєте інфляцію макета, що конструктор у малюнку малюнка невірний, додайте ці конструктори в класі:

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

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

або система Android не зможе надути файл макета. Я сподіваюся, що це могло б допомогти.


0

Окрім відповіді Ішана, якщо ви хочете малювати програмно без взаємодії з користувачем, ви можете редагувати клас трохи так.

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;
}
}

А потім використовуйте як

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

Малювати програмно

drawingCanvas.moveCursorTo(70f, 70f) // Move the cursor (Define starting point)
drawingCanvas.makeLine(200f, 200f) // End point (To where you need to draw)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.