blob: 3bb274b96459338c427e17e6dd70745898384c7d [file] [log] [blame]
/*
* Copyright (C) 2016 The Android Open Source Project
*
* 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 com.android.car.media;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.support.car.ui.AnimationListenerAdapter;
import android.support.car.ui.LogDecelerateInterpolator;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.FrameLayout;
import android.widget.ImageView;
/**
* A view where updating the image will show certain animations. Current animations include fading
* in and scaling down the new image.
*/
public class CrossfadeImageView extends FrameLayout {
// ColorFilters can't currently be modified (b/17262092) so creating a saturation fade with
// color filters would normally require creating a ton of small objects. We get around this by
// caching color filters and limit the saturation to increments of 0.1.
// 0-0.09 -> [0]
// 0.10-0.19 -> [1]
// ...
// 1.0 -> [10]
private final ColorFilter[] mSaturationColorFilters = new ColorFilter[11];
private final ColorMatrix mColorMatrix = new ColorMatrix();
private final ImageView mImageView1;
private final ImageView mImageView2;
private ImageView mActiveImageView;
private ImageView mInactiveImageView;
private Bitmap mCurrentBitmap = null;
private Integer mCurrentColor = null;
private Animation mImageInAnimation;
private Animation mImageOutAnimation;
public CrossfadeImageView(Context context) {
this(context, null);
}
public CrossfadeImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CrossfadeImageView(Context context, AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
public CrossfadeImageView(Context context, AttributeSet attrs,
int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
LayoutParams lp = new LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
ImageView imageViewBackground = new ImageView(context, attrs, defStyleAttr, defStyleRes);
imageViewBackground.setLayoutParams(lp);
imageViewBackground.setBackgroundColor(Color.BLACK);
addView(imageViewBackground);
mImageView1 = new ImageView(context, attrs, defStyleAttr, defStyleRes);
mImageView1.setLayoutParams(lp);
addView(mImageView1);
mImageView2 = new ImageView(context, attrs, defStyleAttr, defStyleRes);
mImageView2.setLayoutParams(lp);
addView(mImageView2);
mActiveImageView = mImageView1;
mInactiveImageView = mImageView2;
mImageInAnimation = AnimationUtils.loadAnimation(context, R.anim.image_in);
mImageInAnimation.setInterpolator(new LogDecelerateInterpolator(100, 0));
mImageOutAnimation = AnimationUtils.loadAnimation(context, R.anim.image_out);
}
public void setImageBitmap(Bitmap bitmap, boolean showAnimation) {
if (bitmap != null && bitmap.sameAs(mCurrentBitmap)) {
return;
}
mCurrentBitmap = bitmap;
mCurrentColor = null;
mInactiveImageView.setImageBitmap(bitmap);
if (showAnimation) {
animateViews();
} else {
mActiveImageView.setImageBitmap(bitmap);
}
}
@Override
public void setBackgroundColor(int color) {
if (mCurrentColor != null && mCurrentColor == color) {
return;
}
mInactiveImageView.setImageBitmap(null);
mCurrentBitmap = null;
mCurrentColor = color;
mInactiveImageView.setBackgroundColor(color);
animateViews();
}
public void setSaturation(float saturation) {
int i = (int) ((saturation * 100) / 10);
ColorFilter cf = mSaturationColorFilters[i];
if (cf == null) {
mColorMatrix.setSaturation((10 * i) / 100f);
cf = new ColorMatrixColorFilter(mColorMatrix);
mSaturationColorFilters[i] = cf;
}
mImageView1.setColorFilter(cf);
mImageView2.setColorFilter(cf);
}
private final Animation.AnimationListener mAnimationListener = new AnimationListenerAdapter() {
@Override
public void onAnimationEnd(Animation animation) {
if (mInactiveImageView != null) {
mInactiveImageView.setVisibility(View.GONE);
}
}
};
private void animateViews() {
mInactiveImageView.setVisibility(View.VISIBLE);
mInactiveImageView.startAnimation(mImageInAnimation);
mInactiveImageView.bringToFront();
mActiveImageView.startAnimation(mImageOutAnimation);
mImageOutAnimation.setAnimationListener(mAnimationListener);
if (mActiveImageView == mImageView1) {
mActiveImageView = mImageView2;
mInactiveImageView = mImageView1;
} else {
mActiveImageView = mImageView1;
mInactiveImageView = mImageView2;
}
}
}