/******************************************************************************* * Copyright 2009 Robot Media SL * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package net.robotmedia.acv.ui.widget; import android.content.Context; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.TransitionDrawable; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.view.animation.Animation; import android.view.animation.DecelerateInterpolator; import android.view.animation.ScaleAnimation; import android.view.animation.Animation.AnimationListener; import android.widget.RelativeLayout; public class Letterbox extends RelativeLayout { protected View mLetterboxTop; protected View mLetterboxBottom; protected View mLetterboxLeft; protected View mLetterboxRight; private int mLetterboxWidth; private int mLetterboxHeight; private int mColor; private View addLetterbox(Context context, int width, int height, int align) { final View letterbox = new View(context); final RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(width, height); params.addRule(align); letterbox.setLayoutParams(params); letterbox.setBackgroundColor(android.R.color.transparent); this.addView(letterbox); return letterbox; } private void init(Context context) { mLetterboxTop = addLetterbox(context, LayoutParams.FILL_PARENT, 1, RelativeLayout.ALIGN_PARENT_TOP); mLetterboxBottom = addLetterbox(context, LayoutParams.FILL_PARENT, 1, RelativeLayout.ALIGN_PARENT_BOTTOM); mLetterboxLeft = addLetterbox(context, 1, LayoutParams.FILL_PARENT, RelativeLayout.ALIGN_PARENT_LEFT); mLetterboxRight = addLetterbox(context, 1, LayoutParams.FILL_PARENT, RelativeLayout.ALIGN_PARENT_RIGHT); } public Letterbox(Context context) { super(context); init(context); } public Letterbox(Context context, AttributeSet attrs) { super(context, attrs); init(context); } private void layoutTop() { RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, mLetterboxHeight); params.addRule(RelativeLayout.ALIGN_PARENT_TOP); mLetterboxTop.setLayoutParams(params); mLetterboxTop.setBackgroundColor(mLetterboxHeight > 1 ? mColor : Color.TRANSPARENT); } private void layoutBottom() { RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, mLetterboxHeight); params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); mLetterboxBottom.setLayoutParams(params); mLetterboxBottom.setBackgroundColor(mLetterboxHeight > 1 ? mColor : Color.TRANSPARENT); } private void layoutLeft() { RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(mLetterboxWidth, ViewGroup.LayoutParams.FILL_PARENT); params.addRule(RelativeLayout.ALIGN_PARENT_LEFT); mLetterboxLeft.setLayoutParams(params); mLetterboxLeft.setBackgroundColor(mLetterboxWidth > 1 ? mColor : Color.TRANSPARENT); } private void layoutRight() { RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(mLetterboxWidth, ViewGroup.LayoutParams.FILL_PARENT); params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); mLetterboxRight.setLayoutParams(params); mLetterboxRight.setBackgroundColor(mLetterboxWidth > 1 ? mColor : Color.TRANSPARENT); } private void configureAndStart(View target, Animation animation, long duration) { Drawable background = target.getBackground(); animation.setInterpolator(new DecelerateInterpolator()); animation.setDuration(duration); target.startAnimation(animation); if (background instanceof TransitionDrawable) { ((TransitionDrawable) background).startTransition((int)duration); } } private void animateTop(long duration) { // Utils.logFrame("top", mLetterboxTop); float topScale = (float) mLetterboxHeight / (float) mLetterboxTop.getHeight(); ScaleAnimation topAnimation = new ScaleAnimation(1, 1, 1, topScale, 0, 0); topAnimation.setAnimationListener(new AnimationListener() { public void onAnimationEnd(Animation animation) { mLetterboxTop.clearAnimation(); // TODO: Find out why is this needed. layoutTop(); } public void onAnimationRepeat(Animation animation) {} public void onAnimationStart(Animation animation) {}} ); configureAndStart(mLetterboxTop, topAnimation, duration); } private void animateBottom(long duration) { // Utils.logFrame("bottom", mLetterboxBottom); float topScale = (float) mLetterboxHeight / (float) mLetterboxTop.getHeight(); ScaleAnimation bottomAnimation = new ScaleAnimation(1, 1, 1, topScale, 0, mLetterboxBottom.getHeight()); bottomAnimation.setAnimationListener(new AnimationListener() { public void onAnimationEnd(Animation animation) { mLetterboxBottom.clearAnimation(); layoutBottom(); } public void onAnimationRepeat(Animation animation) {} public void onAnimationStart(Animation animation) {}} ); configureAndStart(mLetterboxBottom, bottomAnimation, duration); } private void animateLeft(long duration) { // Utils.logFrame("left", mLetterboxLeft); float leftScale = (float) mLetterboxWidth / (float) mLetterboxLeft.getWidth(); ScaleAnimation leftAnimation = new ScaleAnimation(1, leftScale, 1, 1, 0, 0); leftAnimation.setAnimationListener(new AnimationListener() { public void onAnimationEnd(Animation animation) { mLetterboxLeft.clearAnimation(); layoutLeft(); } public void onAnimationRepeat(Animation animation) {} public void onAnimationStart(Animation animation) {}} ); configureAndStart(mLetterboxLeft, leftAnimation, duration); } private void animateRight(long duration) { // Utils.logFrame("right", mLetterboxRight); float leftScale = (float) mLetterboxWidth / (float) mLetterboxLeft.getWidth(); ScaleAnimation rightAnimation = new ScaleAnimation(1, leftScale, 1, 1, mLetterboxRight.getWidth(), 0); rightAnimation.setAnimationListener(new AnimationListener() { public void onAnimationEnd(Animation animation) { mLetterboxRight.clearAnimation(); layoutRight(); } public void onAnimationRepeat(Animation animation) {} public void onAnimationStart(Animation animation) {}} ); configureAndStart(mLetterboxRight, rightAnimation, duration); } /** * Hides the letterbox. * @param animated Not implemented yet. */ public void hide(boolean animated) { // TODO: Implement animation. Just changing the duration does not work when the user is scrolling. show(getWidth(), getHeight(), Color.TRANSPARENT, 0); } /** * Shows a letterbox for the given area with the given color. The area is assumed to be centered. * @param width Width of the area that the letterbox will surround. * @param height Height of the area that the letterbox wil surround. * @param color Color of the letterbox. * @param duration Duration of the animation in miliseconds. */ public void show(int width, int height, int color, long duration) { final ColorDrawable initialColor = new ColorDrawable(mColor); final ColorDrawable finalColor = new ColorDrawable(color); final TransitionDrawable backgroundTransition = new TransitionDrawable(new Drawable[] {initialColor, finalColor}); final int previousWidth = mLetterboxWidth; final int previousHeight = mLetterboxHeight; mLetterboxWidth = Math.max(1, (getWidth() - width) / 2); mLetterboxHeight = Math.max(1, (getHeight() - height) / 2); if (mLetterboxWidth <= 1 && previousWidth <= 1) { mLetterboxLeft.setBackgroundColor(Color.TRANSPARENT); mLetterboxRight.setBackgroundColor(Color.TRANSPARENT); } else { mLetterboxLeft.setBackgroundDrawable(backgroundTransition); mLetterboxRight.setBackgroundDrawable(backgroundTransition); } if (mLetterboxHeight <= 1 && previousHeight <= 1) { mLetterboxTop.setBackgroundColor(Color.TRANSPARENT); mLetterboxBottom.setBackgroundColor(Color.TRANSPARENT); } else { mLetterboxTop.setBackgroundDrawable(backgroundTransition); mLetterboxBottom.setBackgroundDrawable(backgroundTransition); } mColor = color; if (duration > 0) { animateTop(duration); animateBottom(duration); animateLeft(duration); animateRight(duration); } else { layoutTop(); layoutBottom(); layoutLeft(); layoutRight(); } } }