blob: 68cf51c04d4b94c8b30376069f05f505fa798b7e [file] [log] [blame]
/*
* Copyright (C) 2014 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.systemui.statusbar;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Canvas;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.LayerDrawable;
import android.graphics.drawable.RippleDrawable;
import android.util.AttributeSet;
import android.view.View;
import com.android.systemui.R;
/**
* A view that can be used for both the dimmed and normal background of an notification.
*/
public class NotificationBackgroundView extends View {
private final boolean mDontModifyCorners;
private Drawable mBackground;
private int mClipTopAmount;
private int mActualHeight;
private int mClipBottomAmount;
private int mTintColor;
private float[] mCornerRadii = new float[8];
private int mCurrentSidePaddings;
private boolean mBottomIsRounded;
private int mBackgroundTop;
private boolean mBottomAmountClips = true;
public NotificationBackgroundView(Context context, AttributeSet attrs) {
super(context, attrs);
mDontModifyCorners = getResources().getBoolean(
R.bool.config_clipNotificationsToOutline);
}
@Override
protected void onDraw(Canvas canvas) {
if (mClipTopAmount + mClipBottomAmount < mActualHeight - mBackgroundTop) {
canvas.save();
canvas.clipRect(0, mClipTopAmount, getWidth(), mActualHeight - mClipBottomAmount);
draw(canvas, mBackground);
canvas.restore();
}
}
private void draw(Canvas canvas, Drawable drawable) {
if (drawable != null) {
int bottom = mActualHeight;
if (mBottomIsRounded && mBottomAmountClips) {
bottom -= mClipBottomAmount;
}
drawable.setBounds(mCurrentSidePaddings, mBackgroundTop,
getWidth() - mCurrentSidePaddings, bottom);
drawable.draw(canvas);
}
}
@Override
protected boolean verifyDrawable(Drawable who) {
return super.verifyDrawable(who) || who == mBackground;
}
@Override
protected void drawableStateChanged() {
drawableStateChanged(mBackground);
}
private void drawableStateChanged(Drawable d) {
if (d != null && d.isStateful()) {
d.setState(getDrawableState());
}
}
@Override
public void drawableHotspotChanged(float x, float y) {
if (mBackground != null) {
mBackground.setHotspot(x, y);
}
}
/**
* Sets a background drawable. As we need to change our bounds independently of layout, we need
* the notion of a background independently of the regular View background..
*/
public void setCustomBackground(Drawable background) {
if (mBackground != null) {
mBackground.setCallback(null);
unscheduleDrawable(mBackground);
}
mBackground = background;
mBackground.mutate();
if (mBackground != null) {
mBackground.setCallback(this);
setTint(mTintColor);
}
if (mBackground instanceof RippleDrawable) {
((RippleDrawable) mBackground).setForceSoftware(true);
}
updateBackgroundRadii();
invalidate();
}
public void setCustomBackground(int drawableResId) {
final Drawable d = mContext.getDrawable(drawableResId);
setCustomBackground(d);
}
public void setTint(int tintColor) {
if (tintColor != 0) {
mBackground.setColorFilter(tintColor, PorterDuff.Mode.SRC_ATOP);
} else {
mBackground.clearColorFilter();
}
mTintColor = tintColor;
invalidate();
}
public void setActualHeight(int actualHeight) {
mActualHeight = actualHeight;
invalidate();
}
public int getActualHeight() {
return mActualHeight;
}
public void setClipTopAmount(int clipTopAmount) {
mClipTopAmount = clipTopAmount;
invalidate();
}
public void setClipBottomAmount(int clipBottomAmount) {
mClipBottomAmount = clipBottomAmount;
invalidate();
}
@Override
public boolean hasOverlappingRendering() {
// Prevents this view from creating a layer when alpha is animating.
return false;
}
public void setState(int[] drawableState) {
mBackground.setState(drawableState);
}
public void setRippleColor(int color) {
if (mBackground instanceof RippleDrawable) {
RippleDrawable ripple = (RippleDrawable) mBackground;
ripple.setColor(ColorStateList.valueOf(color));
}
}
public void setDrawableAlpha(int drawableAlpha) {
mBackground.setAlpha(drawableAlpha);
}
public void setRoundness(float topRoundness, float bottomRoundNess) {
mBottomIsRounded = bottomRoundNess != 0.0f;
mCornerRadii[0] = topRoundness;
mCornerRadii[1] = topRoundness;
mCornerRadii[2] = topRoundness;
mCornerRadii[3] = topRoundness;
mCornerRadii[4] = bottomRoundNess;
mCornerRadii[5] = bottomRoundNess;
mCornerRadii[6] = bottomRoundNess;
mCornerRadii[7] = bottomRoundNess;
updateBackgroundRadii();
}
public void setBottomAmountClips(boolean clips) {
if (clips != mBottomAmountClips) {
mBottomAmountClips = clips;
invalidate();
}
}
private void updateBackgroundRadii() {
if (mDontModifyCorners) {
return;
}
if (mBackground instanceof LayerDrawable) {
GradientDrawable gradientDrawable =
(GradientDrawable) ((LayerDrawable) mBackground).getDrawable(0);
gradientDrawable.setCornerRadii(mCornerRadii);
}
}
public void setCurrentSidePaddings(float currentSidePaddings) {
mCurrentSidePaddings = (int) currentSidePaddings;
invalidate();
}
public void setBackgroundTop(int backgroundTop) {
mBackgroundTop = backgroundTop;
invalidate();
}
}