165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane/* 265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Copyright (C) 2014 The Android Open Source Project 365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * 465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Licensed under the Apache License, Version 2.0 (the "License"); 565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * you may not use this file except in compliance with the License. 665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * You may obtain a copy of the License at 765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * 865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * http://www.apache.org/licenses/LICENSE-2.0 965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * 1065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Unless required by applicable law or agreed to in writing, software 1165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * distributed under the License is distributed on an "AS IS" BASIS, 1265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * See the License for the specific language governing permissions and 1465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * limitations under the License. 1565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 1665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 1765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lanepackage com.android.tv.settings.util; 1865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 1965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.Context; 2065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.Intent; 2165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.graphics.Color; 2265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.graphics.Rect; 2365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.graphics.RectF; 2465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.graphics.drawable.BitmapDrawable; 2565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.graphics.drawable.Drawable; 2665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.net.Uri; 2765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.os.Bundle; 2865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.os.Parcelable; 2965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.text.TextUtils; 3065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.view.View; 3165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.widget.ImageView; 3265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 336e995161147d9110d77ae1fe38b697e52891d3f2Tony Mantlerimport com.android.tv.settings.widget.BitmapWorkerOptions; 346e995161147d9110d77ae1fe38b697e52891d3f2Tony Mantlerimport com.android.tv.settings.widget.DrawableDownloader; 356e995161147d9110d77ae1fe38b697e52891d3f2Tony Mantler 3665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport java.util.ArrayList; 3765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport java.util.List; 3865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 3965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane/** 4065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Initiator calls {@link #createFromImageView(ImageView)} and 4165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * {@link #writeMultipleToIntent(List, Intent)}. 4265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * <p> 4365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Receiver calls {@link #readMultipleFromIntent(Context, Intent)} to read source and 4465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * {@link #createFromImageView(ImageView)} for target image view; then start animation 4565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * using {@link TransitionImageView} between these two.<p> 4665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * The matching of Uri is up to receiver, typically using {@link TransitionImageMatcher} 4765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * <p> 4865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * The transition image has three bounds, all relative to window<p> 4965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * - {@link #setRect(Rect)} bounds of the image view, including background color<p> 5065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * - {@link #setUnclippedRect(RectF)} bounds of original bitmap without clipping, the rect 5165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * might be bigger than the image view<p> 5265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * - {@link #setClippedRect(RectF)} bounds of clipping<p> 5365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 5465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lanepublic class TransitionImage { 5565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 5665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private Uri mUri; 5765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private BitmapDrawable mBitmap; 5865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private final Rect mRect = new Rect(); 5965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private int mBackground = Color.TRANSPARENT; 6065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private float mAlpha = 1f; 6165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private float mSaturation = 1f; 626e995161147d9110d77ae1fe38b697e52891d3f2Tony Mantler private final RectF mUnclippedRect = new RectF(); 636e995161147d9110d77ae1fe38b697e52891d3f2Tony Mantler private final RectF mClippedRect = new RectF(); 6465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private boolean mUseClippedRectOnTransparent = true; 6565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 6665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public static final String EXTRA_TRANSITION_BITMAP = 6765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane "com.android.tv.settings.transition_bitmap"; 6865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public static final String EXTRA_TRANSITION_BITMAP_RECT = 6965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane "com.android.tv.settings.transition_bmp_rect"; 7065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public static final String EXTRA_TRANSITION_BITMAP_URI = 7165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane "com.android.tv.settings.transition_bmp_uri"; 7265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public static final String EXTRA_TRANSITION_BITMAP_ALPHA = 7365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane "com.android.tv.settings.transition_bmp_alpha"; 7465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public static final String EXTRA_TRANSITION_BITMAP_SATURATION = 7565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane "com.android.tv.settings.transition_bmp_saturation"; 7665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public static final String EXTRA_TRANSITION_BITMAP_BACKGROUND = 7765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane "com.android.tv.settings.transition_bmp_background"; 7865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public static final String EXTRA_TRANSITION_BITMAP_UNCLIPPED_RECT = 7965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane "com.android.tv.settings.transition_bmp_unclipped_rect"; 8065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public static final String EXTRA_TRANSITION_BITMAP_CLIPPED_RECT = 8165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane "com.android.tv.settings.transition_bmp_clipped_rect"; 8265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public static final String EXTRA_TRANSITION_MULTIPLE_BITMAP = 8365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane "com.android.tv.settings.transition_multiple_bitmap"; 8465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 8565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public TransitionImage() { 8665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 8765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 8865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public Uri getUri() { 8965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return mUri; 9065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 9165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 9265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void setUri(Uri uri) { 9365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mUri = uri; 9465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 9565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 9665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public BitmapDrawable getBitmap() { 9765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return mBitmap; 9865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 9965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 10065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void setBitmap(BitmapDrawable bitmap) { 10165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mBitmap = bitmap; 10265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 10365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 10465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public Rect getRect() { 10565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return mRect; 10665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 10765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 10865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void setRect(Rect rect) { 10965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mRect.set(rect); 11065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 11165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 11265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public int getBackground() { 11365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return mBackground; 11465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 11565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 11665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void setBackground(int color) { 11765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mBackground = color; 11865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 11965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 12065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public float getAlpha() { 12165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return mAlpha; 12265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 12365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 12465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void setAlpha(float alpha) { 12565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mAlpha = alpha; 12665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 12765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 12865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public float getSaturation() { 12965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return mSaturation; 13065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 13165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 13265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void setSaturation(float saturation) { 13365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mSaturation = saturation; 13465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 13565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 13665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public RectF getUnclippedRect() { 13765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return mUnclippedRect; 13865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 13965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 14065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void setUnclippedRect(RectF rect) { 14165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mUnclippedRect.set(rect); 14265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 14365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 14465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public RectF getClippedRect() { 14565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return mClippedRect; 14665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 14765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 14865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void setClippedRect(RectF rect) { 14965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mClippedRect.set(rect); 15065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 15165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 15265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public static List<TransitionImage> readMultipleFromIntent(Context context, Intent intent) { 1536e995161147d9110d77ae1fe38b697e52891d3f2Tony Mantler ArrayList<TransitionImage> transitions = new ArrayList<>(); 15465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Bundle extras = intent.getExtras(); 15565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (extras == null) { 15665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return transitions; 15765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 15865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane TransitionImage image = new TransitionImage(); 15965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (image.readFromBundle(context, intent.getSourceBounds(), extras)) { 16065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane transitions.add(image); 16165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 16265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Parcelable[] multiple = 16365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane intent.getParcelableArrayExtra(EXTRA_TRANSITION_MULTIPLE_BITMAP); 16465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (multiple != null) { 16565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane for (int i = 0, size = multiple.length; i < size; i++) { 16665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (!(multiple[i] instanceof Bundle)) { 16765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 16865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 16965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane image = new TransitionImage(); 17065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (image.readFromBundle(context, null, (Bundle) multiple[i])) { 17165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane transitions.add(image); 17265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 17365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 17465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 17565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return transitions; 17665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 17765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 17865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public static void writeMultipleToIntent(List<TransitionImage> transitions, Intent intent) { 17965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (transitions == null || transitions.size() == 0) { 18065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return; 18165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 18265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane int size = transitions.size(); 18365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (size == 1) { 18465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane TransitionImage image = transitions.get(0); 18565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane image.writeToIntent(intent); 18665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return; 18765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 18865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Parcelable[] multipleBundle = new Parcelable[size]; 18965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane for (int i = 0; i < size; i++) { 19065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Bundle b = new Bundle(); 19165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane transitions.get(i).writeToBundle(b); 19265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane multipleBundle[i] = b; 19365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 19465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane intent.putExtra(EXTRA_TRANSITION_MULTIPLE_BITMAP, multipleBundle); 19565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 19665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 19765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public boolean readFromBundle(Context context, Rect intentSourceBounds, Bundle bundle) { 19865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane setBitmap(null); 19965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (bundle == null) { 20065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return false; 20165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 20265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mUri = bundle.getParcelable(EXTRA_TRANSITION_BITMAP_URI); 20365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane BitmapDrawable bitmap = null; 20465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (mUri != null) { 20565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane DrawableDownloader downloader = DrawableDownloader.getInstance(context); 20665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane BitmapWorkerOptions key = new BitmapWorkerOptions.Builder(context) 20765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane .resource(mUri).build(); 2086e995161147d9110d77ae1fe38b697e52891d3f2Tony Mantler bitmap = downloader.getLargestBitmapFromMemCache(key); 20965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 21065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (bitmap == null) { 21165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (bundle.containsKey(EXTRA_TRANSITION_BITMAP)) { 21265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane bitmap = new BitmapDrawable(context.getResources(), 21365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ActivityTransitionBitmapHelper.getBitmapFromBinderBundle( 21465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane bundle.getBundle(EXTRA_TRANSITION_BITMAP))); 21565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 21665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (bitmap == null) { 21765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return false; 21865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 21965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 22065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Rect rect = null; 22165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane String bitmapRectStr = bundle.getString(EXTRA_TRANSITION_BITMAP_RECT); 22265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (!TextUtils.isEmpty(bitmapRectStr)) { 22365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane rect = Rect.unflattenFromString(bitmapRectStr); 22465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 22565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (rect == null) { 22665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane rect = intentSourceBounds; 22765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 22865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (rect == null) { 22965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return false; 23065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 23165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane setBitmap(bitmap); 23265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane setRect(rect); 23365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (!readRectF(bundle.getFloatArray(EXTRA_TRANSITION_BITMAP_CLIPPED_RECT), 23465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mClippedRect)) { 23565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mClippedRect.set(rect); 23665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 23765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (!readRectF(bundle.getFloatArray(EXTRA_TRANSITION_BITMAP_UNCLIPPED_RECT), 23865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mUnclippedRect)) { 23965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mUnclippedRect.set(rect); 24065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 24165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane setAlpha(bundle.getFloat(EXTRA_TRANSITION_BITMAP_ALPHA, 1f)); 24265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane setSaturation(bundle.getFloat(EXTRA_TRANSITION_BITMAP_SATURATION, 1f)); 24365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane setBackground(bundle.getInt(EXTRA_TRANSITION_BITMAP_BACKGROUND, 0)); 24465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return true; 24565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 24665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 24765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void writeToBundle(Bundle bundle) { 24865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane bundle.putParcelable(EXTRA_TRANSITION_BITMAP_URI, mUri); 24965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane bundle.putString(EXTRA_TRANSITION_BITMAP_RECT, mRect.flattenToString()); 25065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (mBitmap != null) { 25165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane bundle.putBundle(EXTRA_TRANSITION_BITMAP, 25265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ActivityTransitionBitmapHelper.bitmapAsBinderBundle(mBitmap.getBitmap())); 25365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 25465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane bundle.putFloatArray(EXTRA_TRANSITION_BITMAP_CLIPPED_RECT, 25565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane writeRectF(mClippedRect, new float[4])); 25665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane bundle.putFloatArray(EXTRA_TRANSITION_BITMAP_UNCLIPPED_RECT, 25765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane writeRectF(mUnclippedRect, new float[4])); 25865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane bundle.putFloat(EXTRA_TRANSITION_BITMAP_ALPHA, mAlpha); 25965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane bundle.putFloat(EXTRA_TRANSITION_BITMAP_SATURATION, mSaturation); 26065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane bundle.putInt(EXTRA_TRANSITION_BITMAP_BACKGROUND, mBackground); 26165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 26265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 26365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void writeToIntent(Intent intent) { 26465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane intent.setSourceBounds(mRect); 26565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane intent.putExtra(EXTRA_TRANSITION_BITMAP_URI, mUri); 26665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane intent.putExtra(EXTRA_TRANSITION_BITMAP_RECT, mRect.flattenToString()); 26765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (mBitmap != null) { 26865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane intent.putExtra(EXTRA_TRANSITION_BITMAP, 26965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ActivityTransitionBitmapHelper.bitmapAsBinderBundle(mBitmap.getBitmap())); 27065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 27165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane intent.putExtra(EXTRA_TRANSITION_BITMAP_CLIPPED_RECT, 27265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane writeRectF(mClippedRect, new float[4])); 27365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane intent.putExtra(EXTRA_TRANSITION_BITMAP_UNCLIPPED_RECT, 27465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane writeRectF(mUnclippedRect, new float[4])); 27565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane intent.putExtra(EXTRA_TRANSITION_BITMAP_ALPHA, mAlpha); 27665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane intent.putExtra(EXTRA_TRANSITION_BITMAP_SATURATION, mSaturation); 27765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane intent.putExtra(EXTRA_TRANSITION_BITMAP_BACKGROUND, mBackground); 27865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 27965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 28065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public static boolean readRectF(float[] values, RectF f) { 28165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (values == null || values.length != 4) { 28265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return false; 28365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 28465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane f.set(values[0], values[1], values[2], values[3]); 28565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return true; 28665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 28765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 28865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public static float[] writeRectF(RectF f, float[] values) { 28965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane values[0] = f.left; 29065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane values[1] = f.top; 29165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane values[2] = f.right; 29265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane values[3] = f.bottom; 29365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return values; 29465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 29565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 29665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane /** 29765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * set bounds and bitmap 29865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 29965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void createFromImageView(ImageView imageView) { 30065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane createFromImageView(imageView, imageView); 30165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 30265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 30365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane /** 30465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * set bounds and bitmap 30565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * 30665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * @param backgroundView background view can be larger than the image view that will 30765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * be drawn with background color 30865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 30965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void createFromImageView(ImageView view, View backgroundView) { 31065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Drawable drawable = view.getDrawable(); 31165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (drawable instanceof BitmapDrawable) { 31265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane setBitmap((BitmapDrawable) drawable); 31365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 31465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // use background View as the outside bounds and we can fill 31565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // background color in it 31665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mClippedRect.set(0, 0, backgroundView.getWidth(), backgroundView.getHeight()); 31765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane WindowLocationUtil.getLocationsInWindow(backgroundView, mClippedRect); 31865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mClippedRect.round(mRect); 31965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // get image view rects 32065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane WindowLocationUtil.getImageLocationsInWindow(view, mClippedRect, mUnclippedRect); 32165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 32265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 32365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane /** 32465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * set if background is transparent, set if we want to use {@link #setClippedRect(RectF)} 32565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * instead of {@link #setRect(Rect)}. Default value is true, and the value is not 32665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * serialized. User should call it before using TransitionImageAnimation. 32765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 32865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void setUseClippedRectOnTransparent(boolean ignoreBackground) { 32965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mUseClippedRectOnTransparent = ignoreBackground; 33065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 33165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 33265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane /** 33365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * get if background is not transparent, set if we want to use {@link #setClippedRect(RectF)} 33465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * instead of {@link #setRect(Rect)} 33565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 33665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public boolean getUseClippedRectOnTransparent() { 33765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return mUseClippedRectOnTransparent; 33865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 33965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 34065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane /** 34165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Get optimized rect depending on the background color 34265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 34365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void getOptimizedRect(Rect rect) { 34465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (mUseClippedRectOnTransparent && mBackground == Color.TRANSPARENT) { 34565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mClippedRect.round(rect); 34665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } else { 34765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane rect.set(mRect); 34865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 34965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 35065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 35165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane @Override 35265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public String toString() { 35365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return "{TransitionImage Uri=" + mUri + " rect=" + mRect 35465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane + " unclipRect=" + mUnclippedRect + " clipRect=" + mClippedRect 35565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane + " bitmap=" + mBitmap + " alpha=" + mAlpha + " saturation=" + mSaturation 35665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane + " background=" + mBackground; 35765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 35865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane} 359