2013-07-24 29 views
14

Kullanıcının tuval üzerine bir daire çizmesine ve sürüklemesine izin vermesi gereken bir Android uygulamasında çalışıyorum. Üzerinde çizgiler ve daireler çizebildim. Ancak bunu sürükleyemiyorum.Tuval üzerinde çizilmiş bir daireyi sürükleyip taşıma

Android'de tuval üzerine çizilmiş bir nesneyi sürüklemek mümkün mü? Örneğin, daire içinde bir dokunuş tespit edersem, daireyi önceki konumdan nasıl silebilirim ve geçerli konuma nasıl taşırım? invalidate()'u denedim. Ancak, kullanıcı birden çok daire çizmiş ve hepsini taşımak istiyorsa işe yaramaz.

+0

Çizilmiş daireler hakkında nasıl bilgi depolarsınız? Kesin daireler mi (drawCircle() ile çizilmiş)? – sandrstar

+0

Merkezin ve yarıçapın X, Y koordinatlarını saklayan daire için bir fasulye sınıfı yaratılır. – Shravz

+1

Bazı kodlar yararlı olabilir. OnDraw() yönteminde bu 'daireler'i saklayan ve çizen bir çeşit çizim görünümünüz olduğunu varsayalım. Eğer öyleyse, invalidate() çalışmalıdır (bu soruda olduğu gibi tek bir daire ile http://stackoverflow.com/q/17289576/657487). Ben haklı mıyım Birden çok dokunma işaretçisi ile sorun mu var? – sandrstar

cevap

35

Çoklu dokunma/çizim işlemiyle ilgili sorunlarınız olabilir. Android Developer site ve Android Blog ile ilgili bazı yararlı dersler var.

ben o Sen ulaşmaya çalışıyor oldukça benzer düşünmek bir örnek oluşturmak başardı Buna dayanarak (komple daire çizim olmadan - çevreler tek dokunuşla tarafından oluşturulan olsun):

public class CirclesDrawingView extends View { 

    private static final String TAG = "CirclesDrawingView"; 

    /** Main bitmap */ 
    private Bitmap mBitmap = null; 

    private Rect mMeasuredRect; 

    /** Stores data about single circle */ 
    private static class CircleArea { 
     int radius; 
     int centerX; 
     int centerY; 

     CircleArea(int centerX, int centerY, int radius) { 
      this.radius = radius; 
      this.centerX = centerX; 
      this.centerY = centerY; 
     } 

     @Override 
     public String toString() { 
      return "Circle[" + centerX + ", " + centerY + ", " + radius + "]"; 
     } 
    } 

    /** Paint to draw circles */ 
    private Paint mCirclePaint; 

    private final Random mRadiusGenerator = new Random(); 
    // Radius limit in pixels 
    private final static int RADIUS_LIMIT = 100; 

    private static final int CIRCLES_LIMIT = 3; 

    /** All available circles */ 
    private HashSet<CircleArea> mCircles = new HashSet<CircleArea>(CIRCLES_LIMIT); 
    private SparseArray<CircleArea> mCirclePointer = new SparseArray<CircleArea>(CIRCLES_LIMIT); 

    /** 
    * Default constructor 
    * 
    * @param ct {@link android.content.Context} 
    */ 
    public CirclesDrawingView(final Context ct) { 
     super(ct); 

     init(ct); 
    } 

    public CirclesDrawingView(final Context ct, final AttributeSet attrs) { 
     super(ct, attrs); 

     init(ct); 
    } 

    public CirclesDrawingView(final Context ct, final AttributeSet attrs, final int defStyle) { 
     super(ct, attrs, defStyle); 

     init(ct); 
    } 

    private void init(final Context ct) { 
     // Generate bitmap used for background 
     mBitmap = BitmapFactory.decodeResource(ct.getResources(), R.drawable.up_image); 

     mCirclePaint = new Paint(); 

     mCirclePaint.setColor(Color.BLUE); 
     mCirclePaint.setStrokeWidth(40); 
     mCirclePaint.setStyle(Paint.Style.FILL); 
    } 

    @Override 
    public void onDraw(final Canvas canv) { 
     // background bitmap to cover all area 
     canv.drawBitmap(mBitmap, null, mMeasuredRect, null); 

     for (CircleArea circle : mCircles) { 
      canv.drawCircle(circle.centerX, circle.centerY, circle.radius, mCirclePaint); 
     } 
    } 

    @Override 
    public boolean onTouchEvent(final MotionEvent event) { 
     boolean handled = false; 

     CircleArea touchedCircle; 
     int xTouch; 
     int yTouch; 
     int pointerId; 
     int actionIndex = event.getActionIndex(); 

     // get touch event coordinates and make transparent circle from it 
     switch (event.getActionMasked()) { 
      case MotionEvent.ACTION_DOWN: 
       // it's the first pointer, so clear all existing pointers data 
       clearCirclePointer(); 

       xTouch = (int) event.getX(0); 
       yTouch = (int) event.getY(0); 

       // check if we've touched inside some circle 
       touchedCircle = obtainTouchedCircle(xTouch, yTouch); 
       touchedCircle.centerX = xTouch; 
       touchedCircle.centerY = yTouch; 
       mCirclePointer.put(event.getPointerId(0), touchedCircle); 

       invalidate(); 
       handled = true; 
       break; 

      case MotionEvent.ACTION_POINTER_DOWN: 
       Log.w(TAG, "Pointer down"); 
       // It secondary pointers, so obtain their ids and check circles 
       pointerId = event.getPointerId(actionIndex); 

       xTouch = (int) event.getX(actionIndex); 
       yTouch = (int) event.getY(actionIndex); 

       // check if we've touched inside some circle 
       touchedCircle = obtainTouchedCircle(xTouch, yTouch); 

       mCirclePointer.put(pointerId, touchedCircle); 
       touchedCircle.centerX = xTouch; 
       touchedCircle.centerY = yTouch; 
       invalidate(); 
       handled = true; 
       break; 

      case MotionEvent.ACTION_MOVE: 
       final int pointerCount = event.getPointerCount(); 

       Log.w(TAG, "Move"); 

       for (actionIndex = 0; actionIndex < pointerCount; actionIndex++) { 
        // Some pointer has moved, search it by pointer id 
        pointerId = event.getPointerId(actionIndex); 

        xTouch = (int) event.getX(actionIndex); 
        yTouch = (int) event.getY(actionIndex); 

        touchedCircle = mCirclePointer.get(pointerId); 

        if (null != touchedCircle) { 
         touchedCircle.centerX = xTouch; 
         touchedCircle.centerY = yTouch; 
        } 
       } 
       invalidate(); 
       handled = true; 
       break; 

      case MotionEvent.ACTION_UP: 
       clearCirclePointer(); 
       invalidate(); 
       handled = true; 
       break; 

      case MotionEvent.ACTION_POINTER_UP: 
       // not general pointer was up 
       pointerId = event.getPointerId(actionIndex); 

       mCirclePointer.remove(pointerId); 
       invalidate(); 
       handled = true; 
       break; 

      case MotionEvent.ACTION_CANCEL: 
       handled = true; 
       break; 

      default: 
       // do nothing 
       break; 
     } 

     return super.onTouchEvent(event) || handled; 
    } 

    /** 
    * Clears all CircleArea - pointer id relations 
    */ 
    private void clearCirclePointer() { 
     Log.w(TAG, "clearCirclePointer"); 

     mCirclePointer.clear(); 
    } 

    /** 
    * Search and creates new (if needed) circle based on touch area 
    * 
    * @param xTouch int x of touch 
    * @param yTouch int y of touch 
    * 
    * @return obtained {@link CircleArea} 
    */ 
    private CircleArea obtainTouchedCircle(final int xTouch, final int yTouch) { 
     CircleArea touchedCircle = getTouchedCircle(xTouch, yTouch); 

     if (null == touchedCircle) { 
      touchedCircle = new CircleArea(xTouch, yTouch, mRadiusGenerator.nextInt(RADIUS_LIMIT) + RADIUS_LIMIT); 

      if (mCircles.size() == CIRCLES_LIMIT) { 
       Log.w(TAG, "Clear all circles, size is " + mCircles.size()); 
       // remove first circle 
       mCircles.clear(); 
      } 

      Log.w(TAG, "Added circle " + touchedCircle); 
      mCircles.add(touchedCircle); 
     } 

     return touchedCircle; 
    } 

    /** 
    * Determines touched circle 
    * 
    * @param xTouch int x touch coordinate 
    * @param yTouch int y touch coordinate 
    * 
    * @return {@link CircleArea} touched circle or null if no circle has been touched 
    */ 
    private CircleArea getTouchedCircle(final int xTouch, final int yTouch) { 
     CircleArea touched = null; 

     for (CircleArea circle : mCircles) { 
      if ((circle.centerX - xTouch) * (circle.centerX - xTouch) + (circle.centerY - yTouch) * (circle.centerY - yTouch) <= circle.radius * circle.radius) { 
       touched = circle; 
       break; 
      } 
     } 

     return touched; 
    } 

    @Override 
    protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { 
     super.onMeasure(widthMeasureSpec, heightMeasureSpec); 

     mMeasuredRect = new Rect(0, 0, getMeasuredWidth(), getMeasuredHeight()); 
    } 
} 

Aktivite içeriyor yalnızca setContentView(R.layout.main) orada main.xml şudur:

<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_height="match_parent" 
    android:layout_width="match_parent" 
    android:id="@+id/scroller"> 
    <com.example.TestApp.CirclesDrawingView 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" /> 
</RelativeLayout> 
+0

Benzer problemde sıkışmış durumdayım, bunu uygulamaya çalışıyorum. Parmak Geçti. –

+0

Bu kodu uygularken bu hataları alıyorum http://pastebin.com/4mHdHh6W: –

+0

Sorunlar şimdi çözüldü. –

İlgili konular