0

スピードメーターに似たダイヤルに円形に配置された8つの画像があり、最初の画像は0に似た位置に配置され、最後の画像は200またはスピードメーターの最後の値に似た位置に配置されています。ここで、ベースに固定され、最初の画像から最後に移動する針を回転させたいと思います。針が回転している間、画像上を移動すると、画像が変化します。針は最初の画像から最後の画像に移動し、最初の画像に戻ります。望まなかったのでセンサーのコードを削除し、背景と主要なチャンクを削除してreverse()、動きを逆転させるために呼び出される新しいメソッドを追加しました。ループを1回実行するだけで出てきます。

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 に答える