FileDocCategorySizeDatePackage
NotificationContentView.javaAPI DocAndroid 5.1 API9508Thu Mar 12 22:22:42 GMT 2015com.android.systemui.statusbar

NotificationContentView

public class NotificationContentView extends android.widget.FrameLayout
A frame layout containing the actual payload of the notification, including the contracted and expanded layout. This class is responsible for clipping the content and and switching between the expanded and contracted view depending on its clipped size.

Fields Summary
private static final long
ANIMATION_DURATION_LENGTH
private final android.graphics.Rect
mClipBounds
private android.view.View
mContractedChild
private android.view.View
mExpandedChild
private NotificationViewWrapper
mContractedWrapper
private int
mSmallHeight
private int
mClipTopAmount
private int
mActualHeight
private final android.view.animation.Interpolator
mLinearInterpolator
private boolean
mContractedVisible
private boolean
mDark
private final android.graphics.Paint
mFadePaint
private boolean
mAnimate
private ViewTreeObserver.OnPreDrawListener
mEnableAnimationPredrawListener
Constructors Summary
public NotificationContentView(android.content.Context context, android.util.AttributeSet attrs)


         
        super(context, attrs);
        mFadePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD));
        reset(true);
    
Methods Summary
public android.view.ViewgetContractedChild()

        return mContractedChild;
    
public android.view.ViewgetExpandedChild()

        return mExpandedChild;
    
public intgetMaxHeight()


        // The maximum height is just the laid out height.
        return getHeight();
    
public intgetMinHeight()

        return mSmallHeight;
    
public booleanhasOverlappingRendering()


        // This is not really true, but good enough when fading from the contracted to the expanded
        // layout, and saves us some layers.
        return false;
    
public booleanisContentExpandable()

        return mExpandedChild != null;
    
public voidnotifyContentUpdated()

        selectLayout(false /* animate */, true /* force */);
        if (mContractedChild != null) {
            mContractedWrapper.notifyContentUpdated();
            mContractedWrapper.setDark(mDark, false /* animate */, 0 /* delay */);
        }
    
protected voidonAttachedToWindow()

        super.onAttachedToWindow();
        updateVisibility();
    
protected voidonLayout(boolean changed, int left, int top, int right, int bottom)

        super.onLayout(changed, left, top, right, bottom);
        updateClipping();
    
protected voidonVisibilityChanged(android.view.View changedView, int visibility)

        super.onVisibilityChanged(changedView, visibility);
        updateVisibility();
    
public voidreset(boolean resetActualHeight)

        if (mContractedChild != null) {
            mContractedChild.animate().cancel();
        }
        if (mExpandedChild != null) {
            mExpandedChild.animate().cancel();
        }
        removeAllViews();
        mContractedChild = null;
        mExpandedChild = null;
        mSmallHeight = getResources().getDimensionPixelSize(R.dimen.notification_min_height);
        mContractedVisible = true;
        if (resetActualHeight) {
            mActualHeight = mSmallHeight;
        }
    
private voidrunSwitchAnimation(boolean showContractedChild)

        mContractedChild.setVisibility(View.VISIBLE);
        mExpandedChild.setVisibility(View.VISIBLE);
        mContractedChild.setLayerType(LAYER_TYPE_HARDWARE, mFadePaint);
        mExpandedChild.setLayerType(LAYER_TYPE_HARDWARE, mFadePaint);
        setLayerType(LAYER_TYPE_HARDWARE, null);
        mContractedChild.animate()
                .alpha(showContractedChild ? 1f : 0f)
                .setDuration(ANIMATION_DURATION_LENGTH)
                .setInterpolator(mLinearInterpolator);
        mExpandedChild.animate()
                .alpha(showContractedChild ? 0f : 1f)
                .setDuration(ANIMATION_DURATION_LENGTH)
                .setInterpolator(mLinearInterpolator)
                .withEndAction(new Runnable() {
                    @Override
                    public void run() {
                        mContractedChild.setLayerType(LAYER_TYPE_NONE, null);
                        mExpandedChild.setLayerType(LAYER_TYPE_NONE, null);
                        setLayerType(LAYER_TYPE_NONE, null);
                        mContractedChild.setVisibility(showContractedChild
                                ? View.VISIBLE
                                : View.INVISIBLE);
                        mExpandedChild.setVisibility(showContractedChild
                                ? View.INVISIBLE
                                : View.VISIBLE);
                    }
                });
    
private voidsanitizeContractedLayoutParams(android.view.View contractedChild)

        LayoutParams lp = (LayoutParams) contractedChild.getLayoutParams();
        lp.height = mSmallHeight;
        contractedChild.setLayoutParams(lp);
    
private voidselectLayout(boolean animate, boolean force)

        if (mContractedChild == null) {
            return;
        }
        boolean showContractedChild = showContractedChild();
        if (showContractedChild != mContractedVisible || force) {
            if (animate && mExpandedChild != null) {
                runSwitchAnimation(showContractedChild);
            } else if (mExpandedChild != null) {
                mContractedChild.setVisibility(showContractedChild ? View.VISIBLE : View.INVISIBLE);
                mContractedChild.setAlpha(showContractedChild ? 1f : 0f);
                mExpandedChild.setVisibility(showContractedChild ? View.INVISIBLE : View.VISIBLE);
                mExpandedChild.setAlpha(showContractedChild ? 0f : 1f);
            }
        }
        mContractedVisible = showContractedChild;
    
public voidsetActualHeight(int actualHeight)

        mActualHeight = actualHeight;
        selectLayout(mAnimate /* animate */, false /* force */);
        updateClipping();
    
public voidsetClipTopAmount(int clipTopAmount)

        mClipTopAmount = clipTopAmount;
        updateClipping();
    
public voidsetContractedChild(android.view.View child)

        if (mContractedChild != null) {
            mContractedChild.animate().cancel();
            removeView(mContractedChild);
        }
        sanitizeContractedLayoutParams(child);
        addView(child);
        mContractedChild = child;
        mContractedWrapper = NotificationViewWrapper.wrap(getContext(), child);
        selectLayout(false /* animate */, true /* force */);
        mContractedWrapper.setDark(mDark, false /* animate */, 0 /* delay */);
    
public voidsetDark(boolean dark, boolean fade, long delay)

        if (mDark == dark || mContractedChild == null) return;
        mDark = dark;
        mContractedWrapper.setDark(dark, fade, delay);
    
public voidsetExpandedChild(android.view.View child)

        if (mExpandedChild != null) {
            mExpandedChild.animate().cancel();
            removeView(mExpandedChild);
        }
        addView(child);
        mExpandedChild = child;
        selectLayout(false /* animate */, true /* force */);
    
private voidsetVisible(boolean isVisible)

        if (isVisible) {

            // We only animate if we are drawn at least once, otherwise the view might animate when
            // it's shown the first time
            getViewTreeObserver().addOnPreDrawListener(mEnableAnimationPredrawListener);
        } else {
            getViewTreeObserver().removeOnPreDrawListener(mEnableAnimationPredrawListener);
            mAnimate = false;
        }
    
private booleanshowContractedChild()

        return mActualHeight <= mSmallHeight || mExpandedChild == null;
    
private voidupdateClipping()

        mClipBounds.set(0, mClipTopAmount, getWidth(), mActualHeight);
        setClipBounds(mClipBounds);
    
private voidupdateVisibility()

        setVisible(isShown());