Example usage for android.graphics Canvas clipRect

List of usage examples for android.graphics Canvas clipRect

Introduction

In this page you can find the example usage for android.graphics Canvas clipRect.

Prototype

public boolean clipRect(int left, int top, int right, int bottom) 

Source Link

Document

Intersect the current clip with the specified rectangle, which is expressed in local coordinates.

Usage

From source file:com.lovely3x.eavlibrary.EasyAdapterView.java

/**
 * overscroll/*from www.j  a v  a  2  s .  c o  m*/
 *
 * @param canvas
 */
protected void drawOverScrollEffect(Canvas canvas) {
    final int scrollY = getScrollY();
    final int scrollX = getScrollX();

    final int width;
    final int height;
    final int translateX;
    final int translateY;

    width = getWidth();
    height = getHeight();

    translateX = 0;
    translateY = 0;

    if (mTopEdgeEffect != null) {//
        if (!mTopEdgeEffect.isFinished()) {
            final int restoreCount = canvas.save();
            canvas.clipRect(translateX, translateY, translateX + width,
                    translateY + mTopEdgeEffect.getMaxHeight());
            final int edgeY = Math.min(0, scrollY) + translateY;
            canvas.translate(translateX, edgeY);
            mTopEdgeEffect.setSize(width, height);
            if (mTopEdgeEffect.draw(canvas)) {
                invalidateTopGlow();
            }
            canvas.restoreToCount(restoreCount);
        }
    }

    if (mBottomEdgeEffect != null) {//
        if (!mBottomEdgeEffect.isFinished()) {
            final int restoreCount = canvas.save();
            canvas.clipRect(translateX, translateY + height - mBottomEdgeEffect.getMaxHeight(),
                    translateX + width, translateY + height);
            final int edgeX = -width + translateX;
            final int edgeY = Math.max(getHeight(), scrollY);
            canvas.translate(edgeX, edgeY);
            canvas.rotate(180, width, 0);
            mBottomEdgeEffect.setSize(width, height);
            if (mBottomEdgeEffect.draw(canvas)) {
                invalidateBottomGlow();
            }
            canvas.restoreToCount(restoreCount);
        }
    }

    if (mLeftEdgeEffect != null) {//
        if (!mLeftEdgeEffect.isFinished()) {
            canvas.clipRect(translateX, translateY, translateX + mLeftEdgeEffect.getMaxHeight(),
                    translateY + height);
            final int restoreCount = canvas.save();
            canvas.translate(-width, getHeight() - getWidth());//?
            canvas.rotate(270, width, 0);//
            mLeftEdgeEffect.setSize(height, width);//?
            if (mLeftEdgeEffect.draw(canvas)) {
                invalidateLeftGlow();
            }
            canvas.restoreToCount(restoreCount);
        }
    }

    if (mRightEdgeEffect != null) {//?
        if (!mRightEdgeEffect.isFinished()) {
            //     canvas.clipRect(translateX, width - mRightEdgeEffect.getMaxHeight(), width, translateY + height);
            final int restoreCount = canvas.save();
            canvas.translate(0, getWidth());//?
            canvas.rotate(-270, width, 0);//
            mRightEdgeEffect.setSize(height, width);//?
            if (mRightEdgeEffect.draw(canvas)) {
                invalidateRightGlow();
            }
            canvas.restoreToCount(restoreCount);
        }
    }
}

From source file:com.aliyun.homeshell.Folder.java

void drawFolderIcon(Canvas c, int w, int h, float padding, float contentPadding, boolean dropMode,
        boolean hotSeat) {
    CellLayout mContent = mContentList.get(0);
    boolean supportCard = isSupportCardIcon();
    int count = mContent.getShortcutAndWidgetContainer().getChildCount();
    int desireWidth = mContent.getDesiredWidth();
    if (mSupportCardIcon != supportCard) {
        updateFolderLayout(supportCard);
    }/*w w w  . j a  v  a2s  . c  o m*/
    updateOrientation();
    int countX = mContent.getCountX();
    int cellWidth = mContent.getCellWidth();
    int cellHeight = mContent.getCellHeight();
    int widthGap = mContent.getWidthGap();
    int heightGap = mContent.getHeightGap();
    int topPadding = mContent.getPaddingTop();
    int startPadding = mContent.getPaddingStart();
    mHotSeat = hotSeat;
    mSupportCardIcon = supportCard;
    mIconChild = count;
    mLastDesireWidth = desireWidth;
    int contentWidth = mContent.getDesiredWidth();
    float iconScale;
    if (supportCard) {
        iconScale = (float) w / contentWidth;
        padding = (int) (startPadding * iconScale);
        mIconPaddingX = contentPadding;
        if (!hotSeat)
            mIconPaddingY = contentPadding - iconScale * getFolderNamePadding();
    } else {
        iconScale = (float) (w - padding * 2) / (contentWidth - startPadding * 2);
        float div = (cellHeight * countX + heightGap * (countX - 1) - cellWidth * countX
                + widthGap * (countX - 1)) / 2 * iconScale * 0.65f;
        c.translate(0, -div);
        mIconPaddingX = contentPadding - iconScale * startPadding;
        if (!hotSeat)
            mIconPaddingY = contentPadding - div - iconScale * (getFolderNamePadding() + topPadding);
    }
    if (hotSeat)
        mIconPaddingY = BubbleTextView.sTopPaddingHotseat - iconScale * getFolderNamePadding();
    mIconScale = iconScale;

    if (supportCard) {
        c.clipRect(0, 0, w, h);
    } else
        c.clipRect(0, 0, w - padding * 2, h - padding);
    c.scale(iconScale, iconScale);
    int iconH = (int) (h / iconScale);

    int countY = (iconH - topPadding + heightGap) / (cellHeight + heightGap);
    ArrayList<View> icons = getItemsInReadingOrder(false);
    if (supportCard)
        c.translate(startPadding, topPadding);
    //YUNOS BEGIN PB
    //##modules(Homeshell): ##author:wutao.wt@alibaba-inc-com
    //##BugID:(5635800) ##date:20141213
    //##decrpition: Homeshell crash
    if (mFolderIcon == null || mFolderIcon.mHideIcon)
        return;
    //YUNOS END PB
    boolean rtl = getResources().getConfiguration().getLayoutDirection() == LAYOUT_DIRECTION_RTL;
    mPageCount = countX * (supportCard ? countX : countX + 1);
    for (int i = 0, N = mDrawingLimit = Math.min(icons.size(), countX * countY); i < N; i++) {
        int x = (rtl ? (countX - (i % countX) - 1) : (i % countX)) * (cellWidth + widthGap);
        int y = (i / countX) * (cellHeight + heightGap);
        c.translate(x, y);
        ((BubbleTextView) icons.get(i)).drawWithRect(0, 0, cellWidth, cellHeight, c);
        c.translate(-x, -y);
    }
}

From source file:com.wb.launcher3.Page.java

