2012-08-30 66 views
0

我正在使用位圖,它是由部分組成的旋轉撥號。意思是用戶可以旋轉位圖。現在我想在ImageView上定義一個用於導航到不同部分的單選按鈕。在位圖Android上觸摸監聽器(Overlay以使位圖部分可點擊)

我們可以通過motionevent x和y來完成,但部分的位置會動態變化。所以,這是不可能的。

有沒有其他方法可以做到這一點?

public class TutorialActivity extends Activity { 

    private static Bitmap imageOriginal, imageScaled; 
    private static Matrix matrix; 

    private ImageView dialer; 
    private int dialerHeight, dialerWidth; 

    private GestureDetector detector; 

    // needed for detecting the inversed rotations 
    private boolean[] quadrantTouched; 

    private boolean allowRotating; 
    View viewNew; 


    Button aboutus,profile,colleagues,picasa,facebook,twitter,youtube,referral; 

    int one_piecewidth,one_pieceheight; 

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


     this.requestWindowFeature(Window.FEATURE_NO_TITLE); 
     this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 
       WindowManager.LayoutParams.FLAG_FULLSCREEN); 

     setContentView(R.layout.main); 

     // initialize the matrix only once 
     if (matrix == null) { 
      matrix = new Matrix(); 
     } else { 
      // not needed, you can also post the matrix immediately to restore the old state 
      matrix.reset(); 
     } 

     detector = new GestureDetector(this, new MyGestureDetector()); 

     // there is no 0th quadrant, to keep it simple the first value gets ignored 
     quadrantTouched = new boolean[] { false, false, false, false, false }; 

     allowRotating = true; 

     //viewNew=LayoutInflater.from(TutorialActivity.this).inflate(R.layout.new_view,null,false); 
     // load the image only once 

     if(imageOriginal==null){ 
      //imageOriginal=loadBitmapFromView(viewNew); 
      imageOriginal=BitmapFactory.decodeResource(getResources(), R.drawable.circular_menu); 
     } 

     imageScaled=imageOriginal; 
     one_piecewidth=((int) imageOriginal.getWidth()/4); 
     one_pieceheight=((int) imageOriginal.getHeight()/4); 


     dialer = (ImageView) findViewById(R.id.imageView_ring); 
     dialer.setImageBitmap(imageOriginal); 


     dialer.setOnTouchListener(new MyOnTouchListener()); 
     dialer.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() { 

      @Override 
      public void onGlobalLayout() { 
       // method called more than once, but the values only need to be initialized one time 
       if (dialerHeight == 0 || dialerWidth == 0) { 
        dialerHeight = dialer.getHeight(); 
        dialerWidth = dialer.getWidth(); 

        // resize 
        Matrix resize = new Matrix(); 
        resize.postScale((float)Math.min(dialerWidth, dialerHeight)/(float)imageOriginal.getWidth(), (float)Math.min(dialerWidth, dialerHeight)/(float)imageOriginal.getHeight()); 
        imageScaled = Bitmap.createBitmap(imageOriginal, 0, 0, imageOriginal.getWidth(), imageOriginal.getHeight(), resize, false); 

        // translate to the image view's center 
        float translateX = dialerWidth/2 - imageScaled.getWidth()/2; 
        float translateY = dialerHeight/2 - imageScaled.getHeight()/2; 
        matrix.postTranslate(translateX, translateY); 

        dialer.setImageBitmap(imageScaled); 
        dialer.setImageMatrix(matrix); 
       } 
      } 
     }); 

    } 

    /** 
    * Rotate the dialer. 
    * 
    * @param degrees The degrees, the dialer should get rotated. 
    */ 
    private void rotateDialer(float degrees) { 
     matrix.postRotate(degrees, dialerWidth/2, dialerHeight/2); 

     dialer.setImageMatrix(matrix); 
     //viewNew.po 

    } 

    /** 
    * @return The angle of the unit circle with the image view's center 
    */ 
    private double getAngle(double xTouch, double yTouch) { 
     double x = xTouch - (dialerWidth/2d); 
     double y = dialerHeight - yTouch - (dialerHeight/2d); 

     switch (getQuadrant(x, y)) { 
      case 1: 
       return Math.asin(y/Math.hypot(x, y)) * 180/Math.PI; 

      case 2: 
      case 3: 
       return 180 - (Math.asin(y/Math.hypot(x, y)) * 180/Math.PI); 

      case 4: 
       return 360 + Math.asin(y/Math.hypot(x, y)) * 180/Math.PI; 

      default: 
       // ignore, does not happen 
       return 0; 
     } 
    } 

    /** 
    * @return The selected quadrant. 
    */ 
    private static int getQuadrant(double x, double y) { 
     if (x >= 0) { 
      return y >= 0 ? 1 : 4; 
     } else { 
      return y >= 0 ? 2 : 3; 
     } 
    } 

    /** 
    * Simple implementation of an {@link OnTouchListener} for registering the dialer's touch events. 
    */ 
    private class MyOnTouchListener implements OnTouchListener { 

     private double startAngle; 

     @Override 
     public boolean onTouch(View v, MotionEvent event) { 

      switch (event.getAction()) { 

       case MotionEvent.ACTION_DOWN: 

        // reset the touched quadrants 
        for (int i = 0; i < quadrantTouched.length; i++) { 
         quadrantTouched[i] = false; 
        } 

        allowRotating = false; 

        startAngle = getAngle(event.getX(), event.getY()); 

        Drawable drawable = dialer.getDrawable(); 
        Rect imageBounds = drawable.getBounds(); 

        //original height and width of the bitmap 
        int intrinsicHeight = drawable.getIntrinsicHeight(); 
        int intrinsicWidth = drawable.getIntrinsicWidth(); 

        //height and width of the visible (scaled) image 
        int scaledHeight = imageBounds.height(); 
        int scaledWidth = imageBounds.width(); 

        //Find the ratio of the original image to the scaled image 
        //Should normally be equal unless a disproportionate scaling 
        //(e.g. fitXY) is used. 
        float heightRatio = intrinsicHeight/scaledHeight; 
        float widthRatio = intrinsicWidth/scaledWidth; 

        //do whatever magic to get your touch point 
        //MotionEvent event; 

        //get the distance from the left and top of the image bounds 
        int scaledImageOffsetX = (int) (event.getX() - imageBounds.left); 
        int scaledImageOffsetY = (int) (event.getY() - imageBounds.top); 

        //scale these distances according to the ratio of your scaling 
        //For example, if the original image is 1.5x the size of the scaled 
        //image, and your offset is (10, 20), your original image offset 
        //values should be (15, 30). 
        int originalImageOffsetX = (int) (scaledImageOffsetX * widthRatio); 
        int originalImageOffsetY = (int) (scaledImageOffsetY * heightRatio); 


        break; 

       case MotionEvent.ACTION_MOVE: 
        double currentAngle = getAngle(event.getX(), event.getY()); 
       if((float) (startAngle - currentAngle)>1.0) 
        rotateDialer((float) (startAngle - currentAngle)); 
        startAngle = currentAngle; 
        break; 

       case MotionEvent.ACTION_UP: 
        allowRotating = true; 
        break; 
      } 

      // set the touched quadrant to true 
      quadrantTouched[getQuadrant(event.getX() - (dialerWidth/2), dialerHeight - event.getY() - (dialerHeight/2))] = true; 

      detector.onTouchEvent(event); 

      return true; 
     } 
    } 

    /** 
    * Simple implementation of a {@link SimpleOnGestureListener} for detecting a fling event. 
    */ 
    private class MyGestureDetector extends SimpleOnGestureListener { 
     @Override 
     public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { 

      // get the quadrant of the start and the end of the fling 
      int q1 = getQuadrant(e1.getX() - (dialerWidth/2), dialerHeight - e1.getY() - (dialerHeight/2)); 
      int q2 = getQuadrant(e2.getX() - (dialerWidth/2), dialerHeight - e2.getY() - (dialerHeight/2)); 

      System.out.println("q1 and q2"+q1+".."+q2); 

      // the inversed rotations 
      if ((q1 == 2 && q2 == 2 && Math.abs(velocityX) < Math.abs(velocityY)) 
        || (q1 == 3 && q2 == 3) 
        || (q1 == 1 && q2 == 3) 
        || (q1 == 4 && q2 == 4 && Math.abs(velocityX) > Math.abs(velocityY)) 
        || ((q1 == 2 && q2 == 3) || (q1 == 3 && q2 == 2)) 
        || ((q1 == 3 && q2 == 4) || (q1 == 4 && q2 == 3)) 
        || (q1 == 2 && q2 == 4 && quadrantTouched[3]) 
        || (q1 == 4 && q2 == 2 && quadrantTouched[3])) { 

       dialer.post(new FlingRunnable(-1 * (velocityX + velocityY))); 
      } else { 
       // the normal rotation 
       dialer.post(new FlingRunnable(velocityX + velocityY)); 
      } 

      return true; 
     } 

      @Override 
      public boolean onSingleTapUp(MotionEvent e){ 


       int pixel = imageScaled.getPixel((int)(e.getX()),(int)(e.getY())); 
       System.out.println("pixel"+pixel+"..."); 

       return true; 

      } 
    } 

    /** 
    * A {@link Runnable} for animating the the dialer's fling. 
    */ 
    private class FlingRunnable implements Runnable { 

     private float velocity; 

     public FlingRunnable(float velocity) { 
      this.velocity = velocity; 
     } 

     @Override 
     public void run() { 
      if (Math.abs(velocity) > 5 && allowRotating) { 
       rotateDialer(velocity/75); 
       velocity /= 1.0666F; 

       // post this instance again 
       dialer.post(this); 
      } 
     } 
    } 

    public static Bitmap loadBitmapFromView(View v) { 

     System.out.println("vvv"+v+"...."); 
     System.out.println("vvvparams"+v.getMeasuredHeight()+"...."); 
     // System.out.println("vvvparamswidth"+v.getLayoutParams().height+"...."); 
      Bitmap b = Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888);     
      Canvas c = new Canvas(b); 
      v.layout(0, 0, 300, 300); 
      v.draw(c); 
      return b; 
     } 

    public Bitmap addView(View v) { 
     v.setDrawingCacheEnabled(true); 

     // this is the important code :) 
     // Without it the view will have a dimension of 0,0 and the bitmap will be null 

     System.out.println("mesaure spec"+MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); 
     v.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), 
        MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); 
     v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight()); 

     v.buildDrawingCache(true); 
     Bitmap b = Bitmap.createBitmap(v.getDrawingCache()); 
     v.setDrawingCacheEnabled(false); 
     return b;// clear drawing cache 
    } 

    public void onResume(){ 
     super.onResume(); 


    } 

} 

回答

0

添加觸摸事件的代碼:

  {  
      case MotionEvent.ACTION_DOWN: 

      start = e.getEventTime(); 

       break; 

      case MotionEvent.ACTION_MOVE: 

      case MotionEvent.ACTION_UP: 
       stop = e.getEventTime(); 
       break; 
     } 
     //delay or use thread 
     if (stop - start > 1500) { 
      //your code 
     } 

     return true; 
+0

你能提供這個答案更多的環境? – afuzzyllama

+0

當手指向下時手指向下(手指向下)和同樣的事情會發生。如果觸摸並保持1.5s或更大,如果塊被執行 –