1ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi/* 2ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Copyright (C) 2009 The Android Open Source Project 3ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * 4ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Licensed under the Apache License, Version 2.0 (the "License"); 5ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * you may not use this file except in compliance with the License. 6ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * You may obtain a copy of the License at 7ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * 8ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * http://www.apache.org/licenses/LICENSE-2.0 9ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * 10ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Unless required by applicable law or agreed to in writing, software 11ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * distributed under the License is distributed on an "AS IS" BASIS, 12ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * See the License for the specific language governing permissions and 14ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * limitations under the License. 15ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 16ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 1781393d6dc5767f7784a00958095614a37bf1a91aGil Dobjanschipackage com.android.videoeditor.widgets; 18ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 19ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 20ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.content.Context; 21ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.graphics.Bitmap; 22ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.graphics.Matrix; 23ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.graphics.RectF; 24ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.graphics.drawable.Drawable; 25ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.util.AttributeSet; 26ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.view.MotionEvent; 27ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.widget.ImageView; 28ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 29ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi/** 30ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * An image view which can be panned and zoomed. 31ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 32ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschipublic class ImageViewTouchBase extends ImageView { 33ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi private static final float SCALE_RATE = 1.25F; 34ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi // Zoom scale is applied after the transform that fits the image screen, 35ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi // so 1.0 is a perfect fit and it doesn't make sense to allow smaller 36ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi // values. 37ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi private static final float MIN_ZOOM_SCALE = 1.0f; 38ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 39ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi // This is the base transformation which is used to show the image 40ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi // initially. The current computation for this shows the image in 41ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi // it's entirety, letterboxing as needed. One could choose to 42ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi // show the image as cropped instead. 43ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi // 44ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi // This matrix is recomputed when we go from the thumbnail image to 45ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi // the full size image. 46ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi private Matrix mBaseMatrix = new Matrix(); 47ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 48ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi // This is the supplementary transformation which reflects what 49ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi // the user has done in terms of zooming and panning. 50ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi // 51ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi // This matrix remains the same when we go from the thumbnail image 52ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi // to the full size image. 53ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi private Matrix mSuppMatrix = new Matrix(); 54ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 55ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi // This is the final matrix which is computed as the concatenation 56ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi // of the base matrix and the supplementary matrix. 57ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi private final Matrix mDisplayMatrix = new Matrix(); 58ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 59ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi // Temporary buffer used for getting the values out of a matrix. 60ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi private final float[] mMatrixValues = new float[9]; 61ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 62ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi // The current bitmap being displayed. 63ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi private Bitmap mBitmapDisplayed; 64ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 65ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi // The width and height of the view 66ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi private int mThisWidth = -1, mThisHeight = -1; 67ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 68ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi private boolean mStretch = true; 69ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi // The zoom scale 70ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi private float mMaxZoom; 71ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi private Runnable mOnLayoutRunnable = null; 72ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi private ImageTouchEventListener mEventListener; 73ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 74ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 75ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Touch interface 76ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 77ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi public interface ImageTouchEventListener { 78ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi public boolean onImageTouchEvent(MotionEvent ev); 79ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 80ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 81ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Constructor 82ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * 83ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @param context The context 84ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 85ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi public ImageViewTouchBase(Context context) { 86ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi super(context); 87ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi setScaleType(ImageView.ScaleType.MATRIX); 88ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 89ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 90ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 91ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Constructor 92ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * 93ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @param context The context 94ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @param attrs The attributes 95ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 96ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi public ImageViewTouchBase(Context context, AttributeSet attrs) { 97ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi super(context, attrs); 98ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi setScaleType(ImageView.ScaleType.MATRIX); 99ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 100ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 101ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 102ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Constructor 103ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * 104ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @param context The context 105ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @param attrs The attributes 106ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @param defStyle The default style 107ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 108ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi public ImageViewTouchBase(Context context, AttributeSet attrs, int defStyle) { 109ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi super(context, attrs, defStyle); 110ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi setScaleType(ImageView.ScaleType.MATRIX); 111ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 112ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 113ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /* 114ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * {@inheritDoc} 115ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 116ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi @Override 117ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 118ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi super.onLayout(changed, left, top, right, bottom); 119ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 120ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi mThisWidth = right - left; 121ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi mThisHeight = bottom - top; 122ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi final Runnable r = mOnLayoutRunnable; 123ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi if (r != null) { 124ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi mOnLayoutRunnable = null; 125ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi r.run(); 126ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } else { 127ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi if (mBitmapDisplayed != null) { 128ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi getProperBaseMatrix(mBitmapDisplayed, mBaseMatrix); 129ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi setImageMatrix(getImageViewMatrix()); 130ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 131ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 132ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 133ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 134ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /* 135ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * {@inheritDoc} 136ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 137ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi @Override 138ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi public boolean dispatchTouchEvent(MotionEvent ev) { 139ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi if (mEventListener != null) { 140ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi return mEventListener.onImageTouchEvent(ev); 141ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } else { 142ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi return false; 143ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 144ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 145ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 146ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /* 147ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * {@inheritDoc} 148ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 149ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi @Override 150ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi public void setImageBitmap(Bitmap bitmap) { 151ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi super.setImageBitmap(bitmap); 152ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 153ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi final Drawable d = getDrawable(); 154ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi if (d != null) { 155ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi d.setDither(true); 156ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 157ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 158ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi mBitmapDisplayed = bitmap; 159ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 160ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 161ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 162ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @param listener The listener 163ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 164ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi public void setEventListener(ImageTouchEventListener listener) { 165ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi mEventListener = listener; 166ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 167ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 168ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 169ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @return The image bitmap 170ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 171ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi public Bitmap getImageBitmap() { 172ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi return mBitmapDisplayed; 173ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 174ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 175ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 176ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * If the view has not yet been measured delay the method 177ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * 178ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @param bitmap The bitmap 179ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @param resetSupp true to reset the transform matrix 180ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 181ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi public void setImageBitmapResetBase(final Bitmap bitmap, final boolean resetSupp) { 182ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi mStretch = true; 183ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi final int viewWidth = getWidth(); 184ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi if (viewWidth <= 0) { 185ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi mOnLayoutRunnable = new Runnable() { 186fe7b065c18808ac3bd15ea5a1248b3af66b50fb7Shih-chia Cheng @Override 187ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi public void run() { 188ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi setImageBitmapResetBase(bitmap, resetSupp); 189ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 190ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi }; 191ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi return; 192ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 193ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 194ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi if (bitmap != null) { 195ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi getProperBaseMatrix(bitmap, mBaseMatrix); 196ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi setImageBitmap(bitmap); 197ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } else { 198ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi mBaseMatrix.reset(); 199ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi setImageBitmap(null); 200ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 201ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 202ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi if (resetSupp) { 203ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi mSuppMatrix.reset(); 204ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 205ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 206ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi setImageMatrix(getImageViewMatrix()); 207ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi mMaxZoom = maxZoom(); 208ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 209ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 210ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 211ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Reset the transform of the current image 212ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 213ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi public void reset() { 214ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi if (mBitmapDisplayed != null) { 215ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi setImageBitmapResetBase(mBitmapDisplayed, true); 216ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 217ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 218ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 219ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 220ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Pan 221ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * 222ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @param dx The horizontal offset 223ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @param dy The vertical offset 224ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 225ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi public void postTranslateCenter(float dx, float dy) { 226ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi mSuppMatrix.postTranslate(dx, dy); 227ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 228ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi center(true, true); 229ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 230ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 231ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 232ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Pan by the specified horizontal and vertical amount 233ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * 234ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @param dx Pan by this horizontal amount 235ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @param dy Pan by this vertical amount 236ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 237ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi private void panBy(float dx, float dy) { 238ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi mSuppMatrix.postTranslate(dx, dy); 239ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 240ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi setImageMatrix(getImageViewMatrix()); 241ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 242ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 243ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 244ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @return The scale 245ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 246ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi public float getScale() { 247ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi return getValue(mSuppMatrix, Matrix.MSCALE_X); 248ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 249ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 250ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 251ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @param rect The input/output rectangle 252ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 253ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi public void mapRect(RectF rect) { 254ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi mSuppMatrix.mapRect(rect); 255ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 256ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 257ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 258ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Setup the base matrix so that the image is centered and scaled properly. 259ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * 260ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @param bitmap The bitmap 261ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @param matrix The matrix 262ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 263ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi private void getProperBaseMatrix(Bitmap bitmap, Matrix matrix) { 264ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi final float viewWidth = getWidth(); 265ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi final float viewHeight = getHeight(); 266ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 267ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi final float w = bitmap.getWidth(); 268ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi final float h = bitmap.getHeight(); 269ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi matrix.reset(); 270ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 271ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi if (mStretch) { 272ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi // We limit up-scaling to 10x otherwise the result may look bad if 273ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi // it's a small icon. 274ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi float widthScale = Math.min(viewWidth / w, 10.0f); 275ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi float heightScale = Math.min(viewHeight / h, 10.0f); 276ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi float scale = Math.min(widthScale, heightScale); 277ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi matrix.postScale(scale, scale); 278ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi matrix.postTranslate((viewWidth - w * scale) / 2F, (viewHeight - h * scale) / 2F); 279ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } else { 280ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi matrix.postTranslate((viewWidth - w) / 2F, (viewHeight - h) / 2F); 281ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 282ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 283ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 284ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 285ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Combine the base matrix and the supp matrix to make the final matrix. 286ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 287ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi private Matrix getImageViewMatrix() { 288ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi // The final matrix is computed as the concatenation of the base matrix 289ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi // and the supplementary matrix. 290ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi mDisplayMatrix.set(mBaseMatrix); 291ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi mDisplayMatrix.postConcat(mSuppMatrix); 292ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi return mDisplayMatrix; 293ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 294ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 295ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 296ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @return The maximum zoom 297ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 298ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi public float getMaxZoom() { 299ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi return mMaxZoom; 300ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 301ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 302ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 303ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Sets the maximum zoom, which is a scale relative to the base matrix. It 304ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * is calculated to show the image at 400% zoom regardless of screen or 305ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * image orientation. If in the future we decode the full 3 megapixel 306ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * image, rather than the current 1024x768, this should be changed down 307ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * to 200%. 308ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 309ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi private float maxZoom() { 310ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi if (mBitmapDisplayed == null) { 311ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi return 1F; 312ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 313ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 314ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi final float fw = (float)mBitmapDisplayed.getWidth() / mThisWidth; 315ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi final float fh = (float)mBitmapDisplayed.getHeight() / mThisHeight; 316ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 317ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi return Math.max(fw, fh) * 4; 318ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 319ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 320ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 321ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Sets the maximum zoom, which is a scale relative to the base matrix. It 322ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * is calculated to show the image at 400% zoom regardless of screen or 323ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * image orientation. If in the future we decode the full 3 megapixel 324ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * image, rather than the current 1024x768, this should be changed down 325ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * to 200%. 326ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 327ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi public static float maxZoom(int bitmapWidth, int bitmapHeight, int viewWidth, int viewHeight) { 328ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi final float fw = (float)bitmapWidth / viewWidth; 329ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi final float fh = (float)bitmapHeight / viewHeight; 330ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 331ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi return Math.max(fw, fh) * 4; 332ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 333ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 334ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 335ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Ensure the scale factor is within limits 336ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * 337ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @param scale The scale factor 338ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * 339ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @return The corrected scaled factor 340ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 341ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi private float correctedZoomScale(float scale) { 342ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi float result = scale; 343ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi if (result > mMaxZoom) { 344ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi result = mMaxZoom; 345ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } else if (result < MIN_ZOOM_SCALE) { 346ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi result = MIN_ZOOM_SCALE; 347ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 348ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 349ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi return result; 350ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 351ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 352ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 353ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Zoom to the specified scale factor 354ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * 355ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @param scale The scale factor 356ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @param centerX The horizontal center 357ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @param centerY The vertical center 358ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 359ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi public void zoomTo(float scale, float centerX, float centerY) { 360ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi float correctedScale = correctedZoomScale(scale); 361ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 362ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi float oldScale = getScale(); 363ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi float deltaScale = correctedScale / oldScale; 364ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 365ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi mSuppMatrix.postScale(deltaScale, deltaScale, centerX, centerY); 366ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi setImageMatrix(getImageViewMatrix()); 367ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi center(true, true); 368ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 369ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 370ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 371ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Zoom to the specified scale factor 372ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * 373ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @param scale The scale factor 374ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 375ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi public void zoomTo(float scale) { 376ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi final float cx = getWidth() / 2F; 377ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi final float cy = getHeight() / 2F; 378ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 379ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi zoomTo(scale, cx, cy); 380ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 381ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 382ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 383ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Zoom to the specified scale factor and center point 384ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * 385ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @param scale The scale factor 386ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @param pointX The horizontal position 387ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @param pointY The vertical position 388ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 389ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi public void zoomToPoint(float scale, float pointX, float pointY) { 390ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi final float cx = getWidth() / 2F; 391ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi final float cy = getHeight() / 2F; 392ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 393ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi panBy(cx - pointX, cy - pointY); 394ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi zoomTo(scale, cx, cy); 395ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 396ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 397ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 398ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Zoom to the specified scale factor and point 399ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * 400ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @param scale The scale factor 401ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @param pointX The horizontal position 402ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @param pointY The vertical position 403ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 404ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi public void zoomToOffset(float scale, float pointX, float pointY) { 405ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 406ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi float correctedScale = correctedZoomScale(scale); 407ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 408ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi float oldScale = getScale(); 409ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi float deltaScale = correctedScale / oldScale; 410ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 411ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi mSuppMatrix.postScale(deltaScale, deltaScale); 412ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi setImageMatrix(getImageViewMatrix()); 413ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 414ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi panBy(-pointX, -pointY); 415ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 416ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 417ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 418ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Zoom in by a preset scale rate 419ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 420ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi public void zoomIn() { 421ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi zoomIn(SCALE_RATE); 422ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 423ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 424ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 425ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Zoom in by the specified scale rate 426ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * 427ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @param rate The scale rate 428ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 429ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi public void zoomIn(float rate) { 430ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi if (getScale() < mMaxZoom && mBitmapDisplayed != null) { 431ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi float cx = getWidth() / 2F; 432ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi float cy = getHeight() / 2F; 433ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 434ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi mSuppMatrix.postScale(rate, rate, cx, cy); 435ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi setImageMatrix(getImageViewMatrix()); 436ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 437ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 438ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 439ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 440ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Zoom out by a preset scale rate 441ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 442ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi public void zoomOut() { 443ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi zoomOut(SCALE_RATE); 444ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 445ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 446ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 447ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Zoom out by the specified scale rate 448ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * 449ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @param rate The scale rate 450ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 451ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi public void zoomOut(float rate) { 452ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi if (getScale() > MIN_ZOOM_SCALE && mBitmapDisplayed != null) { 453ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi float cx = getWidth() / 2F; 454ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi float cy = getHeight() / 2F; 455ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 456ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi // Zoom out to at most 1x. 457ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi Matrix tmp = new Matrix(mSuppMatrix); 458ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi tmp.postScale(1F / rate, 1F / rate, cx, cy); 459ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 460ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi if (getValue(tmp, Matrix.MSCALE_X) < 1F) { 461ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi mSuppMatrix.setScale(1F, 1F, cx, cy); 462ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } else { 463ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi mSuppMatrix.postScale(1F / rate, 1F / rate, cx, cy); 464ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 465ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi setImageMatrix(getImageViewMatrix()); 466ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi center(true, true); 467ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 468ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 469ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 470ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 471ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Center as much as possible in one or both axis. Centering is 472ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * defined as follows: if the image is scaled down below the 473ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * view's dimensions then center it (literally). If the image 474ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * is scaled larger than the view and is translated out of view 475ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * then translate it back into view (i.e. eliminate black bars). 476ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 477ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi private void center(boolean horizontal, boolean vertical) { 478ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi if (mBitmapDisplayed == null) { 479ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi return; 480ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 481ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 482ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi final Matrix m = getImageViewMatrix(); 483ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi final RectF rect = new RectF(0, 0, mBitmapDisplayed.getWidth(), 484ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi mBitmapDisplayed.getHeight()); 485ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 486ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi m.mapRect(rect); 487ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 488ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi final float height = rect.height(); 489ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi final float width = rect.width(); 490ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi float deltaX = 0, deltaY = 0; 491ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 492ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi if (vertical) { 493ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi int viewHeight = getHeight(); 494ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi if (height < viewHeight) { 495ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi deltaY = (viewHeight - height) / 2 - rect.top; 496ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } else if (rect.top > 0) { 497ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi deltaY = -rect.top; 498ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } else if (rect.bottom < viewHeight) { 499ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi deltaY = getHeight() - rect.bottom; 500ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 501ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 502ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 503ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi if (horizontal) { 504ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi int viewWidth = getWidth(); 505ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi if (width < viewWidth) { 506ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi deltaX = (viewWidth - width) / 2 - rect.left; 507ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } else if (rect.left > 0) { 508ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi deltaX = -rect.left; 509ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } else if (rect.right < viewWidth) { 510ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi deltaX = viewWidth - rect.right; 511ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 512ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 513ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 514ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi mSuppMatrix.postTranslate(deltaX, deltaY); 515ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 516ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi setImageMatrix(getImageViewMatrix()); 517ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 518ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 519ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 520ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Get a matrix transform value 521ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * 522ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @param matrix The matrix 523ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @param whichValue Which value 524ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @return The value 525ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 526ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi private float getValue(Matrix matrix, int whichValue) { 527ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi matrix.getValues(mMatrixValues); 528ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi return mMatrixValues[whichValue]; 529ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 530ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi} 531