如何在画布上用多根手指绘制 [英] How to draw with multiple fingers in canvas

查看:106
本文介绍了如何在画布上用多根手指绘制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在通过创建绘图应用程序使用android Canvas类.这是我第一次尝试使用Canvas类.到目前为止,我使用的代码工作正常,工程图工作正常.但是我在这段代码中意识到的是,它只允许用户用一根手指画画,我的意思是说,如果用户用了一根手指以上在画布上画画,则不允许用户用多根手指画画.我浏览了有关多点触摸事件的多个文档,但是未能在我的代码中实现它.任何人都可以帮助我解决这个问题.

I am using android Canvas class from creating drawing application. This is my first attempt to work with Canvas class. So far the code that i used is working fine and the drawing is working fine. But what i realized in this code is that, it allow user to draw with one finger only, i mean to say if the user used more then one finger to draw on canvas it doesn't allow the user to draw with multiple finger. I go through several documentation regarding multiple touch event but failed to implement it in my code. So can anyone help me to figure this out.

我用于在画布上绘制的代码是

public class DrawView extends View implements OnTouchListener 
{
    private Canvas      m_Canvas;

    private Path        m_Path;

    private Paint       m_Paint;

    ArrayList<Pair<Path, Paint>> arrayListPaths = new ArrayList<Pair<Path, Paint>>();

    ArrayList<Pair<Path, Paint>> undonePaths = new ArrayList<Pair<Path, Paint>>(); 

    private float mX, mY;

    private Bitmap bitmapToCanvas;

    private static final float TOUCH_TOLERANCE = 4;

    public DrawView(Context context) 
    {
        super(context);
        setFocusable(true);
        setFocusableInTouchMode(true);      
        this.setOnTouchListener(this);

        onCanvasInitialization();
    }      

    public void onCanvasInitialization()
    {
        m_Paint = new Paint();
        m_Paint.setAntiAlias(true);
        m_Paint.setDither(true);
        m_Paint.setColor(Color.parseColor("#37A1D1"));
        m_Paint.setStyle(Paint.Style.STROKE);
        m_Paint.setStrokeJoin(Paint.Join.ROUND);
        m_Paint.setStrokeCap(Paint.Cap.ROUND);
        m_Paint.setStrokeWidth(2);      

        m_Path = new Path();    
    }

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

        bitmapToCanvas = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        m_Canvas = new Canvas(bitmapToCanvas);
    }

    @Override
    protected void onDraw(Canvas canvas)
    {    
        canvas.drawBitmap(bitmapToCanvas, 0f, 0f, null);
        canvas.drawPath(m_Path, m_Paint);
    }

    public boolean onTouch(View arg0, 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 void touch_start(float x, float y) 
    {
        undonePaths.clear();
        m_Path.reset();
        m_Path.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) 
        {
            m_Path.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
            mX = x;
            mY = y;
        }
    }
    private void touch_up() 
    {
        m_Path.lineTo(mX, mY);

        // commit the path to our offscreen
        m_Canvas.drawPath(m_Path, m_Paint);

        // kill this so we don't double draw                    
        Paint newPaint = new Paint(m_Paint); // Clones the mPaint object
        arrayListPaths.add(new Pair<Path, Paint>(m_Path, newPaint));
        m_Path = new Path();
    }
}

我尝试在代码中进行更改以支持多点触控,但是它无法正常工作.这是我的更改代码 http://pastebin.com/W6qvpYGW .

I tried making changes in my code to support multiple touch, but it doesn't work properly. This is my change code http://pastebin.com/W6qvpYGW.

推荐答案

请参见具有多点触控功能,对我很有帮助.它阐述了如何处理多点触摸

See Making Sense of Multitouch, it helped me a lot. It explanes how to handle multi touches

要记住的要点

1.确保已打开action & MotionEvent.ACTION_MASK

2.如果要同时绘制多条线,请遵循MotionEvent.ACTION_POINTER_DOWN中每个指针的PointerId,并通过比较指针ID在MotionEvent.ACTION_POINTER_UP中释放它.

2.if you want to draw multiple lines at same time, follow PointerId of each pointer which comes in MotionEvent.ACTION_POINTER_DOWN and release it in MotionEvent.ACTION_POINTER_UP by comparing pointer ids.

private static final int INVALID_POINTER_ID = -1;

// The ‘active pointer’ is the one currently moving our object.
private int mActivePointerId = INVALID_POINTER_ID;

