0

I have 8 images which are placed circularly on the dial which resembles a speedometer with first image placed at the position which is similar to 0 and the last image on the position similar to 200 or the last value of the speedometer. Now i want to rotate the needle which is fixed at the base and moves from the first image to last.While the needle rotates,as it moves over the images,the images changes. The needle moves from first image to the last and moves back to first image.! Have removed the sensor's code as i didnt wanted and remove the background and major chunk added a new method called reverse() for reversing the movement not able to find where i am going wrong. it just execute the loop once and comes out.

public final class Thermometer extends View  
{
    private static final String TAG = Thermometer.class.getSimpleName();
    private Handler handler;

    // drawing tools

    private Paint scalePaint;
    private RectF scaleRect;


    private Paint logoPaint;
    private Bitmap logo;
    private Matrix logoMatrix;
    private float logoScale;

    private Paint handPaint;
    private Path handPath;
    private Paint handScrewPaint;

    private Paint backgroundPaint;
    // end drawing tools

    private Bitmap background; // holds the cached static part

    // scale configuration
    private static final int totalNicks = 100;
    private static final float degreesPerNick = 360.0f / totalNicks;
    private static final int centerDegree = 40; // the one in the top center (12
                                                // o'clock)
    private static final int minDegrees = -30;
    private static final int maxDegrees = 110;

    // hand dynamics -- all are angular expressed in F degrees
    private boolean handInitialized = false;
    private float handPosition = minDegrees;
    private float handTarget = minDegrees;
    private float handVelocity = 0.0f;
    private float handAcceleration = 0.0f;
    private long lastHandMoveTime = -1L;

    public Thermometer(Context context) 
    {
        super(context);
        init();
    }

    public Thermometer(Context context, AttributeSet attrs) 
    {
        super(context, attrs);
        init();
    }

    public Thermometer(Context context, AttributeSet attrs, int defStyle) 
    {
        super(context, attrs, defStyle);
        init();
    }


    @Override
    protected void onRestoreInstanceState(Parcelable state) 
    {
        Bundle bundle = (Bundle) state;
        Parcelable superState = bundle.getParcelable("superState");
        super.onRestoreInstanceState(superState);

        handInitialized = bundle.getBoolean("handInitialized");
        handPosition = bundle.getFloat("handPosition");
        handTarget = bundle.getFloat("handTarget");
        handVelocity = bundle.getFloat("handVelocity");
        handAcceleration = bundle.getFloat("handAcceleration");
        lastHandMoveTime = bundle.getLong("lastHandMoveTime");
    }

    @Override
    protected Parcelable onSaveInstanceState() 
    {
        Parcelable superState = super.onSaveInstanceState();

        Bundle state = new Bundle();
        state.putParcelable("superState", superState);
        state.putBoolean("handInitialized", handInitialized);
        state.putFloat("handPosition", handPosition);
        state.putFloat("handTarget", handTarget);
        state.putFloat("handVelocity", handVelocity);
        state.putFloat("handAcceleration", handAcceleration);
        state.putLong("lastHandMoveTime", lastHandMoveTime);
        return state;
    }

    private void init() 
    {
        handler = new Handler();
        initDrawingTools();
    }


    private void initDrawingTools() 
    {
        // the linear gradient is a bit skewed for realism

        logoPaint = new Paint();
        logoPaint.setFilterBitmap(true);
        logo = BitmapFactory.decodeResource(getContext().getResources(),R.drawable.logo);
        logoMatrix = new Matrix();
        logoScale = (1.0f / logo.getWidth()) * 0.3f;

        logoMatrix.setScale(logoScale, logoScale);

        handPaint = new Paint();
        handPaint.setAntiAlias(true);
        handPaint.setColor(0xff392f2c);
        handPaint.setShadowLayer(0.01f, -0.005f, -0.005f, 0x7f000000);
        handPaint.setStyle(Paint.Style.FILL);

        handPath = new Path();
        handPath.moveTo(0.5f, 0.5f + 0.2f);
        handPath.lineTo(0.5f - 0.010f, 0.5f + 0.2f - 0.007f);
        handPath.lineTo(0.5f - 0.002f, 0.5f - 0.32f);
        handPath.lineTo(0.5f + 0.002f, 0.5f - 0.32f);
        handPath.lineTo(0.5f + 0.010f, 0.5f + 0.2f - 0.007f);
        handPath.lineTo(0.5f, 0.5f + 0.2f);
        handPath.addCircle(0.5f, 0.5f, 0.025f, Path.Direction.CW);

        handScrewPaint = new Paint();
        handScrewPaint.setAntiAlias(true);
        handScrewPaint.setColor(0xff493f3c);
        handScrewPaint.setStyle(Paint.Style.FILL);

        backgroundPaint = new Paint();
        backgroundPaint.setFilterBitmap(true);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 
    {
        Log.d(TAG, "Width spec: " + MeasureSpec.toString(widthMeasureSpec));
        Log.d(TAG, "Height spec: " + MeasureSpec.toString(heightMeasureSpec));

        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);

        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        int chosenWidth = chooseDimension(widthMode, widthSize);
        int chosenHeight = chooseDimension(heightMode, heightSize);

        int chosenDimension = Math.min(chosenWidth, chosenHeight);

        setMeasuredDimension(chosenDimension, chosenDimension);
    }