@Override
protected void dispatchDraw(Canvas canvas) {
    int halfScreenSize = getViewportWidth() / 2;
    // mOverScrollX is equal to getScrollX() when we're within the normal scroll range.
    // Otherwise it is equal to the scaled overscroll position.
    int screenCenter = mOverScrollX + halfScreenSize;

    if (screenCenter != mLastScreenCenter || mForceScreenScrolled) {
        // set mForceScreenScrolled before calling screenScrolled so that screenScrolled can
        // set it for the next frame
        mForceScreenScrolled = false;/*from   w  w  w.jav  a 2 s .  c o  m*/
        screenScrolled(screenCenter);
        mLastScreenCenter = screenCenter;
    }

    // Find out which screens are visible; as an optimization we only call draw on them
    final int pageCount = getChildCount();
    if (pageCount > 0) {
        //*/Modified by tyd Greg 2014-03-20,for transition effect
        boolean allowed = true;
        Workspace workspace = null;
        if (this instanceof Workspace) {
            workspace = (Workspace) this;
            allowed = !workspace.isSmall();
        }
        if (TydtechConfig.TYDTECH_DEBUG_FLAG) {
            Log.d("Greg", "allowed: " + allowed);
        }
        /*/
        if(!allowed || !TydtechConfig.TRANSITION_EFFECT_ENABLED){
        getVisiblePages(mTempVisiblePagesRange);
        }else{
        getVisiblePagesExt(mTempVisiblePagesRange);
        }
        //*/
        getVisiblePages(mTempVisiblePagesRange);
        //*/
        final int leftScreen = mTempVisiblePagesRange[0];
        final int rightScreen = mTempVisiblePagesRange[1];
        if (leftScreen != -1 && rightScreen != -1) {
            final long drawingTime = getDrawingTime();
            // Clip to the bounds
            canvas.save();
            canvas.clipRect(getScrollX(), getScrollY(), getScrollX() + getRight() - getLeft(),
                    getScrollY() + getBottom() - getTop());

            // Draw all the children, leaving the drag view for last
            for (int i = pageCount - 1; i >= 0; i--) {
                final View v = getPageAt(i);
                if (v == mDragView)
                    continue;
                if (mForceDrawAllChildrenNextFrame
                        || (leftScreen <= i && i <= rightScreen && shouldDrawChild(v))) {
                    drawChild(canvas, v, drawingTime);
                }
            }
            // Draw the drag view on top (if there is one)
            if (mDragView != null) {
                drawChild(canvas, mDragView, drawingTime);
            }

            mForceDrawAllChildrenNextFrame = false;
            canvas.restore();
        }

        //*/Added by TYD Theobald_Wu on 20130223 [begin] for cycle rolling pages
        if (TydtechConfig.CYCLE_ROLL_PAGES_ENABLED && allowed) {
            canvas.save();
            int width = 0;
            final int pageW = getViewportWidth();
            View v = null;
            int scrollOffset = (pageW - getChildWidth(0)) / 2;
            if (mOverScrollX < 0) {
                int index = pageCount - 1;
                v = getPageAt(index);
                width = getViewportOffsetX() - scrollOffset - v.getWidth();
            } else if (mOverScrollX > mMaxScrollX) {
                v = getPageAt(0);
                width = getViewportOffsetX() + pageW * pageCount + scrollOffset;
            }
            if (TydtechConfig.TYDTECH_DEBUG_FLAG) {
                Log.d("Greg", "width: " + width);
                Log.d("Greg", "mOverScrollX: " + mOverScrollX);
            }
            if (v != null) {
                canvas.translate(width, v.getY());
                canvas.concat(v.getMatrix());
                final int w = v.getWidth();
                final int h = v.getHeight();
                final int sx = v.getScrollX();
                final int sy = v.getScrollY();
                Rect rect = new Rect(sx, sy, sx + w, sy + h);
                ///* zhangwuba mark this, user verison lead to screen flash 2014-5-12
                //canvas.saveLayerAlpha(sx, sy, sx + w, sy + h, (int) (v.getAlpha() * 255),
                //  Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
                //*/
                v.draw(canvas);
            }
            canvas.restore();
        }
        //*/
    }
}

From source file:org.chromium.chrome.browser.toolbar.ToolbarPhone.java

private boolean drawLocationBar(Canvas canvas, long drawingTime) {
    boolean clipped = false;

    if (mLocationBarBackground != null && (mTabSwitcherState == STATIC_TAB || mTextureCaptureMode)) {
        canvas.save();/*  w  w w . ja  v  a2 s.c  om*/
        int backgroundAlpha;
        if (mTabSwitcherModeAnimation != null) {
            // Fade out/in the location bar towards the beginning of the animations to avoid
            // large jumps of stark white.
            backgroundAlpha = (int) (Math.pow(mLocationBar.getAlpha(), 3) * mLocationBarBackgroundAlpha);
        } else if (getToolbarDataProvider().isUsingBrandColor() && !mBrandColorTransitionActive) {
            backgroundAlpha = mUnfocusedLocationBarUsesTransparentBg
                    ? (int) (MathUtils.interpolate(LOCATION_BAR_TRANSPARENT_BACKGROUND_ALPHA, 255,
                            mUrlExpansionPercent))
                    : 255;
        } else {
            backgroundAlpha = mLocationBarBackgroundAlpha;
        }
        mLocationBarBackground.setAlpha(backgroundAlpha);

        if ((mLocationBar.getAlpha() > 0 || mForceDrawLocationBarBackground) && !mTextureCaptureMode) {
            mLocationBarBackground.setBounds(
                    mLocationBarBackgroundBounds.left + mLocationBarBackgroundNtpOffset.left
                            - mLocationBarBackgroundPadding.left,
                    mLocationBarBackgroundBounds.top + mLocationBarBackgroundNtpOffset.top
                            - mLocationBarBackgroundPadding.top,
                    mLocationBarBackgroundBounds.right + mLocationBarBackgroundNtpOffset.right
                            + mLocationBarBackgroundPadding.right,
                    mLocationBarBackgroundBounds.bottom + mLocationBarBackgroundNtpOffset.bottom
                            + mLocationBarBackgroundPadding.bottom);
            mLocationBarBackground.draw(canvas);
        }

        float locationBarClipLeft = mLocationBarBackgroundBounds.left + mLocationBarBackgroundNtpOffset.left;
        float locationBarClipRight = mLocationBarBackgroundBounds.right + mLocationBarBackgroundNtpOffset.right;
        float locationBarClipTop = mLocationBarBackgroundBounds.top + mLocationBarBackgroundNtpOffset.top;
        float locationBarClipBottom = mLocationBarBackgroundBounds.bottom
                + mLocationBarBackgroundNtpOffset.bottom;

        // When unexpanded, the location bar's visible content boundaries are inset from the
        // viewport used to draw the background.  During expansion transitions, compensation
        // is applied to increase the clip regions such that when the location bar converts
        // to the narrower collapsed layout that the visible content is the same.
        if (mUrlExpansionPercent != 1f) {
            int leftDelta = mUnfocusedLocationBarLayoutLeft - getViewBoundsLeftOfLocationBar(mVisualState);
            int rightDelta = getViewBoundsRightOfLocationBar(mVisualState) - mUnfocusedLocationBarLayoutLeft
                    - mUnfocusedLocationBarLayoutWidth;
            float inversePercent = 1f - mUrlExpansionPercent;
            locationBarClipLeft += leftDelta * inversePercent;
            locationBarClipRight -= rightDelta * inversePercent;
        }

        // Clip the location bar child to the URL viewport calculated in onDraw.
        canvas.clipRect(locationBarClipLeft, locationBarClipTop, locationBarClipRight, locationBarClipBottom);
        clipped = true;
    }

    boolean retVal = super.drawChild(canvas, mLocationBar, drawingTime);

    if (clipped)
        canvas.restore();
    return retVal;
}

From source file:com.appunite.list.AbsHorizontalListView.java

