FileDocCategorySizeDatePackage
PrintContentView.javaAPI DocAndroid 5.1 API17577Thu Mar 12 22:22:42 GMT 2015com.android.printspooler.widget

PrintContentView

public final class PrintContentView extends android.view.ViewGroup implements View.OnClickListener
This class is a layout manager for the print screen. It has a sliding area that contains the print options. If the sliding area is open the print options are visible and if it is closed a summary of the print job is shown. Under the sliding area there is a place for putting arbitrary content such as preview, error message, progress indicator, etc. The sliding area is covering the content holder under it when the former is opened.

Fields Summary
private static final int
FIRST_POINTER_ID
private static final int
ALPHA_MASK
private static final int
ALPHA_SHIFT
private static final int
COLOR_MASK
private final android.support.v4.widget.ViewDragHelper
mDragger
private final int
mScrimColor
private android.view.View
mStaticContent
private android.view.ViewGroup
mSummaryContent
private android.view.View
mDynamicContent
private android.view.View
mDraggableContent
private android.view.View
mPrintButton
private android.view.View
mMoreOptionsButton
private android.view.ViewGroup
mOptionsContainer
private android.view.View
mEmbeddedContentContainer
private android.view.View
mEmbeddedContentScrim
private android.view.View
mExpandCollapseHandle
private android.view.View
mExpandCollapseIcon
private int
mClosedOptionsOffsetY
private int
mCurrentOptionsOffsetY
private OptionsStateChangeListener
mOptionsStateChangeListener
private OptionsStateController
mOptionsStateController
private int
mOldDraggableHeight
private float
mDragProgress
Constructors Summary
public PrintContentView(android.content.Context context, android.util.AttributeSet attrs)


       
          
          
    

       
          
          
    

         
        super(context, attrs);
        mDragger = ViewDragHelper.create(this, new DragCallbacks());

        mScrimColor = context.getResources().getColor(R.color.print_preview_scrim_color);

        // The options view is sliding under the static header but appears
        // after it in the layout, so we will draw in opposite order.
        setChildrenDrawingOrderEnabled(true);
    
Methods Summary
public voidcloseOptions()

        if (isOptionsClosed()) {
            return;
        }
        mDragger.smoothSlideViewTo(mDynamicContent, mDynamicContent.getLeft(),
                getClosedOptionsY());
        invalidate();
    
private intcomputeScrimColor()

        final int baseAlpha = (mScrimColor & ALPHA_MASK) >>> ALPHA_SHIFT;
        final int adjustedAlpha = (int) (baseAlpha * (1 - mDragProgress));
        return adjustedAlpha << ALPHA_SHIFT | (mScrimColor & COLOR_MASK);
    
public voidcomputeScroll()

        if (mDragger.continueSettling(true)) {
            postInvalidateOnAnimation();
        }
    
private voidensureImeClosedAndInputFocusCleared()

        View focused = findFocus();

        if (focused != null && focused.isFocused()) {
            InputMethodManager imm = (InputMethodManager) mContext.getSystemService(
                    Context.INPUT_METHOD_SERVICE);
            if (imm.isActive(focused)) {
                imm.hideSoftInputFromWindow(getWindowToken(), 0);
            }
            focused.clearFocus();
        }
    
public voidfocusableViewAvailable(android.view.View v)

        // The framework gives focus to the frist focusable and we
        // do not want that, hence do not announce new focusables.
        return;
    
public LayoutParamsgenerateLayoutParams(android.util.AttributeSet attrs)

        return new ViewGroup.MarginLayoutParams(getContext(), attrs);
    
protected intgetChildDrawingOrder(int childCount, int i)

        return childCount - i - 1;
    
private intgetClosedOptionsY()

        return getOpenedOptionsY() + mClosedOptionsOffsetY;
    
private intgetOpenedOptionsY()

        return mStaticContent.getBottom();
    
private booleanisOptionsClosed()

        return mCurrentOptionsOffsetY == mClosedOptionsOffsetY;
    
public booleanisOptionsOpened()

        return mCurrentOptionsOffsetY == 0;
    
public voidonClick(android.view.View view)

        if (view == mExpandCollapseHandle || view == mSummaryContent) {
            if (isOptionsClosed() && mOptionsStateController.canOpenOptions()) {
                openOptions();
            } else if (isOptionsOpened() && mOptionsStateController.canCloseOptions()) {
                closeOptions();
            } // else in open/close progress do nothing.
        } else if (view == mEmbeddedContentScrim) {
            if (isOptionsOpened() && mOptionsStateController.canCloseOptions()) {
                closeOptions();
            }
        }
    
