android - 以有限度数旋转表盘

标签 android android-canvas android-imageview android-button image-rotation

所有
我想以特定角度旋转图像,如下图所示。我有旋转代码,但它可以旋转 360 度,但我只希望它旋转特定的度数,并获得位于表盘上方的选定数字。

enter image description here


下面是我的代码。 我的自定义查看此工作正常但性能不足。

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector.OnGestureListener;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;

public class MyDialView extends View implements OnGestureListener{
    private static Bitmap bimmap;
    private static Paint paint;
    private static Rect bounds;
    private int totalNicks = 100;
    private int currentNick = 0;
    private GestureDetector gestureDetector;
    private float dragStartDeg = Float.NaN;
    float dialerWidth = 0,dialerHeight = 0;

    private static Paint createDefaultPaint() {
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setFilterBitmap(true);
        return paint;
    }
    private float xyToDegrees(float x, float y) {
        float distanceFromCenter = PointF.length((x - 0.5f), (y - 0.5f));
        if (distanceFromCenter < 0.1f
                || distanceFromCenter > 0.5f) { // ignore center and out of bounds events
            return Float.NaN;
        } else {
            return (float) Math.toDegrees(Math.atan2(x - 0.5f, y - 0.5f));
        }
    }
    public final float getRotationInDegrees() {
        return (360.0f / totalNicks) * currentNick;
    }

    public final void rotate(int nicks) {
        currentNick = (currentNick + nicks);
        if (currentNick >= totalNicks) {
            currentNick %= totalNicks;
        } else if (currentNick < 0) {
            currentNick = (totalNicks + currentNick);
        }
        Log.e("Current nick", String.valueOf(currentNick));
        if((currentNick > 80 || currentNick < 20)){
            invalidate();
        }
    }
    public MyDialView(Context context, AttributeSet attrs) {
        super(context, attrs);
        bimmap = BitmapFactory.decodeResource(context.getResources(),R.drawable.out_round);
        paint = createDefaultPaint();
        gestureDetector = new GestureDetector(getContext(), this);
        dialerWidth = bimmap.getWidth() /2.0f;
        dialerHeight = bimmap.getHeight() / 2.0f;
        bounds = new Rect();
    }



    @Override
    protected void onDraw(Canvas canvas) {
        canvas.getClipBounds(bounds);
            canvas.save(Canvas.MATRIX_SAVE_FLAG);
            //{
                canvas.translate(bounds.left, bounds.top);

                float rotation = getRotationInDegrees();
                canvas.rotate(rotation, dialerWidth, dialerHeight);
                canvas.drawBitmap(bimmap, 0,0,null);
                //canvas.rotate(- rotation, dialerWidth, dialerHeight);
            //}     
            canvas.restore();
    }
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (gestureDetector.onTouchEvent(event)) {
            return true;
        } else {
            return super.onTouchEvent(event);
        }
    }
    //Gesture detector methods
    @Override
    public boolean onDown(MotionEvent e) {
        float x = e.getX() / ((float) getWidth());
        float y = e.getY() / ((float) getHeight());

        dragStartDeg = xyToDegrees(x, y);
        //Log.d("deg = " , ""+dragStartDeg);
        if (! Float.isNaN(dragStartDeg)) {
            return true;
        } else {
            return false;
        }
    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
            float velocityY) {
        return false;
    }

    @Override
    public void onLongPress(MotionEvent e) {

    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
            float distanceY) {
        if (! Float.isNaN(dragStartDeg)) {
            float currentDeg = xyToDegrees(e2.getX() / getWidth(), 
                    e2.getY() / getHeight());

            if (! Float.isNaN(currentDeg)) {
                float degPerNick = 360.0f / totalNicks;
                float deltaDeg = dragStartDeg - currentDeg;

                final int nicks = (int) (Math.signum(deltaDeg) 
                        * Math.floor(Math.abs(deltaDeg) / degPerNick));

                if (nicks != 0) {
                    dragStartDeg = currentDeg;
                    rotate(nicks);
                } 
            } 

            return true;
        } else {
            return false;
        }
    }

    @Override
    public void onShowPress(MotionEvent e) {

    }

    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        return false;
    }

}


