0

我使用位图,作为由部分组成的旋转表盘。意味着用户可以旋转位图。现在我想在 ImageView 上定义一个 singleTap 来导航到不同的部分。

我们可以通过motionevent x 和y 来做,但是section 的位置会动态变化。所以,这是不可能的。

有没有其他方法可以做到这一点?

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


     }

}
4

1 回答 1

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;
于 2012-11-03T14:54:41.987 回答