private voidonDragProgress(float progress)

        if (Float.compare(mDragProgress, progress) == 0) {
            return;
        }

        if ((mDragProgress == 0 && progress > 0)
                || (mDragProgress == 1.0f && progress < 1.0f)) {
            mSummaryContent.setLayerType(View.LAYER_TYPE_HARDWARE, null);
            mDraggableContent.setLayerType(View.LAYER_TYPE_HARDWARE, null);
            mMoreOptionsButton.setLayerType(View.LAYER_TYPE_HARDWARE, null);
            ensureImeClosedAndInputFocusCleared();
        }
        if ((mDragProgress > 0 && progress == 0)
                || (mDragProgress < 1.0f && progress == 1.0f)) {
            mSummaryContent.setLayerType(View.LAYER_TYPE_NONE, null);
            mDraggableContent.setLayerType(View.LAYER_TYPE_NONE, null);
            mMoreOptionsButton.setLayerType(View.LAYER_TYPE_NONE, null);
            mMoreOptionsButton.setLayerType(View.LAYER_TYPE_NONE, null);
        }

        mDragProgress = progress;

        mSummaryContent.setAlpha(progress);

        final float inverseAlpha = 1.0f - progress;
        mOptionsContainer.setAlpha(inverseAlpha);
        mMoreOptionsButton.setAlpha(inverseAlpha);

        mEmbeddedContentScrim.setBackgroundColor(computeScrimColor());
        if (progress == 0) {
            if (mOptionsStateChangeListener != null) {
                mOptionsStateChangeListener.onOptionsOpened();
            }
            mExpandCollapseHandle.setContentDescription(
                    mContext.getString(R.string.collapse_handle));
            announceForAccessibility(mContext.getString(R.string.print_options_expanded));
            mSummaryContent.setVisibility(View.GONE);
            mEmbeddedContentScrim.setOnClickListener(this);
            mExpandCollapseIcon.setBackgroundResource(R.drawable.ic_expand_less);
        } else {
            mSummaryContent.setVisibility(View.VISIBLE);
        }

        if (progress == 1.0f) {
            if (mOptionsStateChangeListener != null) {
                mOptionsStateChangeListener.onOptionsClosed();
            }
            mExpandCollapseHandle.setContentDescription(
                    mContext.getString(R.string.expand_handle));
            announceForAccessibility(mContext.getString(R.string.print_options_collapsed));
            if (mMoreOptionsButton.getVisibility() != View.GONE) {
                mMoreOptionsButton.setVisibility(View.INVISIBLE);
            }
            mDraggableContent.setVisibility(View.INVISIBLE);
            // If we change the scrim visibility the dimming is lagging
            // and is janky. Now it is there but transparent, doing nothing.
            mEmbeddedContentScrim.setOnClickListener(null);
            mEmbeddedContentScrim.setClickable(false);
            mExpandCollapseIcon.setBackgroundResource(R.drawable.ic_expand_more);
        } else {
            if (mMoreOptionsButton.getVisibility() != View.GONE) {
                mMoreOptionsButton.setVisibility(View.VISIBLE);
            }
            mDraggableContent.setVisibility(View.VISIBLE);
        }
    
protected voidonFinishInflate()

        mStaticContent = findViewById(R.id.static_content);
        mSummaryContent = (ViewGroup) findViewById(R.id.summary_content);
        mDynamicContent = findViewById(R.id.dynamic_content);
        mDraggableContent = findViewById(R.id.draggable_content);
        mPrintButton = findViewById(R.id.print_button);
        mMoreOptionsButton = findViewById(R.id.more_options_button);
        mOptionsContainer = (ViewGroup) findViewById(R.id.options_container);
        mEmbeddedContentContainer = findViewById(R.id.embedded_content_container);
        mEmbeddedContentScrim = findViewById(R.id.embedded_content_scrim);
        mExpandCollapseHandle = findViewById(R.id.expand_collapse_handle);
        mExpandCollapseIcon = findViewById(R.id.expand_collapse_icon);

        mExpandCollapseHandle.setOnClickListener(this);
        mSummaryContent.setOnClickListener(this);

        // Make sure we start in a closed options state.
        onDragProgress(1.0f);

        // The framework gives focus to the frist focusable and we
        // do not want that, hence we will take focus instead.
        setFocusableInTouchMode(true);
    
public booleanonInterceptTouchEvent(android.view.MotionEvent event)

        return mDragger.shouldInterceptTouchEvent(event)
                || super.onInterceptTouchEvent(event);
    
