2012-10-30 1 views
0

나는 속도계와 비슷한 다이얼에 원형으로 배치 된 8 개의 이미지가 있는데, 0과 유사한 위치에 첫 번째 이미지가 있고, 속도계의 마지막 값 또는 200과 비슷한 위치에 마지막 이미지가 있습니다. . 이제베이스에 고정 된 바늘을 회전시키고 첫 번째 이미지에서 마지막 이미지로 이동하려고합니다. 바늘이 회전하는 동안 이미지 위로 이동하면서 이미지가 변경됩니다. 바늘이 첫 번째 이미지에서 마지막 이미지로 이동하고 첫 번째 이미지로 다시 이동합니다. 센서 코드를 제거하고 배경을 제거하고 주요 덩어리에 reverse()이라는 새로운 방법을 추가하여 움직임이 역전되어 어디서 잘못 찾았는지 찾을 수 없습니다. 루프를 한 번 실행하면 나옵니다.속도계 애니메이션 안드로이드

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(); 
    } 
} 
+0

사람이 무엇을 당신을 도와 드릴까요? 너는 무엇에 붙어 있니? 너 뭐 해봤 니? 이미지를 바꾸는 방법? 바늘을 돌리는 법? 바늘이 통과 할 때 이미지를 변경하는 방법은 무엇입니까? 세 개 모두? 구현 아이디어는 무엇입니까? – Simon

+0

'Canvas'와'Animation'에 대한 많은 지식이 없기 때문에 완전히 잃어 버렸습니다. 그러나 제가 생각하기에 스레드를 사용하고 각도로 회전시키고 바늘이 이미지가있는 특정 정도에 도달하면 비트 맵을 변경할 계획입니다. 그러나 구현 방법을 모르겠습니다. 니들이 회전 할 때 바늘의베이스가 고정되어 있어야합니다. – sankettt

+0

좋습니다,이 작업을 수행하는 가장 좋은 방법은 예를 들어 ImageView를 확장하여 사용자 지정보기를 만드는 것입니다. 그런 다음 캔버스를 사용하여 바늘 인 이미지를 회전시킵니다. 이것은 http://mindtherobot.com/blog/272/android-custom-ui-making-a-vintage-thermometer/ – Simon

답변

0

그냥 최대의 정도 및 그것은 나를 위해 일 반 시계 방향으로 회전을위한 moveHand() 방법 setHandTarget(minDegrees)의 손 위치를 초기화합니다.

시계 방향으로 회전하려면 반대 방향으로하십시오.

0

나는 손을 보여주는를 해결하고 주요 활동이 삽입 이동 한 :

그것은 하드웨어 가속과 관련이있다
View termometro = (View)findViewById(R.id.termometro); 
    termometro.setLayerType(View.LAYER_TYPE_SOFTWARE, null); 

관련 문제