@Override
protected void dispatchDraw(Canvas canvas) {
    int saveCount = 0;
    final boolean clipToPadding = mClipToPadding;
    if (clipToPadding) {
        saveCount = canvas.save();/*w  ww .  ja  va 2  s  . com*/
        final int scrollX = getScrollX();
        final int scrollY = getScrollY();
        final int paddingLeft = getPaddingLeft();
        final int paddingTop = getPaddingTop();
        final int paddingRight = getPaddingRight();
        final int paddingBottom = getPaddingBottom();
        final int left = getLeft();
        final int top = getTop();
        final int right = getRight();
        final int bottom = getBottom();
        canvas.clipRect(scrollX + paddingLeft, scrollY + paddingTop, scrollX + right - left - paddingRight,
                scrollY + bottom - top - paddingBottom);
        setClipToPadding(false);
    }

    final boolean drawSelectorOnTop = mDrawSelectorOnTop;
    if (!drawSelectorOnTop) {
        drawSelector(canvas);
    }

    super.dispatchDraw(canvas);

    if (drawSelectorOnTop) {
        drawSelector(canvas);
    }

    if (clipToPadding) {
        canvas.restoreToCount(saveCount);
        setClipToPadding(true);
    }
}

From source file:net.droidsolutions.droidcharts.core.plot.CategoryPlot.java

/**
 * Draws the plot on a Java 2D graphics device (such as the screen or a
 * printer).//from   w  w  w .  j av  a2  s.  com
 * <P>
 * At your option, you may supply an instance of {@link PlotRenderingInfo}.
 * If you do, it will be populated with information about the drawing,
 * including various plot dimensions and tooltip info.
 * 
 * @param g2
 *            the graphics device.
 * @param area
 *            the area within which the plot (including axes) should be
 *            drawn.
 * @param anchor
 *            the anchor point (<code>null</code> permitted).
 * @param parentState
 *            the state from the parent plot, if there is one.
 * @param state
 *            collects info as the chart is drawn (possibly
 *            <code>null</code>).
 */
public void draw(Canvas g2, Rectangle2D area, Point2D anchor, PlotState parentState, PlotRenderingInfo state) {

    // if the plot area is too small, just return...
    boolean b1 = (area.getWidth() <= MINIMUM_WIDTH_TO_DRAW);
    boolean b2 = (area.getHeight() <= MINIMUM_HEIGHT_TO_DRAW);
    if (b1 || b2) {
        return;
    }

    // record the plot area...
    if (state == null) {
        // if the incoming state is null, no information will be passed
        // back to the caller - but we create a temporary state to record
        // the plot area, since that is used later by the axes
        state = new PlotRenderingInfo(null);
    }
    state.setPlotArea(area);

    // adjust the drawing area for the plot insets (if any)...
    RectangleInsets insets = getInsets();
    insets.trim(area);

    // calculate the data area...
    AxisSpace space = calculateAxisSpace(g2, area);
    Rectangle2D dataArea = space.shrink(area, null);
    this.axisOffset.trim(dataArea);

    state.setDataArea(dataArea);
    createAndAddEntity((Rectangle2D) dataArea.clone(), state, null, null);

    // if there is a renderer, it draws the background, otherwise use the
    // default background...
    if (getRenderer() != null) {
        getRenderer().drawBackground(g2, this, dataArea);
    } else {
        drawBackground(g2, dataArea);
    }

    Map axisStateMap = drawAxes(g2, area, dataArea, state);

    // the anchor point is typically the point where the mouse last
    // clicked - the crosshairs will be driven off this point...
    if (anchor != null && !dataArea.contains(anchor)) {
        anchor = ShapeUtilities.getPointInRectangle(anchor.getX(), anchor.getY(), dataArea);
    }
    CategoryCrosshairState crosshairState = new CategoryCrosshairState();
    crosshairState.setCrosshairDistance(Double.POSITIVE_INFINITY);
    crosshairState.setAnchor(anchor);

    // specify the anchor X and Y coordinates in Java2D space, for the
    // cases where these are not updated during rendering (i.e. no lock
    // on data)
    crosshairState.setAnchorX(Double.NaN);
    crosshairState.setAnchorY(Double.NaN);
    if (anchor != null) {
        ValueAxis rangeAxis = getRangeAxis();
        if (rangeAxis != null) {
            double y;
            if (getOrientation() == PlotOrientation.VERTICAL) {
                y = rangeAxis.java2DToValue(anchor.getY(), dataArea, getRangeAxisEdge());
            } else {
                y = rangeAxis.java2DToValue(anchor.getX(), dataArea, getRangeAxisEdge());
            }
            crosshairState.setAnchorY(y);
        }
    }
    crosshairState.setRowKey(getDomainCrosshairRowKey());
    crosshairState.setColumnKey(getDomainCrosshairColumnKey());
    crosshairState.setCrosshairY(getRangeCrosshairValue());

    // don't let anyone draw outside the data area
    g2.save();
    g2.clipRect((float) dataArea.getMinX(), (float) dataArea.getMaxY(), (float) dataArea.getMaxX(),
            (float) dataArea.getMinY());

    drawDomainGridlines(g2, dataArea);

    AxisState rangeAxisState = (AxisState) axisStateMap.get(getRangeAxis());
    if (rangeAxisState == null) {
        if (parentState != null) {
            rangeAxisState = (AxisState) parentState.getSharedAxisStates().get(getRangeAxis());
        }
    }
    if (rangeAxisState != null) {
        drawRangeGridlines(g2, dataArea, rangeAxisState.getTicks());
        drawZeroRangeBaseline(g2, dataArea);
    }

    // draw the markers...
    for (int i = 0; i < this.renderers.size(); i++) {
        drawDomainMarkers(g2, dataArea, i, Layer.BACKGROUND);
    }
    for (int i = 0; i < this.renderers.size(); i++) {
        drawRangeMarkers(g2, dataArea, i, Layer.BACKGROUND);
    }

    // now render data items...
    boolean foundData = false;

    // set up the alpha-transparency...
    // TODO TRANSPARENCY
    /*
     * pa Composite originalComposite = g2.getComposite();
     * g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
     * getForegroundAlpha()));
     */

    DatasetRenderingOrder order = getDatasetRenderingOrder();
    if (order == DatasetRenderingOrder.FORWARD) {
        for (int i = 0; i < this.datasets.size(); i++) {
            foundData = render(g2, dataArea, i, state, crosshairState) || foundData;
        }
    } else { // DatasetRenderingOrder.REVERSE
        for (int i = this.datasets.size() - 1; i >= 0; i--) {
            foundData = render(g2, dataArea, i, state, crosshairState) || foundData;
        }
    }
    // draw the foreground markers...
    for (int i = 0; i < this.renderers.size(); i++) {
        drawDomainMarkers(g2, dataArea, i, Layer.FOREGROUND);
    }
    for (int i = 0; i < this.renderers.size(); i++) {
        drawRangeMarkers(g2, dataArea, i, Layer.FOREGROUND);
    }

    // draw the annotations (if any)...
    drawAnnotations(g2, dataArea);

    g2.restore();

    if (!foundData) {
        drawNoDataMessage(g2, dataArea);
    }

    int datasetIndex = crosshairState.getDatasetIndex();
    setCrosshairDatasetIndex(datasetIndex, false);

    // draw domain crosshair if required...
    Comparable rowKey = crosshairState.getRowKey();
    Comparable columnKey = crosshairState.getColumnKey();
    setDomainCrosshairRowKey(rowKey, false);
    setDomainCrosshairColumnKey(columnKey, false);
    if (isDomainCrosshairVisible() && columnKey != null) {
        Paint paint = getDomainCrosshairPaint();
        float stroke = getDomainCrosshairStroke();
        drawDomainCrosshair(g2, dataArea, this.orientation, datasetIndex, rowKey, columnKey, stroke, paint);
    }

    // draw range crosshair if required...
    ValueAxis yAxis = getRangeAxisForDataset(datasetIndex);
    RectangleEdge yAxisEdge = getRangeAxisEdge();
    if (!this.rangeCrosshairLockedOnData && anchor != null) {
        double yy;
        if (getOrientation() == PlotOrientation.VERTICAL) {
            yy = yAxis.java2DToValue(anchor.getY(), dataArea, yAxisEdge);
        } else {
            yy = yAxis.java2DToValue(anchor.getX(), dataArea, yAxisEdge);
        }
        crosshairState.setCrosshairY(yy);
    }
    setRangeCrosshairValue(crosshairState.getCrosshairY(), false);
    if (isRangeCrosshairVisible()) {
        double y = getRangeCrosshairValue();
        Paint paint = getRangeCrosshairPaint();
        float stroke = getRangeCrosshairStroke();
        drawRangeCrosshair(g2, dataArea, getOrientation(), y, yAxis, stroke, paint);
    }

    // draw an outline around the plot area...
    if (isOutlineVisible()) {
        if (getRenderer() != null) {
            getRenderer().drawOutline(g2, this, dataArea);
        } else {
            drawOutline(g2, dataArea);
        }
    }

}