    private int chooseDimension(int mode, int size) 
    {
        if (mode == MeasureSpec.AT_MOST || mode == MeasureSpec.EXACTLY) 
        {
            return size;
        } 
        else 
        { // (mode == MeasureSpec.UNSPECIFIED)
            return getPreferredSize();
        }
    }

    // in case there is no size specified
    private int getPreferredSize() 
    {
        return 300;
    }

    private void drawScale(Canvas canvas) 
    {
        canvas.drawOval(scaleRect, scalePaint);

        canvas.save(Canvas.MATRIX_SAVE_FLAG);
        for (int i = 0; i < totalNicks; ++i) 
        {
            float y1 = scaleRect.top;
            float y2 = y1 - 0.020f;
            canvas.drawLine(0.5f, y1, 0.5f, y2, scalePaint);
            if (i % 5 == 0) 
            {
                int value = nickToDegree(i);
                if (value >= minDegrees && value <= maxDegrees) 
                {
                    String valueString = Integer.toString(value);
                    canvas.drawText(valueString, 0.5f, y2 - 0.015f, scalePaint);
                }
            }
            canvas.rotate(degreesPerNick, 0.5f, 0.5f);
        }
        canvas.restore();
    }

    private int nickToDegree(int nick) 
    {
        int rawDegree = ((nick < totalNicks / 2) ? nick : (nick - totalNicks)) * 2;
        int shiftedDegree = rawDegree + centerDegree;
        return shiftedDegree;
    }

    private float degreeToAngle(float degree) 
    {
        return (degree - centerDegree) / 2.0f * degreesPerNick;
    }

    private void drawLogo(Canvas canvas) 
    {
        canvas.save(Canvas.MATRIX_SAVE_FLAG);
        canvas.translate(0.5f - logo.getWidth() * logoScale / 2.0f,0.5f - logo.getHeight() * logoScale / 2.0f);
        int color = 0x00000000;
        float position = getRelativeTemperaturePosition();
        if (position < 0) 
        {
            color |= (int) ((0xf0) * -position); // blue
        } 
        else 
        {
            color |= ((int) ((0xf0) * position)) << 16; // red
        }
        Log.d(TAG, "*** " + Integer.toHexString(color));
        LightingColorFilter logoFilter = new LightingColorFilter(0xff338822,color);
        logoPaint.setColorFilter(logoFilter);

        canvas.drawBitmap(logo, logoMatrix, logoPaint);
        canvas.restore();
    }

    private void drawHand(Canvas canvas) 
    {
        if (handInitialized) 
        {
            float handAngle = degreeToAngle(handPosition);
            canvas.save(Canvas.MATRIX_SAVE_FLAG);
            canvas.rotate(handAngle, 0.5f, 0.5f);
            canvas.drawPath(handPath, handPaint);
            canvas.restore();
            canvas.drawCircle(0.5f, 0.5f, 0.01f, handScrewPaint);
        }
    }

    private void drawBackground(Canvas canvas) 
    {
        if (background == null) 
        {
            Log.w(TAG, "Background not created");
        } 
        else 
        {
            canvas.drawBitmap(background, 0, 0, backgroundPaint);
        }
    }

    @Override
    protected void onDraw(Canvas canvas) 
    {
        drawBackground(canvas);
        float scale = (float) getWidth();
        canvas.save(Canvas.MATRIX_SAVE_FLAG);
        canvas.scale(scale, scale);
        drawLogo(canvas);
        drawHand(canvas);
        canvas.restore();
        moveHand();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) 
    {
        Log.d(TAG, "Size changed to " + w + "x" + h);
        regenerateBackground();
    }

