RotateImageView.java revision c5e37cbb96b8284203560c51dd5f41c705a21f58
1/* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.camera.ui; 18 19import android.content.Context; 20import android.graphics.Bitmap; 21import android.graphics.Canvas; 22import android.graphics.Rect; 23import android.graphics.drawable.BitmapDrawable; 24import android.graphics.drawable.Drawable; 25import android.graphics.drawable.TransitionDrawable; 26import android.media.ThumbnailUtils; 27import android.util.AttributeSet; 28import android.view.ViewGroup.LayoutParams; 29import android.view.animation.AnimationUtils; 30import android.widget.ImageView; 31 32/** 33 * A @{code ImageView} which can rotate it's content. 34 */ 35public class RotateImageView extends ImageView { 36 37 @SuppressWarnings("unused") 38 private static final String TAG = "RotateImageView"; 39 40 private static final int ANIMATION_SPEED = 180; // 180 deg/sec 41 42 private int mCurrentDegree = 0; // [0, 359] 43 private int mStartDegree = 0; 44 private int mTargetDegree = 0; 45 46 private boolean mClockwise = false, mEnableAnimation = true; 47 48 private long mAnimationStartTime = 0; 49 private long mAnimationEndTime = 0; 50 51 public RotateImageView(Context context, AttributeSet attrs) { 52 super(context, attrs); 53 } 54 55 public void enableAnimation(boolean enable) { 56 mEnableAnimation = enable; 57 } 58 59 // Rotate the view counter-clockwise 60 public void setDegree(int degree) { 61 // make sure in the range of [0, 359] 62 degree = degree >= 0 ? degree % 360 : degree % 360 + 360; 63 if (degree == mTargetDegree) return; 64 65 mTargetDegree = degree; 66 mStartDegree = mCurrentDegree; 67 mAnimationStartTime = AnimationUtils.currentAnimationTimeMillis(); 68 69 int diff = mTargetDegree - mCurrentDegree; 70 diff = diff >= 0 ? diff : 360 + diff; // make it in range [0, 359] 71 72 // Make it in range [-179, 180]. That's the shorted distance between the 73 // two angles 74 diff = diff > 180 ? diff - 360 : diff; 75 76 mClockwise = diff >= 0; 77 mAnimationEndTime = mAnimationStartTime 78 + Math.abs(diff) * 1000 / ANIMATION_SPEED; 79 80 invalidate(); 81 } 82 83 @Override 84 protected void onDraw(Canvas canvas) { 85 Drawable drawable = getDrawable(); 86 if (drawable == null) return; 87 88 Rect bounds = drawable.getBounds(); 89 int w = bounds.right - bounds.left; 90 int h = bounds.bottom - bounds.top; 91 92 if (w == 0 || h == 0) return; // nothing to draw 93 94 if (mCurrentDegree != mTargetDegree) { 95 long time = AnimationUtils.currentAnimationTimeMillis(); 96 if (time < mAnimationEndTime) { 97 int deltaTime = (int)(time - mAnimationStartTime); 98 int degree = mStartDegree + ANIMATION_SPEED 99 * (mClockwise ? deltaTime : -deltaTime) / 1000; 100 degree = degree >= 0 ? degree % 360 : degree % 360 + 360; 101 mCurrentDegree = degree; 102 invalidate(); 103 } else { 104 mCurrentDegree = mTargetDegree; 105 } 106 } 107 108 int left = getPaddingLeft(); 109 int top = getPaddingTop(); 110 int right = getPaddingRight(); 111 int bottom = getPaddingBottom(); 112 int width = getWidth() - left - right; 113 int height = getHeight() - top - bottom; 114 115 int saveCount = canvas.getSaveCount(); 116 canvas.translate(left + width / 2, top + height / 2); 117 canvas.rotate(-mCurrentDegree); 118 canvas.translate(-w / 2, -h / 2); 119 drawable.draw(canvas); 120 canvas.restoreToCount(saveCount); 121 } 122 123 private Bitmap mThumb; 124 private Drawable[] mThumbs; 125 private TransitionDrawable mThumbTransition; 126 127 public void setBitmap(Bitmap bitmap) { 128 // Make sure uri and original are consistently both null or both 129 // non-null. 130 if (bitmap == null) { 131 mThumb = null; 132 mThumbs = null; 133 setImageDrawable(null); 134 setVisibility(GONE); 135 return; 136 } 137 138 LayoutParams param = getLayoutParams(); 139 final int miniThumbWidth = param.width 140 - getPaddingLeft() - getPaddingRight(); 141 final int miniThumbHeight = param.height 142 - getPaddingTop() - getPaddingBottom(); 143 mThumb = ThumbnailUtils.extractThumbnail( 144 bitmap, miniThumbWidth, miniThumbHeight); 145 Drawable drawable; 146 if (mThumbs == null || !mEnableAnimation) { 147 mThumbs = new Drawable[2]; 148 mThumbs[1] = new BitmapDrawable(getContext().getResources(), mThumb); 149 setImageDrawable(mThumbs[1]); 150 } else { 151 mThumbs[0] = mThumbs[1]; 152 mThumbs[1] = new BitmapDrawable(getContext().getResources(), mThumb); 153 mThumbTransition = new TransitionDrawable(mThumbs); 154 setImageDrawable(mThumbTransition); 155 mThumbTransition.startTransition(500); 156 } 157 setVisibility(VISIBLE); 158 } 159} 160