protected voidonLayout(boolean changed, int left, int top, int right, int bottom)

        mStaticContent.layout(left, top, right, mStaticContent.getMeasuredHeight());

        if (mSummaryContent.getVisibility() != View.GONE) {
            mSummaryContent.layout(left, mStaticContent.getMeasuredHeight(), right,
                    mStaticContent.getMeasuredHeight() + mSummaryContent.getMeasuredHeight());
        }

        final int dynContentTop = mStaticContent.getMeasuredHeight() + mCurrentOptionsOffsetY;
        final int dynContentBottom = dynContentTop + mDynamicContent.getMeasuredHeight();

        mDynamicContent.layout(left, dynContentTop, right, dynContentBottom);

        MarginLayoutParams params = (MarginLayoutParams) mPrintButton.getLayoutParams();

        final int printButtonLeft;
        if (getLayoutDirection() == View.LAYOUT_DIRECTION_LTR) {
            printButtonLeft = right - mPrintButton.getMeasuredWidth() - params.getMarginStart();
        } else {
            printButtonLeft = left + params.getMarginStart();
        }
        final int printButtonTop = dynContentBottom - mPrintButton.getMeasuredHeight() / 2;
        final int printButtonRight = printButtonLeft + mPrintButton.getMeasuredWidth();
        final int printButtonBottom = printButtonTop + mPrintButton.getMeasuredHeight();

        mPrintButton.layout(printButtonLeft, printButtonTop, printButtonRight, printButtonBottom);

        final int embContentTop = mStaticContent.getMeasuredHeight() + mClosedOptionsOffsetY
                + mDynamicContent.getMeasuredHeight();
        final int embContentBottom = embContentTop + mEmbeddedContentContainer.getMeasuredHeight();

        mEmbeddedContentContainer.layout(left, embContentTop, right, embContentBottom);
    
protected voidonMeasure(int widthMeasureSpec, int heightMeasureSpec)

        final boolean wasOpened = isOptionsOpened();

        measureChild(mStaticContent, widthMeasureSpec, heightMeasureSpec);

        if (mSummaryContent.getVisibility() != View.GONE) {
            measureChild(mSummaryContent, widthMeasureSpec, heightMeasureSpec);
        }

        measureChild(mDynamicContent, widthMeasureSpec, heightMeasureSpec);

        measureChild(mPrintButton, widthMeasureSpec, heightMeasureSpec);

        // The height of the draggable content may change and if that happens
        // we have to adjust the sliding area closed state offset.
        mClosedOptionsOffsetY = mSummaryContent.getMeasuredHeight()
                - mDraggableContent.getMeasuredHeight();

        if (mCurrentOptionsOffsetY == Integer.MIN_VALUE) {
            mCurrentOptionsOffsetY = mClosedOptionsOffsetY;
        }

        final int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        // The content host must be maximally large size that fits entirely
        // on the screen when the options are collapsed.
        ViewGroup.LayoutParams params = mEmbeddedContentContainer.getLayoutParams();
        params.height = heightSize - mStaticContent.getMeasuredHeight()
                - mSummaryContent.getMeasuredHeight() - mDynamicContent.getMeasuredHeight()
                + mDraggableContent.getMeasuredHeight();

        // The height of the draggable content may change and if that happens
        // we have to adjust the current offset to ensure the sliding area is
        // at the correct position.
        if (mOldDraggableHeight != mDraggableContent.getMeasuredHeight()) {
            if (mOldDraggableHeight != 0) {
                mCurrentOptionsOffsetY = wasOpened ? 0 : mClosedOptionsOffsetY;
            }
            mOldDraggableHeight = mDraggableContent.getMeasuredHeight();
        }

        // The content host can grow vertically as much as needed - we will be covering it.
        final int hostHeightMeasureSpec = MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, 0);
        measureChild(mEmbeddedContentContainer, widthMeasureSpec, hostHeightMeasureSpec);

        setMeasuredDimension(resolveSize(MeasureSpec.getSize(widthMeasureSpec), widthMeasureSpec),
                resolveSize(heightSize, heightMeasureSpec));
    
public booleanonTouchEvent(android.view.MotionEvent event)

        mDragger.processTouchEvent(event);
        return true;
    
public voidopenOptions()

        if (isOptionsOpened()) {
            return;
        }
        mDragger.smoothSlideViewTo(mDynamicContent, mDynamicContent.getLeft(),
                getOpenedOptionsY());
        invalidate();
    
public voidrequestDisallowInterceptTouchEvent(boolean disallowIntercept)

        /* do nothing */
    
public voidsetOpenOptionsController(com.android.printspooler.widget.PrintContentView$OptionsStateController controller)

        mOptionsStateController = controller;
    
public voidsetOptionsStateChangeListener(com.android.printspooler.widget.PrintContentView$OptionsStateChangeListener listener)

        mOptionsStateChangeListener = listener;