2013-08-01 3 views
0

Я пробую простой CustomView с холстом. Этот пользовательский вид просто меняет положение изображения значка на экране случайным образом, когда вызывается updatePosition(), и в моем намерении нужно перемещать изображение при перетаскивании, масштабировать на пинче ... и когда я касаюсь позиции на экране, должен появляться в щелкнув позицию.Canvas view crash application on touch events

Моя попытка это следовать

public class CustomView extends View { 

    Bitmap mBmp; 
    Random mRnd; 
    Paint mPaint; 

    private static final int INVALID_POINTER_ID = -1; 

    private float mPosX; 
    private float mPosY; 

    private float mLastTouchX; 
    private float mLastTouchY; 
    private int mActivePointerId = INVALID_POINTER_ID; 

    private ScaleGestureDetector mScaleDetector; 
    private float mScaleFactor = 1.f; 

    int w, h, bw, bh; 
    int px = -1, py = -1; 

    public CustomView(Context context) { 
     this(context, null, 0); 
     mBmp = BitmapFactory.decodeResource(context.getResources(), 
       R.drawable.icon); 

    } 

    public CustomView(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
     mScaleDetector = new ScaleGestureDetector(context, new ScaleListener()); 
    } 

    public CustomView(Context context, AttributeSet attrs) { 
     super(context, attrs, 0); 

     mBmp = BitmapFactory.decodeResource(context.getResources(), 
       R.drawable.icon); 
     bw = mBmp.getWidth(); 
     bh = mBmp.getHeight(); 
     mPaint = new Paint(); 
     mPaint.setColor(Color.CYAN); 
     mPaint.setAntiAlias(true); 
     mRnd = new Random(); 

    } 

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

     canvas.save(); 
     Log.d("DEBUG", "X: " + mPosX + " Y: " + mPosY); 
     canvas.translate(mPosX, mPosY); 
     canvas.scale(mScaleFactor, mScaleFactor); 

     if (px == -1 && py == -1) { 
      px = w/2 - bw/2; 
      py = h/2 - bh/2; 
     } 

     canvas.drawCircle(px + (bw/2), py + (bh/2), 70, mPaint); 
     canvas.drawBitmap(mBmp, px, py, null); 

     canvas.restore(); 

    } 

    public void updatePosition() { 
     px = mRnd.nextInt(w - bw); 
     py = mRnd.nextInt(h - bh); 
     invalidate(); 
    } 

    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
     w = MeasureSpec.getSize(widthMeasureSpec); 
     h = MeasureSpec.getSize(heightMeasureSpec); 
     setMeasuredDimension(w, h); 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent ev) { 
     mScaleDetector.onTouchEvent(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; 
      mActivePointerId = ev.getPointerId(0); 
      break; 
     } 

     case MotionEvent.ACTION_MOVE: { 
      final int pointerIndex = ev.findPointerIndex(mActivePointerId); 
      final float x = ev.getX(pointerIndex); 
      final float y = ev.getY(pointerIndex); 

      if (!mScaleDetector.isInProgress()) { 
       final float dx = x - mLastTouchX; 
       final float dy = y - mLastTouchY; 

       mPosX += dx; 
       mPosY += dy; 

       invalidate(); 
      } 

      mLastTouchX = x; 
      mLastTouchY = y; 

      break; 
     } 

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

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

     case MotionEvent.ACTION_POINTER_UP: { 
      final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; 
      final int pointerId = ev.getPointerId(pointerIndex); 
      if (pointerId == mActivePointerId) { 
       final int newPointerIndex = pointerIndex == 0 ? 1 : 0; 
       mLastTouchX = ev.getX(newPointerIndex); 
       mLastTouchY = ev.getY(newPointerIndex); 
       mActivePointerId = ev.getPointerId(newPointerIndex); 
      } 
      break; 
     } 
     } 

     return true; 
    } 

    private class ScaleListener extends 
      ScaleGestureDetector.SimpleOnScaleGestureListener { 
     @Override 
     public boolean onScale(ScaleGestureDetector detector) { 
      mScaleFactor *= detector.getScaleFactor(); 

      // Don't let the object get too small or too large. 
      mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 10.0f)); 

      invalidate(); 
      return true; 
     } 
    } 

} 

updatePosition() слушатель работает в то время как onTouchListener причиной аварии приложения с NullPointerException при попытке перетащить изображение или коснитесь любого положения экрана

Могли кто-нибудь Помогите мне? Спасибо

ответ

1

Похоже, что mScaleDetector инициализируется только в одном из конструкторов. Он должен быть инициализирован во всех конструкторах. Общий шаблон состоит в том, чтобы создать метод init() и поместить все, что вы инициализируете, затем вызвать этот метод из всех конструкторов.

Примечание: всегда полезно размещать StackTrace ... Вы должны уметь видеть, какой конструктор вызван.

+1

В качестве альтернативы просто переместите конструкторы с помощью 'this()', как в первом, и переместите всю инициализацию на самую полную (взяв 3 параметра). – Delyan

+0

Спасибо. Я следил за вашим предложением, и теперь перетаскивание работает без какого-либо сбоя, но изображение не появляется в прикосновенном положении, перемещается только при перетаскивании, я также хочу, чтобы * телепортировался * в прикосновенном положении – AndreaF

+0

@AndreaF вам следует создайте еще один вопрос для этой проблемы. – JRomero