From source file:net.droidsolutions.droidcharts.core.plot.XYPlot.java

/**
 * Draws the plot within the specified area on a graphics device.
 * /*from ww  w .  j  a  v  a2  s .c  o m*/
 * @param g2
 *            the graphics device.
 * @param area
 *            the plot area (in Java2D space).
 * @param anchor
 *            an anchor point in Java2D space (<code>null</code> permitted).
 * @param parentState
 *            the state from the parent plot, if there is one (
 *            <code>null</code> permitted).
 * @param info
 *            collects chart drawing information (<code>null</code>
 *            permitted).
 */
public void draw(Canvas g2, Rectangle2D area, Point2D anchor, PlotState parentState, PlotRenderingInfo info) {

    // if the plot area is too small, just return...
    boolean b1 = (area.getWidth() <= MINIMUM_WIDTH_TO_DRAW);
    boolean b2 = (area.getHeight() <= MINIMUM_HEIGHT_TO_DRAW);
    if (b1 || b2) {
        return;
    }

    // record the plot area...
    if (info != null) {
        info.setPlotArea(area);
    }

    // adjust the drawing area for the plot insets (if any)...
    RectangleInsets insets = getInsets();
    insets.trim(area);

    AxisSpace space = calculateAxisSpace(g2, area);
    Rectangle2D dataArea = space.shrink(area, null);
    this.axisOffset.trim(dataArea);
    createAndAddEntity((Rectangle2D) dataArea.clone(), info, null, null);
    if (info != null) {
        info.setDataArea(dataArea);
    }

    // draw the plot background and axes...
    drawBackground(g2, dataArea);
    Map axisStateMap = drawAxes(g2, area, dataArea, info);

    PlotOrientation orient = getOrientation();

    // the anchor point is typically the point where the mouse last
    // clicked - the crosshairs will be driven off this point...
    if (anchor != null && !dataArea.contains(anchor)) {
        anchor = null;
    }
    CrosshairState crosshairState = new CrosshairState();
    crosshairState.setCrosshairDistance(Double.POSITIVE_INFINITY);
    crosshairState.setAnchor(anchor);

    crosshairState.setAnchorX(Double.NaN);
    crosshairState.setAnchorY(Double.NaN);
    if (anchor != null) {
        ValueAxis domainAxis = getDomainAxis();
        if (domainAxis != null) {
            double x;
            if (orient == PlotOrientation.VERTICAL) {
                x = domainAxis.java2DToValue(anchor.getX(), dataArea, getDomainAxisEdge());
            } else {
                x = domainAxis.java2DToValue(anchor.getY(), dataArea, getDomainAxisEdge());
            }
            crosshairState.setAnchorX(x);
        }
        ValueAxis rangeAxis = getRangeAxis();
        if (rangeAxis != null) {
            double y;
            if (orient == PlotOrientation.VERTICAL) {
                y = rangeAxis.java2DToValue(anchor.getY(), dataArea, getRangeAxisEdge());
            } else {
                y = rangeAxis.java2DToValue(anchor.getX(), dataArea, getRangeAxisEdge());
            }
            crosshairState.setAnchorY(y);
        }
    }
    crosshairState.setCrosshairX(getDomainCrosshairValue());
    crosshairState.setCrosshairY(getRangeCrosshairValue());

    g2.save();
    g2.clipRect((float) dataArea.getMinX(), (float) dataArea.getMinY(), (float) dataArea.getMaxX(),
            (float) dataArea.getMaxY());

    AxisState domainAxisState = (AxisState) axisStateMap.get(getDomainAxis());
    if (domainAxisState == null) {
        if (parentState != null) {
            domainAxisState = (AxisState) parentState.getSharedAxisStates().get(getDomainAxis());
        }
    }

    AxisState rangeAxisState = (AxisState) axisStateMap.get(getRangeAxis());
    if (rangeAxisState == null) {
        if (parentState != null) {
            rangeAxisState = (AxisState) parentState.getSharedAxisStates().get(getRangeAxis());
        }
    }
    if (domainAxisState != null) {
        drawDomainTickBands(g2, dataArea, domainAxisState.getTicks());
    }
    if (rangeAxisState != null) {
        drawRangeTickBands(g2, dataArea, rangeAxisState.getTicks());
    }
    if (domainAxisState != null) {
        drawDomainGridlines(g2, dataArea, domainAxisState.getTicks());
        drawZeroDomainBaseline(g2, dataArea);
    }
    if (rangeAxisState != null) {
        drawRangeGridlines(g2, dataArea, rangeAxisState.getTicks());
        drawZeroRangeBaseline(g2, dataArea);
    }

    // draw the markers that are associated with a specific renderer...
    for (int i = 0; i < this.renderers.size(); i++) {
        drawDomainMarkers(g2, dataArea, i, Layer.BACKGROUND);
    }
    for (int i = 0; i < this.renderers.size(); i++) {
        drawRangeMarkers(g2, dataArea, i, Layer.BACKGROUND);
    }

    // now draw annotations and render data items...
    boolean foundData = false;
    DatasetRenderingOrder order = getDatasetRenderingOrder();
    if (order == DatasetRenderingOrder.FORWARD) {

        // draw background annotations
        int rendererCount = this.renderers.size();
        for (int i = 0; i < rendererCount; i++) {
            XYItemRenderer r = getRenderer(i);
            if (r != null) {
                ValueAxis domainAxis = getDomainAxisForDataset(i);
                ValueAxis rangeAxis = getRangeAxisForDataset(i);
                r.drawAnnotations(g2, dataArea, domainAxis, rangeAxis, Layer.BACKGROUND, info);
            }
        }

        // render data items...
        for (int i = 0; i < getDatasetCount(); i++) {
            foundData = render(g2, dataArea, i, info, crosshairState) || foundData;
        }

        // draw foreground annotations
        for (int i = 0; i < rendererCount; i++) {
            XYItemRenderer r = getRenderer(i);
            if (r != null) {
                ValueAxis domainAxis = getDomainAxisForDataset(i);
                ValueAxis rangeAxis = getRangeAxisForDataset(i);
                r.drawAnnotations(g2, dataArea, domainAxis, rangeAxis, Layer.FOREGROUND, info);
            }
        }

    } else if (order == DatasetRenderingOrder.REVERSE) {

        // draw background annotations
        int rendererCount = this.renderers.size();
        for (int i = rendererCount - 1; i >= 0; i--) {
            XYItemRenderer r = getRenderer(i);
            if (i >= getDatasetCount()) { // we need the dataset to make
                continue; // a link to the axes
            }
            if (r != null) {
                ValueAxis domainAxis = getDomainAxisForDataset(i);
                ValueAxis rangeAxis = getRangeAxisForDataset(i);
                r.drawAnnotations(g2, dataArea, domainAxis, rangeAxis, Layer.BACKGROUND, info);
            }
        }

        for (int i = getDatasetCount() - 1; i >= 0; i--) {
            foundData = render(g2, dataArea, i, info, crosshairState) || foundData;
        }

        // draw foreground annotations
        for (int i = rendererCount - 1; i >= 0; i--) {
            XYItemRenderer r = getRenderer(i);
            if (i >= getDatasetCount()) { // we need the dataset to make
                continue; // a link to the axes
            }
            if (r != null) {
                ValueAxis domainAxis = getDomainAxisForDataset(i);
                ValueAxis rangeAxis = getRangeAxisForDataset(i);
                r.drawAnnotations(g2, dataArea, domainAxis, rangeAxis, Layer.FOREGROUND, info);
            }
        }

    }

    // draw domain crosshair if required...
    int xAxisIndex = crosshairState.getDomainAxisIndex();
    ValueAxis xAxis = getDomainAxis(xAxisIndex);
    RectangleEdge xAxisEdge = getDomainAxisEdge(xAxisIndex);
    if (!this.domainCrosshairLockedOnData && anchor != null) {
        double xx;
        if (orient == PlotOrientation.VERTICAL) {
            xx = xAxis.java2DToValue(anchor.getX(), dataArea, xAxisEdge);
        } else {
            xx = xAxis.java2DToValue(anchor.getY(), dataArea, xAxisEdge);
        }
        crosshairState.setCrosshairX(xx);
    }
    setDomainCrosshairValue(crosshairState.getCrosshairX(), false);
    if (isDomainCrosshairVisible()) {
        double x = getDomainCrosshairValue();
        Paint paint = getDomainCrosshairPaint();
        int oldAlpha = paint.getAlpha();
        paint.setAlpha(getForegroundAlpha());
        Float stroke = getDomainCrosshairStroke();
        drawDomainCrosshair(g2, dataArea, orient, x, xAxis, stroke, paint);
        paint.setAlpha(oldAlpha);
    }

    // draw range crosshair if required...
    int yAxisIndex = crosshairState.getRangeAxisIndex();
    ValueAxis yAxis = getRangeAxis(yAxisIndex);
    RectangleEdge yAxisEdge = getRangeAxisEdge(yAxisIndex);
    if (!this.rangeCrosshairLockedOnData && anchor != null) {
        double yy;
        if (orient == PlotOrientation.VERTICAL) {
            yy = yAxis.java2DToValue(anchor.getY(), dataArea, yAxisEdge);
        } else {
            yy = yAxis.java2DToValue(anchor.getX(), dataArea, yAxisEdge);
        }
        crosshairState.setCrosshairY(yy);
    }
    setRangeCrosshairValue(crosshairState.getCrosshairY(), false);
    if (isRangeCrosshairVisible()) {
        double y = getRangeCrosshairValue();
        Paint paint = getRangeCrosshairPaint();
        int oldAlpha = paint.getAlpha();
        paint.setAlpha(getForegroundAlpha());
        Float stroke = getRangeCrosshairStroke();
        drawRangeCrosshair(g2, dataArea, orient, y, yAxis, stroke, paint);
        paint.setAlpha(oldAlpha);
    }

    if (!foundData) {
        drawNoDataMessage(g2, dataArea);
    }

    for (int i = 0; i < this.renderers.size(); i++) {
        drawDomainMarkers(g2, dataArea, i, Layer.FOREGROUND);
    }
    for (int i = 0; i < this.renderers.size(); i++) {
        drawRangeMarkers(g2, dataArea, i, Layer.FOREGROUND);
    }

    drawAnnotations(g2, dataArea, info);
    g2.restore();
    drawOutline(g2, dataArea);

}