    private void regenerateBackground() 
    {
        // free the old bitmap
        if (background != null) 
        {
            background.recycle();
        }

        background = Bitmap.createBitmap(getWidth(), getHeight(),Bitmap.Config.ARGB_8888);
        Canvas backgroundCanvas = new Canvas(background);
        float scale = (float) getWidth();
        backgroundCanvas.scale(scale, scale);

    }

    private boolean handNeedsToMove() 
    {
        return Math.abs(handPosition - handTarget) > 0.01f;
    }

    private void moveHand() 
    {
        setHandTarget(maxDegrees);
        if (!handNeedsToMove()) 
        {
            return;
        }
        if (lastHandMoveTime != -1L) 
        {
            long currentTime = System.currentTimeMillis();
            float delta = (currentTime - lastHandMoveTime) / 1500.0f;
            float direction = Math.signum(handVelocity);
            if (Math.abs(handVelocity) < 90.0f) 
            {
                handAcceleration = 5.0f * (handTarget - handPosition);
            } 
            else 
            {
                handAcceleration = 0.0f;
            }
            handPosition += handVelocity * delta;
            handVelocity += handAcceleration * delta;
            if ((handTarget - handPosition) * direction < 0.01f * direction) 
            {
                handPosition = handTarget;
                handVelocity = 0.0f;
                handAcceleration = 0.0f;
                lastHandMoveTime = -1L;
            } 
            else 
            {
                Log.i("inside ","direction else loop");
                lastHandMoveTime = System.currentTimeMillis();
            }
            invalidate();
        }   
        else 
        {
            Log.i("inside ","direction first final else loop");
            lastHandMoveTime = System.currentTimeMillis();
            moveHand();
        }
        if(handPosition==maxDegrees)
        {
            reverse();
        }
    }

    public void reverse()
    {
        handAcceleration=1.0f;
        Log.i("Hand Velocity",Float.toString(handVelocity));
        Log.i("Inside","next loop");
        setHandTarget(minDegrees);
        if (!handNeedsToMove()) 
        {
            return;
        }
        if (lastHandMoveTime != -1L) 
        {
            long currentTime = System.currentTimeMillis();
            float delta = (currentTime -lastHandMoveTime) / 1500.0f;
            float direction = Math.signum(handVelocity);
            if (Math.abs(handVelocity) <90.0f) 
            {
                handAcceleration = 5.0f * (handPosition+handTarget);
                Log.i("Hand Acceleration",Float.toString(handAcceleration));
            }       
            else 
            {
                handAcceleration = 0.0f;
            }   
            handPosition -= handVelocity * delta;
            handVelocity -= handAcceleration *delta;
            if ((handPosition + handTarget) * direction < 0.01f * direction) 
            {
                handPosition = handTarget;
                handVelocity = 0.0f;
                handAcceleration = 0.0f;
                lastHandMoveTime =-1L; 
            } 
            else 
            {
                lastHandMoveTime = System.currentTimeMillis();
            }   
            invalidate();
        } 
        else 
        {
            lastHandMoveTime = System.currentTimeMillis();
            reverse();
        }   
    }

    private float getRelativeTemperaturePosition() 
    {
        if (handPosition < centerDegree) 
        {
            return -(centerDegree - handPosition)/ (float) (centerDegree - minDegrees);
        } 
        else 
        {
            return (handPosition - centerDegree)/ (float) (maxDegrees - centerDegree);
        }
    }

    private void setHandTarget(float temperature) 
    {
        if (temperature < minDegrees) 
        {
            temperature = minDegrees;
        } 
        else if (temperature > maxDegrees) 
        {
            temperature = maxDegrees;
        }
        handTarget = temperature;
        handInitialized = true;
        invalidate();
    }
}
4

2 回答 2

0

只需将手的位置初始化为最大程度,并在逆时针旋转的moveHand()方法setHandTarget(minDegrees)中它对我有用。

对于顺时针旋转,只需做相反的事情。

于 2012-11-27T10:39:51.437 回答
0

我已经解决了在主要活动中插入这个的手显示和移动:

    View termometro = (View)findViewById(R.id.termometro);
    termometro.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

它与硬件加速有关

于 2014-10-19T14:51:47.077 回答