// Existing code ...

@Override
public boolean onTouchEvent(MotionEvent ev) {
    final int action = ev.getAction();
    switch (action & MotionEvent.ACTION_MASK) {
    case MotionEvent.ACTION_DOWN: {
        final float x = ev.getX();
        final float y = ev.getY();

        mLastTouchX = x;
        mLastTouchY = y;

        // Save the ID of this pointer
        mActivePointerId = ev.getPointerId(0);
        break;
    }

    case MotionEvent.ACTION_MOVE: {
        // Find the index of the active pointer and fetch its position
        final int pointerIndex = ev.findPointerIndex(mActivePointerId);
        final float x = ev.getX(pointerIndex);
        final float y = ev.getY(pointerIndex);

        final float dx = x - mLastTouchX;
        final float dy = y - mLastTouchY;

        mPosX += dx;
        mPosY += dy;

        mLastTouchX = x;
        mLastTouchY = y;

        invalidate();
        break;
    }

    case MotionEvent.ACTION_UP: {
        mActivePointerId = INVALID_POINTER_ID;
        break;
    }

    case MotionEvent.ACTION_CANCEL: {
        mActivePointerId = INVALID_POINTER_ID;
        break;
    }

    case MotionEvent.ACTION_POINTER_UP: {
        // Extract the index of the pointer that left the touch sensor
        final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) 
                >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
        final int pointerId = ev.getPointerId(pointerIndex);
        if (pointerId == mActivePointerId) {
            // This was our active pointer going up. Choose a new
            // active pointer and adjust accordingly.
            final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
            mLastTouchX = ev.getX(newPointerIndex);
            mLastTouchY = ev.getY(newPointerIndex);
            mActivePointerId = ev.getPointerId(newPointerIndex);
        }
        break;
    }
    }

    return true;
}

修改

请参阅此代码...仍然存在一些问题,但是我认为您可以调试并修复这些问题...而且逻辑不存在,请执行以下操作……

Please see this code... This still has some issues but i think you can debug it and fix those ... Also the logic is not there persisting lines please implement that...

package com.example.stackgmfdght;

import java.util.ArrayList;


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.util.Pair;
import android.view.MotionEvent;
import android.view.View;

public class JustDoIt extends View
{
    private Canvas          m_Canvas;

 //   private Path            m_Path;

    int current_path_count=-1; 
    ArrayList <Path> m_Path_list =  new ArrayList<Path>();
    ArrayList <Float> mX_list =  new ArrayList<Float>();
    ArrayList <Float> mY_list =  new ArrayList<Float>();
    ArrayList <Integer> mActivePointerId_list =  new ArrayList<Integer>();

    private Paint       m_Paint;

    ArrayList<Pair<Path, Paint>> arrayListPaths = new ArrayList<Pair<Path, Paint>>();

    //ArrayList<Pair<Path, Paint>> undonePaths = new ArrayList<Pair<Path, Paint>>();

    private float mX, mY;

    private Bitmap bitmapToCanvas;

    private static final float TOUCH_TOLERANCE = 4;

    public JustDoIt (Context context)
    {
            super(context);
            setFocusable(true);
            setFocusableInTouchMode(true);      

            onCanvasInitialization();
    }     

    public JustDoIt(Context context, AttributeSet attributeSet) {
        super(context, attributeSet);
        setFocusable(true);
        setFocusableInTouchMode(true);      

        onCanvasInitialization();
    }

    public void onCanvasInitialization()
    {
            m_Paint = new Paint();
            m_Paint.setAntiAlias(true);
            m_Paint.setDither(true);
            m_Paint.setColor(Color.parseColor("#37A1D1"));
            m_Paint.setStyle(Paint.Style.STROKE);
            m_Paint.setStrokeJoin(Paint.Join.ROUND);
            m_Paint.setStrokeCap(Paint.Cap.ROUND);
            m_Paint.setStrokeWidth(2);            

         //   m_Path = new Path();  
    }

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