From source file:org.telegram.ui.Components.AudioPlayerAlert.java

public AudioPlayerAlert(final Context context) {
    super(context, true);

    MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject();
    if (messageObject != null) {
        currentAccount = messageObject.currentAccount;
    } else {//from ww  w  .  ja v a2s . c  o m
        currentAccount = UserConfig.selectedAccount;
    }

    parentActivity = (LaunchActivity) context;
    noCoverDrawable = context.getResources().getDrawable(R.drawable.nocover).mutate();
    noCoverDrawable.setColorFilter(
            new PorterDuffColorFilter(Theme.getColor(Theme.key_player_placeholder), PorterDuff.Mode.MULTIPLY));

    TAG = DownloadController.getInstance(currentAccount).generateObserverTag();
    NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.messagePlayingDidReset);
    NotificationCenter.getInstance(currentAccount).addObserver(this,
            NotificationCenter.messagePlayingPlayStateChanged);
    NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.messagePlayingDidStart);
    NotificationCenter.getInstance(currentAccount).addObserver(this,
            NotificationCenter.messagePlayingProgressDidChanged);
    NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.musicDidLoad);

    shadowDrawable = context.getResources().getDrawable(R.drawable.sheet_shadow).mutate();
    shadowDrawable.setColorFilter(
            new PorterDuffColorFilter(Theme.getColor(Theme.key_player_background), PorterDuff.Mode.MULTIPLY));
    paint.setColor(Theme.getColor(Theme.key_player_placeholderBackground));

    containerView = new FrameLayout(context) {

        private boolean ignoreLayout = false;

        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            if (ev.getAction() == MotionEvent.ACTION_DOWN && scrollOffsetY != 0 && ev.getY() < scrollOffsetY
                    && placeholderImageView.getTranslationX() == 0) {
                dismiss();
                return true;
            }
            return super.onInterceptTouchEvent(ev);
        }

        @Override
        public boolean onTouchEvent(MotionEvent e) {
            return !isDismissed() && super.onTouchEvent(e);
        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            int height = MeasureSpec.getSize(heightMeasureSpec);
            int contentSize = AndroidUtilities.dp(178) + playlist.size() * AndroidUtilities.dp(56)
                    + backgroundPaddingTop + ActionBar.getCurrentActionBarHeight()
                    + AndroidUtilities.statusBarHeight;
            int padding;
            heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
            if (searching) {
                padding = AndroidUtilities.dp(178) + ActionBar.getCurrentActionBarHeight()
                        + (Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0);
            } else {
                if (contentSize < height) {
                    padding = height - contentSize;
                } else {
                    padding = (contentSize < height ? 0 : height - (height / 5 * 3));
                }
                padding += ActionBar.getCurrentActionBarHeight()
                        + (Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0);
            }
            if (listView.getPaddingTop() != padding) {
                ignoreLayout = true;
                listView.setPadding(0, padding, 0, AndroidUtilities.dp(8));
                ignoreLayout = false;
            }
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            inFullSize = getMeasuredHeight() >= height;
            int availableHeight = height - ActionBar.getCurrentActionBarHeight()
                    - (Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0)
                    - AndroidUtilities.dp(120);
            int maxSize = Math.max(availableHeight, getMeasuredWidth());
            thumbMaxX = (getMeasuredWidth() - maxSize) / 2 - AndroidUtilities.dp(17);
            thumbMaxY = AndroidUtilities.dp(19);
            panelEndTranslation = getMeasuredHeight() - playerLayout.getMeasuredHeight();
            thumbMaxScale = maxSize / (float) placeholderImageView.getMeasuredWidth() - 1.0f;

            endTranslation = ActionBar.getCurrentActionBarHeight() + AndroidUtilities.dp(5);
            int scaledHeight = (int) Math
                    .ceil(placeholderImageView.getMeasuredHeight() * (1.0f + thumbMaxScale));
            if (scaledHeight > availableHeight) {
                endTranslation -= (scaledHeight - availableHeight);
            }
        }

        @Override
        protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
            super.onLayout(changed, left, top, right, bottom);
            int y = actionBar.getMeasuredHeight();
            shadow.layout(shadow.getLeft(), y, shadow.getRight(), y + shadow.getMeasuredHeight());
            updateLayout();

            setFullAnimationProgress(fullAnimationProgress);
        }

        @Override
        public void requestLayout() {
            if (ignoreLayout) {
                return;
            }
            super.requestLayout();
        }

        @Override
        protected void onDraw(Canvas canvas) {
            shadowDrawable.setBounds(0,
                    Math.max(actionBar.getMeasuredHeight(), scrollOffsetY) - backgroundPaddingTop,
                    getMeasuredWidth(), getMeasuredHeight());
            shadowDrawable.draw(canvas);
        }
    };
    containerView.setWillNotDraw(false);
    containerView.setPadding(backgroundPaddingLeft, 0, backgroundPaddingLeft, 0);

    actionBar = new ActionBar(context);
    actionBar.setBackgroundColor(Theme.getColor(Theme.key_player_actionBar));
    actionBar.setBackButtonImage(R.drawable.ic_ab_back);
    actionBar.setItemsColor(Theme.getColor(Theme.key_player_actionBarItems), false);
    actionBar.setItemsBackgroundColor(Theme.getColor(Theme.key_player_actionBarSelector), false);
    actionBar.setTitleColor(Theme.getColor(Theme.key_player_actionBarTitle));
    actionBar.setSubtitleColor(Theme.getColor(Theme.key_player_actionBarSubtitle));
    actionBar.setAlpha(0.0f);
    actionBar.setTitle("1");
    actionBar.setSubtitle("1");
    actionBar.getTitleTextView().setAlpha(0.0f);
    actionBar.getSubtitleTextView().setAlpha(0.0f);
    avatarContainer = new ChatAvatarContainer(context, null, false);
    avatarContainer.setEnabled(false);
    avatarContainer.setTitleColors(Theme.getColor(Theme.key_player_actionBarTitle),
            Theme.getColor(Theme.key_player_actionBarSubtitle));
    if (messageObject != null) {
        long did = messageObject.getDialogId();
        int lower_id = (int) did;
        int high_id = (int) (did >> 32);
        if (lower_id != 0) {
            if (lower_id > 0) {
                TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(lower_id);
                if (user != null) {
                    avatarContainer.setTitle(ContactsController.formatName(user.first_name, user.last_name));
                    avatarContainer.setUserAvatar(user);
                }
            } else {
                TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-lower_id);
                if (chat != null) {
                    avatarContainer.setTitle(chat.title);
                    avatarContainer.setChatAvatar(chat);
                }
            }
        } else {
            TLRPC.EncryptedChat encryptedChat = MessagesController.getInstance(currentAccount)
                    .getEncryptedChat(high_id);
            if (encryptedChat != null) {
                TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(encryptedChat.user_id);
                if (user != null) {
                    avatarContainer.setTitle(ContactsController.formatName(user.first_name, user.last_name));
                    avatarContainer.setUserAvatar(user);
                }
            }
        }
    }
    avatarContainer.setSubtitle(LocaleController.getString("AudioTitle", R.string.AudioTitle));
    actionBar.addView(avatarContainer, 0, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT,
            LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 56, 0, 40, 0));

    ActionBarMenu menu = actionBar.createMenu();
    menuItem = menu.addItem(0, R.drawable.ic_ab_other);
    menuItem.addSubItem(1, LocaleController.getString("Forward", R.string.Forward));
    menuItem.addSubItem(2, LocaleController.getString("ShareFile", R.string.ShareFile));
    //menuItem.addSubItem(3, LocaleController.getString("Delete", R.string.Delete));
    menuItem.addSubItem(4, LocaleController.getString("ShowInChat", R.string.ShowInChat));
    menuItem.setTranslationX(AndroidUtilities.dp(48));
    menuItem.setAlpha(0.0f);

    searchItem = menu.addItem(0, R.drawable.ic_ab_search).setIsSearchField(true)
            .setActionBarMenuItemSearchListener(new ActionBarMenuItem.ActionBarMenuItemSearchListener() {
                @Override
                public void onSearchCollapse() {
                    avatarContainer.setVisibility(View.VISIBLE);
                    if (hasOptions) {
                        menuItem.setVisibility(View.INVISIBLE);
                    }
                    if (searching) {
                        searchWas = false;
                        searching = false;
                        setAllowNestedScroll(true);
                        listAdapter.search(null);
                    }
                }

                @Override
                public void onSearchExpand() {
                    searchOpenPosition = layoutManager.findLastVisibleItemPosition();
                    View firstVisView = layoutManager.findViewByPosition(searchOpenPosition);
                    searchOpenOffset = ((firstVisView == null) ? 0 : firstVisView.getTop())
                            - listView.getPaddingTop();

                    avatarContainer.setVisibility(View.GONE);
                    if (hasOptions) {
                        menuItem.setVisibility(View.GONE);
                    }
                    searching = true;
                    setAllowNestedScroll(false);
                    listAdapter.notifyDataSetChanged();
                }

                @Override
                public void onTextChanged(EditText editText) {
                    if (editText.length() > 0) {
                        listAdapter.search(editText.getText().toString());
                    } else {
                        searchWas = false;
                        listAdapter.search(null);
                    }
                }
            });
    EditTextBoldCursor editText = searchItem.getSearchField();
    editText.setHint(LocaleController.getString("Search", R.string.Search));
    editText.setTextColor(Theme.getColor(Theme.key_player_actionBarTitle));
    editText.setHintTextColor(Theme.getColor(Theme.key_player_time));
    editText.setCursorColor(Theme.getColor(Theme.key_player_actionBarTitle));

    if (!AndroidUtilities.isTablet()) {
        actionBar.showActionModeTop();
        actionBar.setActionModeTopColor(Theme.getColor(Theme.key_player_actionBarTop));
    }
    actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() {
        @Override
        public void onItemClick(int id) {
            if (id == -1) {
                dismiss();
            } else {
                onSubItemClick(id);
            }
        }
    });

    shadow = new View(context);
    shadow.setAlpha(0.0f);
    shadow.setBackgroundResource(R.drawable.header_shadow);

    shadow2 = new View(context);
    shadow2.setAlpha(0.0f);
    shadow2.setBackgroundResource(R.drawable.header_shadow);

    playerLayout = new FrameLayout(context);
    playerLayout.setBackgroundColor(Theme.getColor(Theme.key_player_background));

    placeholderImageView = new BackupImageView(context) {

        private RectF rect = new RectF();

        @Override
        protected void onDraw(Canvas canvas) {
            if (hasNoCover == 1 || hasNoCover == 2
                    && (!getImageReceiver().hasBitmapImage() || getImageReceiver().getCurrentAlpha() != 1.0f)) {
                rect.set(0, 0, getMeasuredWidth(), getMeasuredHeight());
                canvas.drawRoundRect(rect, getRoundRadius(), getRoundRadius(), paint);
                float plusScale = thumbMaxScale / getScaleX() / 3;
                int s = (int) (AndroidUtilities.dp(63)
                        * Math.max(plusScale / thumbMaxScale, 1.0f / thumbMaxScale));
                int x = (int) (rect.centerX() - s / 2);
                int y = (int) (rect.centerY() - s / 2);
                noCoverDrawable.setBounds(x, y, x + s, y + s);
                noCoverDrawable.draw(canvas);
            }
            if (hasNoCover != 1) {
                super.onDraw(canvas);
            }
        }
    };
    placeholderImageView.setRoundRadius(AndroidUtilities.dp(20));
    placeholderImageView.setPivotX(0);
    placeholderImageView.setPivotY(0);
    placeholderImageView.setOnClickListener(view -> {
        if (animatorSet != null) {
            animatorSet.cancel();
            animatorSet = null;
        }
        animatorSet = new AnimatorSet();
        if (scrollOffsetY <= actionBar.getMeasuredHeight()) {
            animatorSet.playTogether(ObjectAnimator.ofFloat(AudioPlayerAlert.this, "fullAnimationProgress",
                    isInFullMode ? 0.0f : 1.0f));
        } else {
            animatorSet.playTogether(
                    ObjectAnimator.ofFloat(AudioPlayerAlert.this, "fullAnimationProgress",
                            isInFullMode ? 0.0f : 1.0f),
                    ObjectAnimator.ofFloat(actionBar, "alpha", isInFullMode ? 0.0f : 1.0f),
                    ObjectAnimator.ofFloat(shadow, "alpha", isInFullMode ? 0.0f : 1.0f),
                    ObjectAnimator.ofFloat(shadow2, "alpha", isInFullMode ? 0.0f : 1.0f));
        }

        animatorSet.setInterpolator(new DecelerateInterpolator());
        animatorSet.setDuration(250);
        animatorSet.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                if (animation.equals(animatorSet)) {
                    if (!isInFullMode) {
                        listView.setScrollEnabled(true);
                        if (hasOptions) {
                            menuItem.setVisibility(View.INVISIBLE);
                        }
                        searchItem.setVisibility(View.VISIBLE);
                    } else {
                        if (hasOptions) {
                            menuItem.setVisibility(View.VISIBLE);
                        }
                        searchItem.setVisibility(View.INVISIBLE);
                    }
                    animatorSet = null;
                }
            }
        });
        animatorSet.start();
        if (hasOptions) {
            menuItem.setVisibility(View.VISIBLE);
        }
        searchItem.setVisibility(View.VISIBLE);
        isInFullMode = !isInFullMode;
        listView.setScrollEnabled(false);
        if (isInFullMode) {
            shuffleButton.setAdditionalOffset(-AndroidUtilities.dp(20 + 48));
        } else {
            shuffleButton.setAdditionalOffset(-AndroidUtilities.dp(10));
        }
    });

    titleTextView = new TextView(context);
    titleTextView.setTextColor(Theme.getColor(Theme.key_player_actionBarTitle));
    titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
    titleTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
    titleTextView.setEllipsize(TextUtils.TruncateAt.END);
    titleTextView.setSingleLine(true);
    playerLayout.addView(titleTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT,
            LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 72, 18, 60, 0));

    authorTextView = new TextView(context);
    authorTextView.setTextColor(Theme.getColor(Theme.key_player_time));
    authorTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
    authorTextView.setEllipsize(TextUtils.TruncateAt.END);
    authorTextView.setSingleLine(true);
    playerLayout.addView(authorTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT,
            LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 72, 40, 60, 0));

    optionsButton = new ActionBarMenuItem(context, null, 0, Theme.getColor(Theme.key_player_actionBarItems));
    optionsButton.setLongClickEnabled(false);
    optionsButton.setIcon(R.drawable.ic_ab_other);
    optionsButton.setAdditionalOffset(-AndroidUtilities.dp(120));
    playerLayout.addView(optionsButton,
            LayoutHelper.createFrame(40, 40, Gravity.TOP | Gravity.RIGHT, 0, 19, 10, 0));
    optionsButton.addSubItem(1, LocaleController.getString("Forward", R.string.Forward));
    optionsButton.addSubItem(2, LocaleController.getString("ShareFile", R.string.ShareFile));
    //optionsButton.addSubItem(3, LocaleController.getString("Delete", R.string.Delete));
    optionsButton.addSubItem(4, LocaleController.getString("ShowInChat", R.string.ShowInChat));
    optionsButton.setOnClickListener(v -> optionsButton.toggleSubMenu());
    optionsButton.setDelegate(this::onSubItemClick);

    seekBarView = new SeekBarView(context);
    seekBarView.setDelegate(progress -> MediaController.getInstance()
            .seekToProgress(MediaController.getInstance().getPlayingMessageObject(), progress));
    playerLayout.addView(seekBarView,
            LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 30, Gravity.TOP | Gravity.LEFT, 8, 62, 8, 0));

    progressView = new LineProgressView(context);
    progressView.setVisibility(View.INVISIBLE);
    progressView.setBackgroundColor(Theme.getColor(Theme.key_player_progressBackground));
    progressView.setProgressColor(Theme.getColor(Theme.key_player_progress));
    playerLayout.addView(progressView,
            LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 2, Gravity.TOP | Gravity.LEFT, 20, 78, 20, 0));

    timeTextView = new SimpleTextView(context);
    timeTextView.setTextSize(12);
    timeTextView.setText("0:00");
    timeTextView.setTextColor(Theme.getColor(Theme.key_player_time));
    playerLayout.addView(timeTextView,
            LayoutHelper.createFrame(100, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 20, 92, 0, 0));

    durationTextView = new TextView(context);
    durationTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12);
    durationTextView.setTextColor(Theme.getColor(Theme.key_player_time));
    durationTextView.setGravity(Gravity.CENTER);
    playerLayout.addView(durationTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT,
            LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.RIGHT, 0, 90, 20, 0));

    FrameLayout bottomView = new FrameLayout(context) {
        @Override
        protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
            int dist = ((right - left) - AndroidUtilities.dp(8 + 48 * 5)) / 4;
            for (int a = 0; a < 5; a++) {
                int l = AndroidUtilities.dp(4 + 48 * a) + dist * a;
                int t = AndroidUtilities.dp(9);
                buttons[a].layout(l, t, l + buttons[a].getMeasuredWidth(), t + buttons[a].getMeasuredHeight());
            }
        }
    };
    playerLayout.addView(bottomView,
            LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 66, Gravity.TOP | Gravity.LEFT, 0, 106, 0, 0));

    buttons[0] = shuffleButton = new ActionBarMenuItem(context, null, 0, 0);
    shuffleButton.setLongClickEnabled(false);
    shuffleButton.setAdditionalOffset(-AndroidUtilities.dp(10));
    bottomView.addView(shuffleButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP));
    shuffleButton.setOnClickListener(v -> shuffleButton.toggleSubMenu());

    TextView textView = shuffleButton.addSubItem(1,
            LocaleController.getString("ReverseOrder", R.string.ReverseOrder));
    textView.setPadding(AndroidUtilities.dp(8), 0, AndroidUtilities.dp(16), 0);
    playOrderButtons[0] = context.getResources().getDrawable(R.drawable.music_reverse).mutate();
    textView.setCompoundDrawablePadding(AndroidUtilities.dp(8));
    textView.setCompoundDrawablesWithIntrinsicBounds(playOrderButtons[0], null, null, null);

    textView = shuffleButton.addSubItem(2, LocaleController.getString("Shuffle", R.string.Shuffle));
    textView.setPadding(AndroidUtilities.dp(8), 0, AndroidUtilities.dp(16), 0);
    playOrderButtons[1] = context.getResources().getDrawable(R.drawable.pl_shuffle).mutate();
    textView.setCompoundDrawablePadding(AndroidUtilities.dp(8));
    textView.setCompoundDrawablesWithIntrinsicBounds(playOrderButtons[1], null, null, null);

    shuffleButton.setDelegate(id -> {
        MediaController.getInstance().toggleShuffleMusic(id);
        updateShuffleButton();
        listAdapter.notifyDataSetChanged();
    });

    ImageView prevButton;
    buttons[1] = prevButton = new ImageView(context);
    prevButton.setScaleType(ImageView.ScaleType.CENTER);
    prevButton.setImageDrawable(Theme.createSimpleSelectorDrawable(context, R.drawable.pl_previous,
            Theme.getColor(Theme.key_player_button), Theme.getColor(Theme.key_player_buttonActive)));
    bottomView.addView(prevButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP));
    prevButton.setOnClickListener(v -> MediaController.getInstance().playPreviousMessage());

    buttons[2] = playButton = new ImageView(context);
    playButton.setScaleType(ImageView.ScaleType.CENTER);
    playButton.setImageDrawable(Theme.createSimpleSelectorDrawable(context, R.drawable.pl_play,
            Theme.getColor(Theme.key_player_button), Theme.getColor(Theme.key_player_buttonActive)));
    bottomView.addView(playButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP));
    playButton.setOnClickListener(v -> {
        if (MediaController.getInstance().isDownloadingCurrentMessage()) {
            return;
        }
        if (MediaController.getInstance().isMessagePaused()) {
            MediaController.getInstance().playMessage(MediaController.getInstance().getPlayingMessageObject());
        } else {
            MediaController.getInstance().pauseMessage(MediaController.getInstance().getPlayingMessageObject());
        }
    });

    ImageView nextButton;
    buttons[3] = nextButton = new ImageView(context);
    nextButton.setScaleType(ImageView.ScaleType.CENTER);
    nextButton.setImageDrawable(Theme.createSimpleSelectorDrawable(context, R.drawable.pl_next,
            Theme.getColor(Theme.key_player_button), Theme.getColor(Theme.key_player_buttonActive)));
    bottomView.addView(nextButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP));
    nextButton.setOnClickListener(v -> MediaController.getInstance().playNextMessage());

    buttons[4] = repeatButton = new ImageView(context);
    repeatButton.setScaleType(ImageView.ScaleType.CENTER);
    repeatButton.setPadding(0, 0, AndroidUtilities.dp(8), 0);
    bottomView.addView(repeatButton, LayoutHelper.createFrame(50, 48, Gravity.LEFT | Gravity.TOP));
    repeatButton.setOnClickListener(v -> {
        SharedConfig.toggleRepeatMode();
        updateRepeatButton();
    });

    listView = new RecyclerListView(context) {

        boolean ignoreLayout;

        @Override
        protected void onLayout(boolean changed, int l, int t, int r, int b) {
            super.onLayout(changed, l, t, r, b);

            if (searchOpenPosition != -1 && !actionBar.isSearchFieldVisible()) {
                ignoreLayout = true;
                layoutManager.scrollToPositionWithOffset(searchOpenPosition, searchOpenOffset);
                super.onLayout(false, l, t, r, b);
                ignoreLayout = false;
                searchOpenPosition = -1;
            } else if (scrollToSong) {
                scrollToSong = false;
                boolean found = false;
                MessageObject playingMessageObject = MediaController.getInstance().getPlayingMessageObject();
                if (playingMessageObject != null) {
                    int count = listView.getChildCount();
                    for (int a = 0; a < count; a++) {
                        View child = listView.getChildAt(a);
                        if (child instanceof AudioPlayerCell) {
                            if (((AudioPlayerCell) child).getMessageObject() == playingMessageObject) {
                                if (child.getBottom() <= getMeasuredHeight()) {
                                    found = true;
                                }
                                break;
                            }
                        }
                    }
                    if (!found) {
                        int idx = playlist.indexOf(playingMessageObject);
                        if (idx >= 0) {
                            ignoreLayout = true;
                            if (SharedConfig.playOrderReversed) {
                                layoutManager.scrollToPosition(idx);
                            } else {
                                layoutManager.scrollToPosition(playlist.size() - idx);
                            }
                            super.onLayout(false, l, t, r, b);
                            ignoreLayout = false;
                        }
                    }
                }
            }
        }

        @Override
        public void requestLayout() {
            if (ignoreLayout) {
                return;
            }
            super.requestLayout();
        }

        @Override
        protected boolean allowSelectChildAtPosition(float x, float y) {
            float p = playerLayout.getY() + playerLayout.getMeasuredHeight();
            return playerLayout == null || y > playerLayout.getY() + playerLayout.getMeasuredHeight();
        }

        @Override
        public boolean drawChild(Canvas canvas, View child, long drawingTime) {
            canvas.save();
            canvas.clipRect(0,
                    (actionBar != null ? actionBar.getMeasuredHeight() : 0) + AndroidUtilities.dp(50),
                    getMeasuredWidth(), getMeasuredHeight());
            boolean result = super.drawChild(canvas, child, drawingTime);
            canvas.restore();
            return result;
        }
    };
    listView.setPadding(0, 0, 0, AndroidUtilities.dp(8));
    listView.setClipToPadding(false);
    listView.setLayoutManager(
            layoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false));
    listView.setHorizontalScrollBarEnabled(false);
    listView.setVerticalScrollBarEnabled(false);
    containerView.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT,
            LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT));
    listView.setAdapter(listAdapter = new ListAdapter(context));
    listView.setGlowColor(Theme.getColor(Theme.key_dialogScrollGlow));
    listView.setOnItemClickListener((view, position) -> {
        if (view instanceof AudioPlayerCell) {
            ((AudioPlayerCell) view).didPressedButton();
        }
    });
    listView.setOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            if (newState == RecyclerView.SCROLL_STATE_DRAGGING && searching && searchWas) {
                AndroidUtilities.hideKeyboard(getCurrentFocus());
            }
        }

        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            updateLayout();
        }
    });

    playlist = MediaController.getInstance().getPlaylist();
    listAdapter.notifyDataSetChanged();

    containerView.addView(playerLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 178));
    containerView.addView(shadow2, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 3));
    containerView.addView(placeholderImageView,
            LayoutHelper.createFrame(40, 40, Gravity.TOP | Gravity.LEFT, 17, 19, 0, 0));
    containerView.addView(shadow, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 3));
    containerView.addView(actionBar);

    updateTitle(false);
    updateRepeatButton();
    updateShuffleButton();
}