2014-12-25 2 views
1

Я пытаюсь реализовать циферблат часов, где растровое изображение руки вращается вокруг центра лица на холсте.Вращение растрового изображения вокруг стержня на холсте

  1. В основном в методе onDraw(), я хочу иметь возможность разместить ресурс изображения на холсте, а затем поворачивать его, поворачивая его каждую секунду.
  2. У меня есть логика для запуска вращения каждую секунду, я не уверен, как получить ресурс изображения, а затем повернуть его.

Любая помощь будет определена!

ответ

1

Основные шаги:

  1. декодировать растрового изображения из, например, ресурсов, но есть и другие способы. (Вы хотели бы сделать это один раз при инициализации класса, а не на каждом розыгрыше цикла.):

    Bitmap = mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.watch_face);

  2. Настройка Matrix внутри onDraw для вращения. Что-то вроде:

    Matrix mMatrix = new Matrix(); mMatrix.setRotate (degreeOfRotation, mBitmap.getWidth()/2, mBitmap.getHeight()/2);

  3. Нарисуйте Bitmap, используя метод, который принимает в вашей матрице: canvas.drawBitmap(mBitmap, mMatrix, mPaint);

Есть другие детали. Настройка Paint. Вы можете обнаружить, что вам нужно использовать метод Matrix postRotate. И т. Д. Но этого должно быть достаточно, чтобы вы начали Googling.

+0

Расположение стержня не изменяется. – AndroidDev

1

В этой определенной ситуации (я думаю, вы пытаетесь повернуть растровые изображения с помощью Google watch face api), вы должны иметь в виду правила, описанные в this brilliant post, и избегать использования больших растровых изображений для рук часов. Это означает, что вам нужно указать вертикальные и горизонтальные поля. Я использовал решение, размещенное Jave here.

yourCanvas.save(Canvas.MATRIX_SAVE_FLAG); //Save the canvas 
yourCanvas.rotate(currentRotation, centerX, centerY); 
int marginX = (width - yourBitmap.getWidth())/2; //Calculate horizontal margin 
yourCanvas.drawBitmap(yourBitmap, marginX, 0, yourPaint); 
yourCanvas.restore(); 

Я отказался от кадрирования растрового изображения по вертикали, так как это гораздо проще повернуть его таким образом, но оно должно быть принято во внимание, если вы хотите быть в полном соответствии с правилами. Было бы даже лучше не рассчитать marginX здесь. Это может быть сделано в onSurfaceChanged, как описано в сообщении, упомянутом выше.

0

Мне недавно нужно было решить проблему вращения растрового изображения для Android Wear watchface. Для меня работал следующий код onDraw. Убедитесь, что ваши растровые изображения масштабируются до того OnDraw вызывается:

 // first draw the background 
     if (isInAmbientMode()) { 
      canvas.drawColor(Color.BLACK); 
     } else { 
      if (mBackgroundBitmapScaled == null) { 
       canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), mBackgroundPaint); 
      } 
      else { 
       canvas.drawBitmap(mBackgroundBitmapScaled, 0, 0, null); 
      } 
     } 

     // now setup to draw the hands.. 
     float centerX = bounds.width()/2f; 
     float centerY = bounds.height()/2f; 

     float secRot = mCalendar.get(Calendar.SECOND)/30f * (float) Math.PI; 
     int minutes = mCalendar.get(Calendar.MINUTE); 
     float minRot = minutes/30f * (float) Math.PI; 
     float hrRot = ((mCalendar.get(Calendar.HOUR) + (minutes/60f))/6f) * (float) Math.PI; 

     if (isInAmbientMode()) { 
      mHandPaint.clearShadowLayer(); 
      float minLength = centerX - 40; 
      float hrLength = centerX - 80; 

      // hour hand 
      float hrX = (float) Math.sin(hrRot) * hrLength; 
      float hrY = (float) -Math.cos(hrRot) * hrLength; 
      canvas.drawLine(centerX, centerY, centerX + hrX, centerY + hrY, mHandPaint); 

      // minute hand 
      float minX = (float) Math.sin(minRot) * minLength; 
      float minY = (float) -Math.cos(minRot) * minLength; 
      canvas.drawLine(centerX, centerY, centerX + minX, centerY + minY, mHandPaint); 
     } 
     else { 
      // hour hand 
      Matrix matrix = new Matrix(); 
      matrix.setRotate (hrRot/(float) Math.PI * 180, mHourHandBitmapScaled.getWidth()/2, mHourHandBitmapScaled.getHeight()/2); 
      canvas.drawBitmap(mHourHandBitmapScaled, matrix, mHandPaint); 

      // minute hand 
      matrix = new Matrix(); 
      matrix.setRotate (minRot/(float) Math.PI * 180, mHourHandBitmapScaled.getWidth()/2, mHourHandBitmapScaled.getHeight()/2); 
      canvas.drawBitmap(mMinuteHandBitmapScaled, matrix, mHandPaint); 
     } 

     if (!mAmbient) { 
      // second hand 
      float secLength = centerX - 20; 
      float secX = (float) Math.sin(secRot) * secLength; 
      float secY = (float) -Math.cos(secRot) * secLength; 
      canvas.drawLine(centerX, centerY, centerX + secX, centerY + secY, mHandPaint); 
     } 

и масштабирования:

private void scaleWatchFace(int width, int height) { 
     Log.v(TAG, "scaleWatchFace"); 
     mBackgroundBitmapScaled = Bitmap.createScaledBitmap(mBackgroundBitmap, width, height, true /* filter */); 
     float ratio = (float) width/mBackgroundBitmap.getWidth(); 
     mMinuteHandBitmapScaled = Bitmap.createScaledBitmap(mMinuteHandBitmap, 
       (int) (mMinuteHandBitmap.getWidth() * ratio), 
       (int) (mMinuteHandBitmap.getHeight() * ratio), true); 
     mHourHandBitmapScaled = Bitmap.createScaledBitmap(mHourHandBitmap, 
       (int) (mHourHandBitmap.getWidth() * ratio), 
       (int) (mHourHandBitmap.getHeight() * ratio), true); 
    } 

Обратите внимание, что размеры изображения моего фона и часы ручной ресурсы являются все 480x480. Это устраняет необходимость перевода в центр, и (возможно) проще на батарею.

Надеюсь, это полезно.

Смежные вопросы