根据用户选择,我想要 0-9 并且还允许用户旋转到 0-9 而不是更多旋转。

我还检查了下面的另一个代码。

dialer = (ImageView) findViewById(R.id.imageView_ring);
        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);
                    Log.e("Rotation degree :"+rotationDegrees, String.valueOf(tickNumber));
                }
            }
        });

int tickNumber = 0;
    private void rotateDialer(float degrees) {

        //System.out.println("Rotation Done :: "+rotationDone);

       // if(!rotationDone) {

            this.rotationDegrees += degrees;
            this.rotationDegrees = this.rotationDegrees % 360;

            tickNumber = (int)this.rotationDegrees*100/360;
            // It could be negative
            if (tickNumber > 0) tickNumber = 100 - tickNumber;


            //this.rotationDegrees  = Math.abs(rotationDegrees);
            this.tickNumber = Math.abs(tickNumber);

           if(tickNumber  < 20 || tickNumber > 80){
               Log.e("Rotation degree :"+rotationDegrees, String.valueOf(tickNumber));
               matrix.postRotate(degrees, dialerWidth / 2, dialerHeight / 2);
               dialer.setImageMatrix(matrix);
           }

       // }
    }
    /**
     * @return The angle of the unit circle with the image view's center
     */
    private double getAngle(double xTouch, double yTouch) {

        double delta_x = xTouch - (dialerWidth) /2;
        double delta_y = (dialerHeight) /2 - yTouch;
        double radians = Math.atan2(delta_y, delta_x);

        double dx = xTouch - dWidth;
        double dy = (dHeight - ((dialerHeight) /2)) -  yTouch;
        double dRadi = Math.atan2(dy, dx);
        //Log.e("MY degree", String.valueOf( Math.toDegrees(dRadi)));
        //return Math.toDegrees(dRadi);
        return Math.toDegrees(radians);
    }



    /**
     * 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());
                    break;

                case MotionEvent.ACTION_MOVE:
                    /*double rotationAngleRadians = Math.atan2(event.getX() - (dialer.getWidth() / 2 ),     ( (dialer.getHeight() / 2 ) - event.getY()));
                    double angle = (int) Math.toDegrees(rotationAngleRadians);
                    Log.i("gg", "rotaion angle"+angle);*/

                    double currentAngle = getAngle(event.getX(), event.getY());
                    //if(currentAngle < 130 || currentAngle < 110){
                        //Log.e("Start angle :"+startAngle, "Current angle:"+currentAngle);
                        rotateDialer((float) (startAngle - currentAngle));
                        startAngle = currentAngle;
                    //}


                    //Log.e("MOVE start Degree:"+startAngle, "Current Degree :"+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;
        }
    }

最佳答案

我不明白你的问题。下面的代码将图像旋转 48 度。

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

int degrees = 48;
Matrix matrix = new Matrix();
matrix.setRotate(degrees);
Bitmap bmpBowRotated = Bitmap.createBitmap(imageOrginal, 0, 0, imageOrginal.getWidth(),imageOrginal.getHeight(), matrix, false);

dialer.setImageBitmap(bmpBowRotated);

关于android - 以有限度数旋转表盘,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14067633/

相关文章:

android - 获取 Canvas 的一部分作为位图

复制到图库的Android透明图像获得纯黑色背景

android - 如何使用选择器为 ImageView 着色?

android - 使用前置摄像头捕捉图像

java - 编辑文本。红色光标和下划线

android - 如何使用 PorterDuff Xfermodes 和 Alpha Mask 删除位图的一部分?

android - Gradle 构建在本地机器上工作但在 Jenkins CI 服务器上失败?

android - 如何测试对象初始化的约束?

android - 如何在 Android 上正确缩放游戏