            bitmapToCanvas = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
            m_Canvas = new Canvas(bitmapToCanvas);
    }

    @Override
    protected void onDraw(Canvas canvas)
    {    
            canvas.drawBitmap(bitmapToCanvas, 0f, 0f, null);
            for(int i=0;i<=current_path_count;i++)
            {
            canvas.drawPath(m_Path_list.get(i), m_Paint);
            }
    }


    public void onDrawCanvas()
    {
            for (Pair<Path, Paint> p : arrayListPaths)
            {
                m_Canvas.drawPath(p.first, p.second);
            }
    }

    private static final int INVALID_POINTER_ID = -1;

    // The ‘active pointer’ is the one currently moving our object.
    private int mActivePointerId = INVALID_POINTER_ID;



    @Override
    public boolean onTouchEvent(MotionEvent event)
    {
            super.onTouchEvent(event);

            final int action = event.getAction();  

            switch (action & MotionEvent.ACTION_MASK)
            {
                    case MotionEvent.ACTION_DOWN:
                    {
                            float x = event.getX();
                            float y = event.getY();


                            current_path_count=0;
                            mActivePointerId_list.add ( event.getPointerId(0),current_path_count);                                              
                            touch_start((x ),(y ),current_path_count );
                    }
                    break;

                    case MotionEvent.ACTION_POINTER_DOWN:
                    {

           if(event.getPointerCount()>current_path_count)
           {

                            current_path_count++;
                            float x = event.getX(current_path_count);
                            float y = event.getY(current_path_count);


                            mActivePointerId_list.add ( event.getPointerId(current_path_count),current_path_count);                                              
                                touch_start((x ),(y ),current_path_count);  
           } 
                    }
                    break;

                    case MotionEvent.ACTION_MOVE:
                    {
                         for(int i=0;i<=current_path_count;i++)
                         { try{
                                     int pointerIndex = event
                                    .findPointerIndex(mActivePointerId_list.get(i));

                                    float x = event.getX(pointerIndex);
                                    float y = event.getY(pointerIndex);

                                    touch_move((x ),(y ),i);
                         }
                         catch(Exception e)
                         {
                             e.printStackTrace();
                         }
                         }


                    }
                    break;

                    case MotionEvent.ACTION_UP:
                    { current_path_count=-1; 
                         for(int i=0;i<=current_path_count;i++)
                         {

                                    touch_up(i);
                         }
                         mActivePointerId_list =  new ArrayList<Integer>();


                    }
                    break;

                    case MotionEvent.ACTION_CANCEL:
                    {
                            mActivePointerId = INVALID_POINTER_ID;  
                            current_path_count=-1; 
                    }
                    break;

                    case MotionEvent.ACTION_POINTER_UP:
                    {
                            final int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
                            final int pointerId = event.getPointerId(pointerIndex);
                            for(int i=0;i<=current_path_count;i++)
                         {
                            if (pointerId == mActivePointerId_list.get(i))
                            {
                                    // This was our active pointer going up. Choose a new
                                    // active pointer and adjust accordingly.

                                     mActivePointerId_list.remove(i);
                                    touch_up(i);
                                    break;
                            }              
                         }
                    }    
                    break;

                    case MotionEvent.ACTION_OUTSIDE:
                    break;
    }

    invalidate();
    return true;
}

    private void touch_start(float x, float y, int count)
    {
        //    undonePaths.clear();
           Path  m_Path=new Path();

           m_Path_list.add(count,m_Path);

           m_Path_list.get(count).reset();


           m_Path_list.get(count).moveTo(x, y);

            mX_list.add(count,x);
            mY_list.add(count,y);

    }

    private void touch_move(float x, float y,int count)
    {
            float dx = Math.abs(x - mX_list.get(count));
            float dy = Math.abs(y - mY_list.get(count));
            if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE)
            {
                    m_Path_list.get(count).quadTo(mX_list.get(count), mY_list.get(count), (x + mX_list.get(count))/2, (y + mY_list.get(count))/2);
                    try{

                        mX_list.remove(count);
                        mY_list.remove(count);
                        }
                        catch(Exception e)
                        {
                           e.printStackTrace();
                        }
                    mX_list.add(count,x);
                    mY_list.add(count,y);
            }
    }
    private void touch_up(int count)
    {
         m_Path_list.get(count).lineTo(mX_list.get(count), mY_list.get(count));

            // commit the path to our offscreen
            m_Canvas.drawPath( m_Path_list.get(count), m_Paint);

            // kill this so we don't double draw                          
            Paint newPaint = new Paint(m_Paint); // Clones the mPaint object
            arrayListPaths.add(new Pair<Path, Paint>( m_Path_list.get(count), newPaint));
            m_Path_list.remove(count);
            mX_list.remove(count);
            mY_list.remove(count);
    }
}

这篇关于如何在画布上用多根手指绘制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