List of usage examples for android.graphics Canvas drawPath
public void drawPath(@NonNull Path path, @NonNull Paint paint)
From source file:com.ushahidi.platform.mobile.app.presentation.view.ui.widget.TitlePageIndicator.java
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (mViewPager == null) { return;//from w ww.ja v a 2 s . c om } final int count = mViewPager.getAdapter().getCount(); if (count == 0) { return; } // mCurrentPage is -1 on first start and after orientation changed. If so, retrieve the // correct index from viewpager. if (mCurrentPage == -1 && mViewPager != null) { mCurrentPage = mViewPager.getCurrentItem(); } //Calculate views bounds ArrayList<Rect> bounds = calculateAllBounds(mPaintText); final int boundsSize = bounds.size(); //Make sure we're on a page that still exists if (mCurrentPage >= boundsSize) { setCurrentItem(boundsSize - 1); return; } final int countMinusOne = count - 1; final float halfWidth = getWidth() / 2f; final int left = getLeft(); final float leftClip = left + mClipPadding; final int width = getWidth(); int height = getHeight(); final int right = left + width; final float rightClip = right - mClipPadding; int page = mCurrentPage; float offsetPercent; if (mPageOffset <= 0.5) { offsetPercent = mPageOffset; } else { page += 1; offsetPercent = 1 - mPageOffset; } final boolean currentSelected = (offsetPercent <= SELECTION_FADE_PERCENTAGE); final boolean currentBold = (offsetPercent <= BOLD_FADE_PERCENTAGE); final float selectedPercent = (SELECTION_FADE_PERCENTAGE - offsetPercent) / SELECTION_FADE_PERCENTAGE; //Verify if the current view must be clipped to the screen Rect curPageBound = bounds.get(mCurrentPage); float curPageWidth = curPageBound.right - curPageBound.left; if (curPageBound.left < leftClip) { //Try to clip to the screen (left side) clipViewOnTheLeft(curPageBound, curPageWidth, left); } if (curPageBound.right > rightClip) { //Try to clip to the screen (right side) clipViewOnTheRight(curPageBound, curPageWidth, right); } //Left views starting from the current position if (mCurrentPage > 0) { for (int i = mCurrentPage - 1; i >= 0; i--) { Rect bound = bounds.get(i); //Is left side is outside the screen if (bound.left < leftClip) { int w = bound.right - bound.left; //Try to clip to the screen (left side) clipViewOnTheLeft(bound, w, left); //Except if there's an intersection with the right view Rect rightBound = bounds.get(i + 1); //Intersection if (bound.right + mTitlePadding > rightBound.left) { bound.left = (int) (rightBound.left - w - mTitlePadding); bound.right = bound.left + w; } } } } //Right views starting from the current position if (mCurrentPage < countMinusOne) { for (int i = mCurrentPage + 1; i < count; i++) { Rect bound = bounds.get(i); //If right side is outside the screen if (bound.right > rightClip) { int w = bound.right - bound.left; //Try to clip to the screen (right side) clipViewOnTheRight(bound, w, right); //Except if there's an intersection with the left view Rect leftBound = bounds.get(i - 1); //Intersection if (bound.left - mTitlePadding < leftBound.right) { bound.left = (int) (leftBound.right + mTitlePadding); bound.right = bound.left + w; } } } } //Now draw views int colorTextAlpha = mColorText >>> 24; for (int i = 0; i < count; i++) { //Get the title Rect bound = bounds.get(i); //Only if one side is visible if ((bound.left > left && bound.left < right) || (bound.right > left && bound.right < right)) { final boolean currentPage = (i == page); final CharSequence pageTitle = getTitle(i); //Only set bold if we are within bounds mPaintText.setFakeBoldText(currentPage && currentBold && mBoldText); //Draw text as unselected mPaintText.setColor(mColorText); if (currentPage && currentSelected) { //Fade out/in unselected text as the selected text fades in/out mPaintText.setAlpha(colorTextAlpha - (int) (colorTextAlpha * selectedPercent)); } //Except if there's an intersection with the right view if (i < boundsSize - 1) { Rect rightBound = bounds.get(i + 1); //Intersection if (bound.right + mTitlePadding > rightBound.left) { int w = bound.right - bound.left; bound.left = (int) (rightBound.left - w - mTitlePadding); bound.right = bound.left + w; } } canvas.drawText(pageTitle, 0, pageTitle.length(), bound.left, bound.bottom + mTopPadding, mPaintText); //If we are within the selected bounds draw the selected text if (currentPage && currentSelected) { mPaintText.setColor(mColorSelected); mPaintText.setAlpha((int) ((mColorSelected >>> 24) * selectedPercent)); canvas.drawText(pageTitle, 0, pageTitle.length(), bound.left, bound.bottom + mTopPadding, mPaintText); } } } //If we want the line on the top change height to zero and invert the line height to trick the drawing code float footerLineHeight = mFooterLineHeight; float footerIndicatorLineHeight = mFooterIndicatorHeight; if (mLinePosition == LinePosition.Top) { height = 0; footerLineHeight = -footerLineHeight; footerIndicatorLineHeight = -footerIndicatorLineHeight; } //Draw the footer line mPath.reset(); mPath.moveTo(0, height - footerLineHeight / 2f); mPath.lineTo(width, height - footerLineHeight / 2f); mPath.close(); canvas.drawPath(mPath, mPaintFooterLine); float heightMinusLine = height - footerLineHeight; switch (mFooterIndicatorStyle) { case Triangle: mPath.reset(); mPath.moveTo(halfWidth, heightMinusLine - footerIndicatorLineHeight); mPath.lineTo(halfWidth + footerIndicatorLineHeight, heightMinusLine); mPath.lineTo(halfWidth - footerIndicatorLineHeight, heightMinusLine); mPath.close(); canvas.drawPath(mPath, mPaintFooterIndicator); break; case Underline: if (!currentSelected || page >= boundsSize) { break; } Rect underlineBounds = bounds.get(page); final float rightPlusPadding = underlineBounds.right; final float leftMinusPadding = underlineBounds.left; final float heightMinusLineMinusIndicator = heightMinusLine - footerIndicatorLineHeight; mPath.reset(); mPath.moveTo(leftMinusPadding, heightMinusLine); mPath.lineTo(rightPlusPadding, heightMinusLine); mPath.lineTo(rightPlusPadding, heightMinusLineMinusIndicator); mPath.lineTo(leftMinusPadding, heightMinusLineMinusIndicator); mPath.close(); mPaintFooterIndicator.setColor(mSelectedFooterColor); mPaintFooterIndicator.setAlpha((int) (0xFF * selectedPercent)); canvas.drawPath(mPath, mPaintFooterIndicator); mPaintFooterIndicator.setAlpha(0xFF); break; default: break; } }
From source file:com.pc.pager.indicator.TitlePageIndicator.java
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (mViewPager == null) { return;/* ww w . j ava 2 s. c om*/ } final int count = mViewPager.getAdapter().getCount(); if (count == 0) { return; } // mCurrentPage is -1 on first start and after orientation changed. If // so, retrieve the correct index from viewpager. if (mCurrentPage == -1 && mViewPager != null) { mCurrentPage = mViewPager.getCurrentItem(); } // Calculate views bounds ArrayList<Rect> bounds = calculateAllBounds(mPaintText); final int boundsSize = bounds.size(); // Make sure we're on a page that still exists if (mCurrentPage >= boundsSize) { setCurrentItem(boundsSize - 1); return; } final int countMinusOne = count - 1; final float halfWidth = getWidth() / 2f; final int left = getLeft(); final float leftClip = left + mClipPadding; final int width = getWidth(); int height = getHeight(); final int right = left + width; final float rightClip = right - mClipPadding; int page = mCurrentPage; float offsetPercent; if (mPageOffset <= 0.5) { offsetPercent = mPageOffset; } else { page += 1; offsetPercent = 1 - mPageOffset; } final boolean currentSelected = (offsetPercent <= SELECTION_FADE_PERCENTAGE); final boolean currentBold = (offsetPercent <= BOLD_FADE_PERCENTAGE); final float selectedPercent = (SELECTION_FADE_PERCENTAGE - offsetPercent) / SELECTION_FADE_PERCENTAGE; // Verify if the current view must be clipped to the screen Rect curPageBound = bounds.get(mCurrentPage); float curPageWidth = curPageBound.right - curPageBound.left; if (curPageBound.left < leftClip) { // Try to clip to the screen (left side) clipViewOnTheLeft(curPageBound, curPageWidth, left); } if (curPageBound.right > rightClip) { // Try to clip to the screen (right side) clipViewOnTheRight(curPageBound, curPageWidth, right); } // Left views starting from the current position if (mCurrentPage > 0) { for (int i = mCurrentPage - 1; i >= 0; i--) { Rect bound = bounds.get(i); // Is left side is outside the screen if (bound.left < leftClip) { int w = bound.right - bound.left; // Try to clip to the screen (left side) clipViewOnTheLeft(bound, w, left); // Except if there's an intersection with the right view Rect rightBound = bounds.get(i + 1); // Intersection if (bound.right + mTitlePadding > rightBound.left) { bound.left = (int) (rightBound.left - w - mTitlePadding); bound.right = bound.left + w; } } } } // Right views starting from the current position if (mCurrentPage < countMinusOne) { for (int i = mCurrentPage + 1; i < count; i++) { Rect bound = bounds.get(i); // If right side is outside the screen if (bound.right > rightClip) { int w = bound.right - bound.left; // Try to clip to the screen (right side) clipViewOnTheRight(bound, w, right); // Except if there's an intersection with the left view Rect leftBound = bounds.get(i - 1); // Intersection if (bound.left - mTitlePadding < leftBound.right) { bound.left = (int) (leftBound.right + mTitlePadding); bound.right = bound.left + w; } } } } // Now draw views int colorTextAlpha = mColorText >>> 24; for (int i = 0; i < count; i++) { // Get the title Rect bound = bounds.get(i); // Only if one side is visible if ((bound.left > left && bound.left < right) || (bound.right > left && bound.right < right)) { final boolean currentPage = (i == page); final CharSequence pageTitle = getTitle(i); // Only set bold if we are within bounds mPaintText.setFakeBoldText(currentPage && currentBold && mBoldText); // Draw text as unselected mPaintText.setColor(mColorText); if (currentPage && currentSelected) { // Fade out/in unselected text as the selected text fades // in/out mPaintText.setAlpha(colorTextAlpha - (int) (colorTextAlpha * selectedPercent)); } // Except if there's an intersection with the right view if (i < boundsSize - 1) { Rect rightBound = bounds.get(i + 1); // Intersection if (bound.right + mTitlePadding > rightBound.left) { int w = bound.right - bound.left; bound.left = (int) (rightBound.left - w - mTitlePadding); bound.right = bound.left + w; } } canvas.drawText(pageTitle, 0, pageTitle.length(), bound.left + TextMaginLeftAndRight / 2, bound.bottom + mTopPadding, mPaintText); // If we are within the selected bounds draw the selected text if (currentPage && currentSelected) { mPaintText.setColor(mColorSelected); mPaintText.setAlpha((int) ((mColorSelected >>> 24) * selectedPercent)); canvas.drawText(pageTitle, 0, pageTitle.length(), bound.left + TextMaginLeftAndRight / 2, bound.bottom + mTopPadding, mPaintText); } } } // If we want the line on the top change height to zero and invert the // line height to trick the drawing code float footerLineHeight = mFooterLineHeight; float footerIndicatorLineHeight = mFooterIndicatorHeight; if (mLinePosition == LinePosition.Top) { height = 0; footerLineHeight = -footerLineHeight; footerIndicatorLineHeight = -footerIndicatorLineHeight; } // Draw the footer line mPath.reset(); mPath.moveTo(0, height - footerLineHeight / 2f); mPath.lineTo(width, height - footerLineHeight / 2f); mPath.close(); canvas.drawPath(mPath, mPaintFooterLine); float heightMinusLine = height - footerLineHeight; switch (mFooterIndicatorStyle) { case Triangle: mPath.reset(); mPath.moveTo(halfWidth, heightMinusLine - footerIndicatorLineHeight); mPath.lineTo(halfWidth + footerIndicatorLineHeight, heightMinusLine); mPath.lineTo(halfWidth - footerIndicatorLineHeight, heightMinusLine); mPath.close(); canvas.drawPath(mPath, mPaintFooterIndicator); break; case Underline: if (!currentSelected || page >= boundsSize) { break; } Rect underlineBounds = bounds.get(page); final float rightPlusPadding = underlineBounds.right + mFooterIndicatorUnderlinePadding; final float leftMinusPadding = underlineBounds.left - mFooterIndicatorUnderlinePadding; final float heightMinusLineMinusIndicator = heightMinusLine - footerIndicatorLineHeight; mPath.reset(); mPath.moveTo(leftMinusPadding, heightMinusLine); mPath.lineTo(rightPlusPadding, heightMinusLine); mPath.lineTo(rightPlusPadding, heightMinusLineMinusIndicator); mPath.lineTo(leftMinusPadding, heightMinusLineMinusIndicator); mPath.close(); mPaintFooterIndicator.setAlpha((int) (0xFF * selectedPercent)); canvas.drawPath(mPath, mPaintFooterIndicator); mPaintFooterIndicator.setAlpha(0xFF); break; } }
From source file:com.viewpagerindicator.as.library.indicator.RecyclerTitlePageIndicator.java
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (mRecyclerView == null) { return;/*from w w w . j av a2 s .co m*/ } final int count = mRecyclerView.getAdapter().getItemCount(); if (count == 0) { return; } // mCurrentPage is -1 on first start and after orientation changed. If so, retrieve the correct index from viewpager. if (mCurrentPage == -1 && mRecyclerView != null) { mCurrentPage = ((RecyclerViewPager) mRecyclerView).getCurrentPosition();//.getCurrentItem(); } //Calculate views bounds ArrayList<Rect> bounds = calculateAllBounds(mPaintText); final int boundsSize = bounds.size(); //Make sure we're on a page that still exists if (mCurrentPage >= boundsSize) { setCurrentItem(boundsSize - 1); return; } final int countMinusOne = count - 1; final float halfWidth = getWidth() / 2f; final int left = getLeft(); final float leftClip = left + mClipPadding; final int width = getWidth(); int height = getHeight(); final int right = left + width; final float rightClip = right - mClipPadding; int page = mCurrentPage; float offsetPercent; if (mPageOffset <= 0.5) { offsetPercent = mPageOffset; } else { page += 1; offsetPercent = 1 - mPageOffset; } final boolean currentSelected = (offsetPercent <= SELECTION_FADE_PERCENTAGE); final boolean currentBold = (offsetPercent <= BOLD_FADE_PERCENTAGE); final float selectedPercent = (SELECTION_FADE_PERCENTAGE - offsetPercent) / SELECTION_FADE_PERCENTAGE; //Verify if the current view must be clipped to the screen Rect curPageBound = bounds.get(mCurrentPage); float curPageWidth = curPageBound.right - curPageBound.left; if (curPageBound.left < leftClip) { //Try to clip to the screen (left side) clipViewOnTheLeft(curPageBound, curPageWidth, left); } if (curPageBound.right > rightClip) { //Try to clip to the screen (right side) clipViewOnTheRight(curPageBound, curPageWidth, right); } //Left views starting from the current position if (mCurrentPage > 0) { for (int i = mCurrentPage - 1; i >= 0; i--) { Rect bound = bounds.get(i); //Is left side is outside the screen if (bound.left < leftClip) { int w = bound.right - bound.left; //Try to clip to the screen (left side) clipViewOnTheLeft(bound, w, left); //Except if there's an intersection with the right view Rect rightBound = bounds.get(i + 1); //Intersection if (bound.right + mTitlePadding > rightBound.left) { bound.left = (int) (rightBound.left - w - mTitlePadding); bound.right = bound.left + w; } } } } //Right views starting from the current position if (mCurrentPage < countMinusOne) { for (int i = mCurrentPage + 1; i < count; i++) { Rect bound = bounds.get(i); //If right side is outside the screen if (bound.right > rightClip) { int w = bound.right - bound.left; //Try to clip to the screen (right side) clipViewOnTheRight(bound, w, right); //Except if there's an intersection with the left view Rect leftBound = bounds.get(i - 1); //Intersection if (bound.left - mTitlePadding < leftBound.right) { bound.left = (int) (leftBound.right + mTitlePadding); bound.right = bound.left + w; } } } } //Now draw views int colorTextAlpha = mColorText >>> 24; for (int i = 0; i < count; i++) { //Get the title Rect bound = bounds.get(i); //Only if one side is visible if ((bound.left > left && bound.left < right) || (bound.right > left && bound.right < right)) { final boolean currentPage = (i == page); final CharSequence pageTitle = getTitle(i); //Only set bold if we are within bounds mPaintText.setFakeBoldText(currentPage && currentBold && mBoldText); //Draw text as unselected mPaintText.setColor(mColorText); if (currentPage && currentSelected) { //Fade out/in unselected text as the selected text fades in/out mPaintText.setAlpha(colorTextAlpha - (int) (colorTextAlpha * selectedPercent)); } //Except if there's an intersection with the right view if (i < boundsSize - 1) { Rect rightBound = bounds.get(i + 1); //Intersection if (bound.right + mTitlePadding > rightBound.left) { int w = bound.right - bound.left; bound.left = (int) (rightBound.left - w - mTitlePadding); bound.right = bound.left + w; } } canvas.drawText(pageTitle, 0, pageTitle.length(), bound.left, bound.bottom + mTopPadding, mPaintText); //If we are within the selected bounds draw the selected text if (currentPage && currentSelected) { mPaintText.setColor(mColorSelected); mPaintText.setAlpha((int) ((mColorSelected >>> 24) * selectedPercent)); canvas.drawText(pageTitle, 0, pageTitle.length(), bound.left, bound.bottom + mTopPadding, mPaintText); } } } //If we want the line on the top change height to zero and invert the line height to trick the drawing code float footerLineHeight = mFooterLineHeight; float footerIndicatorLineHeight = mFooterIndicatorHeight; if (mLinePosition == LinePosition.Top) { height = 0; footerLineHeight = -footerLineHeight; footerIndicatorLineHeight = -footerIndicatorLineHeight; } //Draw the footer line mPath.reset(); mPath.moveTo(0, height - footerLineHeight / 2f); mPath.lineTo(width, height - footerLineHeight / 2f); mPath.close(); canvas.drawPath(mPath, mPaintFooterLine); float heightMinusLine = height - footerLineHeight; switch (mFooterIndicatorStyle) { case Triangle: mPath.reset(); mPath.moveTo(halfWidth, heightMinusLine - footerIndicatorLineHeight); mPath.lineTo(halfWidth + footerIndicatorLineHeight, heightMinusLine); mPath.lineTo(halfWidth - footerIndicatorLineHeight, heightMinusLine); mPath.close(); canvas.drawPath(mPath, mPaintFooterIndicator); break; case Underline: if (!currentSelected || page >= boundsSize) { break; } Rect underlineBounds = bounds.get(page); final float rightPlusPadding = underlineBounds.right + mFooterIndicatorUnderlinePadding; final float leftMinusPadding = underlineBounds.left - mFooterIndicatorUnderlinePadding; final float heightMinusLineMinusIndicator = heightMinusLine - footerIndicatorLineHeight; mPath.reset(); mPath.moveTo(leftMinusPadding, heightMinusLine); mPath.lineTo(rightPlusPadding, heightMinusLine); mPath.lineTo(rightPlusPadding, heightMinusLineMinusIndicator); mPath.lineTo(leftMinusPadding, heightMinusLineMinusIndicator); mPath.close(); mPaintFooterIndicator.setAlpha((int) (0xFF * selectedPercent)); canvas.drawPath(mPath, mPaintFooterIndicator); mPaintFooterIndicator.setAlpha(0xFF); break; } }
From source file:com.focustech.common.widget.TitlePageIndicator.java
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (mViewPager == null) { return;//ww w.ja v a 2 s . c o m } final int count = mViewPager.getAdapter().getCount(); if (count == 0) { return; } // mCurrentPage is -1 on first start and after orientation changed. If // so, retrieve the correct index from // viewpager. if (mCurrentPage == -1 && mViewPager != null) { mCurrentPage = mViewPager.getCurrentItem(); } // Calculate views bounds ArrayList<Rect> bounds = calculateAllBounds(mPaintText); final int boundsSize = bounds.size(); // Make sure we're on a page that still exists if (mCurrentPage >= boundsSize) { setCurrentItem(boundsSize - 1); return; } final int countMinusOne = count - 1; final float halfWidth = getWidth() / 2f; final int left = getLeft(); final float leftClip = left + mClipPadding; final int width = getWidth(); int height = getHeight(); final int right = left + width; final float rightClip = right - mClipPadding; int page = mCurrentPage; float offsetPercent; if (mPageOffset <= 0.5) { offsetPercent = mPageOffset; } else { page += 1; offsetPercent = 1 - mPageOffset; } final boolean currentSelected = (offsetPercent <= SELECTION_FADE_PERCENTAGE); final boolean currentBold = (offsetPercent <= BOLD_FADE_PERCENTAGE); final float selectedPercent = (SELECTION_FADE_PERCENTAGE - offsetPercent) / SELECTION_FADE_PERCENTAGE; // Verify if the current view must be clipped to the screen Rect curPageBound = bounds.get(mCurrentPage); float curPageWidth = curPageBound.right - curPageBound.left; if (curPageBound.left < leftClip) { // Try to clip to the screen (left side) clipViewOnTheLeft(curPageBound, curPageWidth, left); } if (curPageBound.right > rightClip) { // Try to clip to the screen (right side) clipViewOnTheRight(curPageBound, curPageWidth, right); } // Left views starting from the current position if (mCurrentPage > 0) { for (int i = mCurrentPage - 1; i >= 0; i--) { Rect bound = bounds.get(i); // Is left side is outside the screen if (bound.left < leftClip) { int w = bound.right - bound.left; // Try to clip to the screen (left side) clipViewOnTheLeft(bound, w, left); // Except if there's an intersection with the right view Rect rightBound = bounds.get(i + 1); // Intersection if (bound.right + mTitlePadding > rightBound.left) { bound.left = (int) (rightBound.left - w - mTitlePadding); bound.right = bound.left + w; } } } } // Right views starting from the current position if (mCurrentPage < countMinusOne) { for (int i = mCurrentPage + 1; i < count; i++) { Rect bound = bounds.get(i); // If right side is outside the screen if (bound.right > rightClip) { int w = bound.right - bound.left; // Try to clip to the screen (right side) clipViewOnTheRight(bound, w, right); // Except if there's an intersection with the left view Rect leftBound = bounds.get(i - 1); // Intersection if (bound.left - mTitlePadding < leftBound.right) { bound.left = (int) (leftBound.right + mTitlePadding); bound.right = bound.left + w; } } } } // Now draw views int colorTextAlpha = mColorText >>> 24; for (int i = 0; i < count; i++) { // Get the title Rect bound = bounds.get(i); // Only if one side is visible if ((bound.left > left && bound.left < right) || (bound.right > left && bound.right < right)) { final boolean currentPage = (i == page); final CharSequence pageTitle = getTitle(i); // Only set bold if we are within bounds mPaintText.setFakeBoldText(currentPage && currentBold && mBoldText); // Draw text as unselected mPaintText.setColor(mColorText); if (currentPage && currentSelected) { // Fade out/in unselected text as the selected text fades // in/out mPaintText.setAlpha(colorTextAlpha - (int) (colorTextAlpha * selectedPercent)); } // Except if there's an intersection with the right view if (i < boundsSize - 1) { Rect rightBound = bounds.get(i + 1); // Intersection if (bound.right + mTitlePadding > rightBound.left) { int w = bound.right - bound.left; bound.left = (int) (rightBound.left - w - mTitlePadding); bound.right = bound.left + w; } } canvas.drawText(pageTitle, 0, pageTitle.length(), bound.left, bound.bottom + mTopPadding, mPaintText); if (i == 0 && mIsShowPoint) { canvas.drawCircle(bound.right - 5, bound.top + (bound.bottom - bound.top) / 3 + mTopPadding, 5, mPaintCircle); } // If we are within the selected bounds draw the selected text if (currentPage && currentSelected) { mPaintText.setColor(mColorSelected); mPaintText.setAlpha((int) ((mColorSelected >>> 24) * selectedPercent)); canvas.drawText(pageTitle, 0, pageTitle.length(), bound.left, bound.bottom + mTopPadding, mPaintText); } } } // If we want the line on the top change height to zero and invert the // line height to trick the drawing code float footerLineHeight = mFooterLineHeight; float footerIndicatorLineHeight = mFooterIndicatorHeight; if (mLinePosition == LinePosition.Top) { height = 0; footerLineHeight = -footerLineHeight; footerIndicatorLineHeight = -footerIndicatorLineHeight; } // Draw the footer line mPath.reset(); mPath.moveTo(0, height - footerLineHeight / 2f); mPath.lineTo(width, height - footerLineHeight / 2f); mPath.close(); canvas.drawPath(mPath, mPaintFooterLine); float heightMinusLine = height - footerLineHeight; switch (mFooterIndicatorStyle) { case Triangle: mPath.reset(); mPath.moveTo(halfWidth, heightMinusLine - footerIndicatorLineHeight); mPath.lineTo(halfWidth + footerIndicatorLineHeight, heightMinusLine); mPath.lineTo(halfWidth - footerIndicatorLineHeight, heightMinusLine); mPath.close(); canvas.drawPath(mPath, mPaintFooterIndicator); break; case Underline: if (!currentSelected || page >= boundsSize) { break; } Rect underlineBounds = bounds.get(page); final float rightPlusPadding = underlineBounds.right + mFooterIndicatorUnderlinePadding; final float leftMinusPadding = underlineBounds.left - mFooterIndicatorUnderlinePadding; final float heightMinusLineMinusIndicator = heightMinusLine - footerIndicatorLineHeight; mPath.reset(); mPath.moveTo(leftMinusPadding, heightMinusLine); mPath.lineTo(rightPlusPadding, heightMinusLine); mPath.lineTo(rightPlusPadding, heightMinusLineMinusIndicator); mPath.lineTo(leftMinusPadding, heightMinusLineMinusIndicator); mPath.close(); mPaintFooterIndicator.setAlpha((int) (0xFF * selectedPercent)); canvas.drawPath(mPath, mPaintFooterIndicator); mPaintFooterIndicator.setAlpha(0xFF); break; default: break; } }
From source file:com.icloud.listenbook.base.view.viewpagerindicator.TitlePageIndicator.java
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (mViewPager == null) { return;// w w w .j a v a 2 s .co m } final int count = mViewPager.getAdapter().getCount(); if (count == 0) { return; } // mCurrentPage is -1 on first start and after orientation changed. If // so, retrieve the correct index from viewpager. if (mCurrentPage == -1 && mViewPager != null) { mCurrentPage = mViewPager.getCurrentItem(); } // Calculate views bounds ArrayList<Rect> bounds = calculateAllBounds(mPaintText); final int boundsSize = bounds.size(); // Make sure we're on a page that still exists if (mCurrentPage >= boundsSize) { setCurrentItem(boundsSize - 1); return; } final int countMinusOne = count - 1; final float halfWidth = getWidth() / 2f; final int left = getLeft(); final float leftClip = left + mClipPadding; final int width = getWidth(); int height = getHeight(); final int right = left + width; final float rightClip = right - mClipPadding; int page = mCurrentPage; float offsetPercent; if (mPageOffset <= 0.5) { offsetPercent = mPageOffset; } else { page += 1; offsetPercent = 1 - mPageOffset; } final boolean currentSelected = (offsetPercent <= SELECTION_FADE_PERCENTAGE); final boolean currentBold = (offsetPercent <= BOLD_FADE_PERCENTAGE); final float selectedPercent = (SELECTION_FADE_PERCENTAGE - offsetPercent) / SELECTION_FADE_PERCENTAGE; // Verify if the current view must be clipped to the screen Rect curPageBound = bounds.get(mCurrentPage); float curPageWidth = curPageBound.right - curPageBound.left; if (curPageBound.left < leftClip) { // Try to clip to the screen (left side) clipViewOnTheLeft(curPageBound, curPageWidth, left); } if (curPageBound.right > rightClip) { // Try to clip to the screen (right side) clipViewOnTheRight(curPageBound, curPageWidth, right); } // Left views starting from the current position if (mCurrentPage > 0) { for (int i = mCurrentPage - 1; i >= 0; i--) { Rect bound = bounds.get(i); // Is left side is outside the screen if (bound.left < leftClip) { int w = bound.right - bound.left; // Try to clip to the screen (left side) clipViewOnTheLeft(bound, w, left); // Except if there's an intersection with the right view Rect rightBound = bounds.get(i + 1); if (mTitlePadding == TITLEPADDINGMAX && (i == (mCurrentPage - 1))) { bound.left -= width * mPageOffset; bound.right = bound.left + w; } else if (bound.right + mTitlePadding > rightBound.left) { bound.left = (int) (rightBound.left - w - mTitlePadding); bound.right = bound.left + w; } } } } // Right views starting from the current position if (mCurrentPage < countMinusOne) { for (int i = mCurrentPage + 1; i < count; i++) { Rect bound = bounds.get(i); // If right side is outside the screen if (bound.right > rightClip) { int w = bound.right - bound.left; // Try to clip to the screen (right side) clipViewOnTheRight(bound, w, right); // Except if there's an intersection with the left view Rect leftBound = bounds.get(i - 1); // Intersection if (mTitlePadding == TITLEPADDINGMAX && (i == (page + 1) || i == (mCurrentPage + 1))) { if (mCurrentPage != page) { bound.left += width * (1 - mPageOffset); bound.right = bound.left + w; } } else if (bound.left - mTitlePadding < leftBound.right) { bound.left = (int) (leftBound.right + mTitlePadding); bound.right = bound.left + w; } } } } // Now draw views int colorTextAlpha = mColorText >>> 24; for (int i = 0; i < count; i++) { // Get the title Rect bound = bounds.get(i); // Only if one side is visible if ((bound.left > left && bound.left < right) || (bound.right > left && bound.right < right)) { final boolean currentPage = (i == page); final CharSequence pageTitle = getTitle(i); // Only set bold if we are within bounds mPaintText.setFakeBoldText(currentPage && currentBold && mBoldText); // Draw text as unselected mPaintText.setColor(mColorText); if (currentPage && currentSelected) { // Fade out/in unselected text as the selected text fades // in/out mPaintText.setAlpha(colorTextAlpha - (int) (colorTextAlpha * selectedPercent)); } // Except if there's an intersection with the right view if (i < boundsSize - 1) { Rect rightBound = bounds.get(i + 1); // Intersection if (mTitlePadding != TITLEPADDINGMAX && bound.right + mTitlePadding > rightBound.left) { int w = bound.right - bound.left; bound.left = (int) (rightBound.left - w - mTitlePadding); bound.right = bound.left + w; } } canvas.drawText(pageTitle, 0, pageTitle.length(), bound.left, bound.bottom + mTopPadding, mPaintText); // If we are within the selected bounds draw the selected text if (currentPage && currentSelected) { mPaintText.setColor(mColorSelected); mPaintText.setAlpha((int) ((mColorSelected >>> 24) * selectedPercent)); canvas.drawText(pageTitle, 0, pageTitle.length(), bound.left, bound.bottom + mTopPadding, mPaintText); } } } // If we want the line on the top change height to zero and invert the // line height to trick the drawing code float footerLineHeight = mFooterLineHeight; float footerIndicatorLineHeight = mFooterIndicatorHeight; if (mLinePosition == LinePosition.Top) { height = 0; footerLineHeight = -footerLineHeight; footerIndicatorLineHeight = -footerIndicatorLineHeight; } // Draw the footer line mPath.reset(); mPath.moveTo(0, height - footerLineHeight / 2f); mPath.lineTo(width, height - footerLineHeight / 2f); mPath.close(); canvas.drawPath(mPath, mPaintFooterLine); float heightMinusLine = height - footerLineHeight; switch (mFooterIndicatorStyle) { case Triangle: mPath.reset(); mPath.moveTo(halfWidth, heightMinusLine - footerIndicatorLineHeight); mPath.lineTo(halfWidth + footerIndicatorLineHeight, heightMinusLine); mPath.lineTo(halfWidth - footerIndicatorLineHeight, heightMinusLine); mPath.close(); canvas.drawPath(mPath, mPaintFooterIndicator); break; case Underline: if (!currentSelected || page >= boundsSize) { break; } Rect underlineBounds = bounds.get(page); final float rightPlusPadding = underlineBounds.right + mFooterIndicatorUnderlinePadding; final float leftMinusPadding = underlineBounds.left - mFooterIndicatorUnderlinePadding; final float heightMinusLineMinusIndicator = heightMinusLine - footerIndicatorLineHeight; mPath.reset(); mPath.moveTo(leftMinusPadding, heightMinusLine); mPath.lineTo(rightPlusPadding, heightMinusLine); mPath.lineTo(rightPlusPadding, heightMinusLineMinusIndicator); mPath.lineTo(leftMinusPadding, heightMinusLineMinusIndicator); mPath.close(); mPaintFooterIndicator.setAlpha((int) (0xFF * selectedPercent)); canvas.drawPath(mPath, mPaintFooterIndicator); mPaintFooterIndicator.setAlpha(0xFF); break; } }
From source file:com.home.library.vpi.TitlePageIndicator.java
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (mViewPager == null) { return;//from ww w .ja v a2 s. co m } final int count = mViewPager.getAdapter().getCount(); if (count == 0) { return; } // mCurrentPage is -1 on first start and after orientation changed. If so, retrieve the correct index from viewpager. if (mCurrentPage == -1 && mViewPager != null) { mCurrentPage = mViewPager.getCurrentItem(); } //Calculate views bounds ArrayList<Rect> bounds = calculateAllBounds(mPaintText); final int boundsSize = bounds.size(); //Make sure we're on a page that still exists if (mCurrentPage >= boundsSize) { setCurrentItem(boundsSize - 1); return; } setBackGroundColor(canvas); final int countMinusOne = count - 1; final float halfWidth = getWidth() / 2f; final int left = getLeft(); final float leftClip = left + mClipPadding; final int width = getWidth(); int height = getHeight(); final int right = left + width; final float rightClip = right - mClipPadding; int page = mCurrentPage; float offsetPercent; if (mPageOffset <= 0.5) { offsetPercent = mPageOffset; } else { page += 1; offsetPercent = 1 - mPageOffset; } final boolean currentSelected = (offsetPercent <= SELECTION_FADE_PERCENTAGE); final boolean currentBold = (offsetPercent <= BOLD_FADE_PERCENTAGE); final float selectedPercent = (SELECTION_FADE_PERCENTAGE - offsetPercent) / SELECTION_FADE_PERCENTAGE; //Verify if the current view must be clipped to the screen Rect curPageBound = bounds.get(mCurrentPage); float curPageWidth = curPageBound.right - curPageBound.left; if (curPageBound.left < leftClip) { //Try to clip to the screen (left side) clipViewOnTheLeft(curPageBound, curPageWidth, left); } if (curPageBound.right > rightClip) { //Try to clip to the screen (right side) clipViewOnTheRight(curPageBound, curPageWidth, right); } //Left views starting from the current position if (mCurrentPage > 0) { for (int i = mCurrentPage - 1; i >= 0; i--) { Rect bound = bounds.get(i); //Is left side is outside the screen if (bound.left < leftClip) { int w = bound.right - bound.left; //Try to clip to the screen (left side) clipViewOnTheLeft(bound, w, left); //Except if there's an intersection with the right view Rect rightBound = bounds.get(i + 1); //Intersection if (bound.right + mTitlePadding > rightBound.left) { bound.left = (int) (rightBound.left - w - mTitlePadding); bound.right = bound.left + w; } } } } //Right views starting from the current position if (mCurrentPage < countMinusOne) { for (int i = mCurrentPage + 1; i < count; i++) { Rect bound = bounds.get(i); //If right side is outside the screen if (bound.right > rightClip) { int w = bound.right - bound.left; //Try to clip to the screen (right side) clipViewOnTheRight(bound, w, right); //Except if there's an intersection with the left view Rect leftBound = bounds.get(i - 1); //Intersection if (bound.left - mTitlePadding < leftBound.right) { bound.left = (int) (leftBound.right + mTitlePadding); bound.right = bound.left + w; } } } } //Now draw views int colorTextAlpha = mColorText >>> 24; for (int i = 0; i < count; i++) { //Get the title Rect bound = bounds.get(i); //Only if one side is visible if ((bound.left > left && bound.left < right) || (bound.right > left && bound.right < right)) { final boolean currentPage = (i == page); final CharSequence pageTitle = getTitle(i); //Only set bold if we are within bounds mPaintText.setFakeBoldText(currentPage && currentBold && mBoldText); //Draw text as unselected if (mScrollState != ViewPager.SCROLL_STATE_IDLE) { mPaintText.setColor(mColorText); } if (currentPage && currentSelected && mScrollState != ViewPager.SCROLL_STATE_IDLE) { //Fade out/in unselected text as the selected text fades in/out mPaintText.setAlpha(colorTextAlpha - (int) (colorTextAlpha * selectedPercent)); } //Except if there's an intersection with the right view if (i < boundsSize - 1) { Rect rightBound = bounds.get(i + 1); //Intersection if (bound.right + mTitlePadding > rightBound.left) { int w = bound.right - bound.left; bound.left = (int) (rightBound.left - w - mTitlePadding); bound.right = bound.left + w; } } canvas.drawText(pageTitle, 0, pageTitle.length(), bound.left, bound.bottom + mTopPadding, mPaintText); //If we are within the selected bounds draw the selected text if (currentPage && currentSelected) { //mScrollState != ViewPager.SCROLL_STATE_IDLE if (mScrollState != ViewPager.SCROLL_STATE_IDLE) { mPaintText.setColor(mColorSelected); mPaintText.setAlpha((int) ((mColorSelected >>> 24) * selectedPercent)); } canvas.drawText(pageTitle, 0, pageTitle.length(), bound.left, bound.bottom + mTopPadding, mPaintText); } } } //If we want the line on the top change height to zero and invert the line height to trick the drawing code float footerLineHeight = mFooterLineHeight; float footerIndicatorLineHeight = mFooterIndicatorHeight; if (mLinePosition == LinePosition.Top) { height = 0; footerLineHeight = -footerLineHeight; footerIndicatorLineHeight = -footerIndicatorLineHeight; } //Draw the footer line mPath.reset(); mPath.moveTo(0, height - footerLineHeight / 2f); mPath.lineTo(width, height - footerLineHeight / 2f); mPath.close(); if (mScrollState != ViewPager.SCROLL_STATE_IDLE) { mPaintFooterLine.setColor(mFooterColor); } canvas.drawPath(mPath, mPaintFooterLine); float heightMinusLine = height - footerLineHeight; switch (mFooterIndicatorStyle) { case Triangle: mPath.reset(); mPath.moveTo(halfWidth, heightMinusLine - footerIndicatorLineHeight); mPath.lineTo(halfWidth + footerIndicatorLineHeight, heightMinusLine); mPath.lineTo(halfWidth - footerIndicatorLineHeight, heightMinusLine); mPath.close(); canvas.drawPath(mPath, mPaintFooterIndicator); break; case Underline: if (!currentSelected || page >= boundsSize) { break; } Rect underlineBounds = bounds.get(page); final float rightPlusPadding = underlineBounds.right + mFooterIndicatorUnderlinePadding; final float leftMinusPadding = underlineBounds.left - mFooterIndicatorUnderlinePadding; final float heightMinusLineMinusIndicator = heightMinusLine - footerIndicatorLineHeight; mPath.reset(); mPath.moveTo(leftMinusPadding, heightMinusLine); mPath.lineTo(rightPlusPadding, heightMinusLine); mPath.lineTo(rightPlusPadding, heightMinusLineMinusIndicator); mPath.lineTo(leftMinusPadding, heightMinusLineMinusIndicator); mPath.close(); if (mScrollState != ViewPager.SCROLL_STATE_IDLE) { mPaintFooterIndicator.setAlpha((int) (0xFF * selectedPercent)); } canvas.drawPath(mPath, mPaintFooterIndicator); if (mScrollState != ViewPager.SCROLL_STATE_IDLE) { mPaintFooterIndicator.setAlpha(0xFF); } break; } }
From source file:org.onebusaway.android.map.googlemapsv2.StopOverlay.java
/** * Creates a bus stop icon with the given direction arrow, or without a direction arrow if * the direction is NO_DIRECTION/* w w w . j av a 2 s.co m*/ * * @param direction Bus stop direction, obtained from ObaStop.getDirection() and defined in * constants in this class, or NO_DIRECTION if the stop icon shouldn't have a * direction arrow * @return a bus stop icon bitmap with the arrow pointing the given direction, or with no arrow * if direction is NO_DIRECTION */ private static Bitmap createBusStopIcon(String direction) throws NullPointerException { if (direction == null) { throw new IllegalArgumentException(direction); } Resources r = Application.get().getResources(); Context context = Application.get(); Float directionAngle = null; // 0-360 degrees Bitmap bm; Canvas c; Drawable shape; Float rotationX = null, rotationY = null; // Point around which to rotate the arrow Paint arrowPaintFill = new Paint(); arrowPaintFill.setStyle(Paint.Style.FILL); arrowPaintFill.setAntiAlias(true); if (direction.equals(NO_DIRECTION)) { // Don't draw the arrow bm = Bitmap.createBitmap(mPx, mPx, Bitmap.Config.ARGB_8888); c = new Canvas(bm); shape = ContextCompat.getDrawable(context, R.drawable.map_stop_icon); shape.setBounds(0, 0, bm.getWidth(), bm.getHeight()); } else if (direction.equals(NORTH)) { directionAngle = 0f; bm = Bitmap.createBitmap(mPx, (int) (mPx + mBuffer), Bitmap.Config.ARGB_8888); c = new Canvas(bm); shape = ContextCompat.getDrawable(context, R.drawable.map_stop_icon); shape.setBounds(0, (int) mBuffer, mPx, bm.getHeight()); // Shade with darkest color at tip of arrow arrowPaintFill.setShader(new LinearGradient(bm.getWidth() / 2, 0, bm.getWidth() / 2, mArrowHeightPx, r.getColor(R.color.theme_primary), r.getColor(R.color.theme_accent), Shader.TileMode.MIRROR)); // For NORTH, no rotation occurs - use center of image anyway so we have some value rotationX = bm.getWidth() / 2f; rotationY = bm.getHeight() / 2f; } else if (direction.equals(NORTH_WEST)) { directionAngle = 315f; // Arrow is drawn N, rotate 315 degrees bm = Bitmap.createBitmap((int) (mPx + mBuffer), (int) (mPx + mBuffer), Bitmap.Config.ARGB_8888); c = new Canvas(bm); shape = ContextCompat.getDrawable(context, R.drawable.map_stop_icon); shape.setBounds((int) mBuffer, (int) mBuffer, bm.getWidth(), bm.getHeight()); // Shade with darkest color at tip of arrow arrowPaintFill.setShader(new LinearGradient(0, 0, mBuffer, mBuffer, r.getColor(R.color.theme_primary), r.getColor(R.color.theme_accent), Shader.TileMode.MIRROR)); // Rotate around below coordinates (trial and error) rotationX = mPx / 2f + mBuffer / 2f; rotationY = bm.getHeight() / 2f - mBuffer / 2f; } else if (direction.equals(WEST)) { directionAngle = 0f; // Arrow is drawn pointing West, so no rotation bm = Bitmap.createBitmap((int) (mPx + mBuffer), mPx, Bitmap.Config.ARGB_8888); c = new Canvas(bm); shape = ContextCompat.getDrawable(context, R.drawable.map_stop_icon); shape.setBounds((int) mBuffer, 0, bm.getWidth(), bm.getHeight()); arrowPaintFill.setShader(new LinearGradient(0, bm.getHeight() / 2, mArrowHeightPx, bm.getHeight() / 2, r.getColor(R.color.theme_primary), r.getColor(R.color.theme_accent), Shader.TileMode.MIRROR)); // For WEST rotationX = bm.getHeight() / 2f; rotationY = bm.getHeight() / 2f; } else if (direction.equals(SOUTH_WEST)) { directionAngle = 225f; // Arrow is drawn N, rotate 225 degrees bm = Bitmap.createBitmap((int) (mPx + mBuffer), (int) (mPx + mBuffer), Bitmap.Config.ARGB_8888); c = new Canvas(bm); shape = ContextCompat.getDrawable(context, R.drawable.map_stop_icon); shape.setBounds((int) mBuffer, 0, bm.getWidth(), mPx); arrowPaintFill.setShader(new LinearGradient(0, bm.getHeight(), mBuffer, bm.getHeight() - mBuffer, r.getColor(R.color.theme_primary), r.getColor(R.color.theme_accent), Shader.TileMode.MIRROR)); // Rotate around below coordinates (trial and error) rotationX = bm.getWidth() / 2f - mBuffer / 4f; rotationY = mPx / 2f + mBuffer / 4f; } else if (direction.equals(SOUTH)) { directionAngle = 180f; // Arrow is drawn N, rotate 180 degrees bm = Bitmap.createBitmap(mPx, (int) (mPx + mBuffer), Bitmap.Config.ARGB_8888); c = new Canvas(bm); shape = ContextCompat.getDrawable(context, R.drawable.map_stop_icon); shape.setBounds(0, 0, bm.getWidth(), (int) (bm.getHeight() - mBuffer)); arrowPaintFill.setShader(new LinearGradient(bm.getWidth() / 2, bm.getHeight(), bm.getWidth() / 2, bm.getHeight() - mArrowHeightPx, r.getColor(R.color.theme_primary), r.getColor(R.color.theme_accent), Shader.TileMode.MIRROR)); rotationX = bm.getWidth() / 2f; rotationY = bm.getHeight() / 2f; } else if (direction.equals(SOUTH_EAST)) { directionAngle = 135f; // Arrow is drawn N, rotate 135 degrees bm = Bitmap.createBitmap((int) (mPx + mBuffer), (int) (mPx + mBuffer), Bitmap.Config.ARGB_8888); c = new Canvas(bm); shape = ContextCompat.getDrawable(context, R.drawable.map_stop_icon); shape.setBounds(0, 0, mPx, mPx); arrowPaintFill.setShader(new LinearGradient(bm.getWidth(), bm.getHeight(), bm.getWidth() - mBuffer, bm.getHeight() - mBuffer, r.getColor(R.color.theme_primary), r.getColor(R.color.theme_accent), Shader.TileMode.MIRROR)); // Rotate around below coordinates (trial and error) rotationX = (mPx + mBuffer / 2) / 2f; rotationY = bm.getHeight() / 2f; } else if (direction.equals(EAST)) { directionAngle = 180f; // Arrow is drawn pointing West, so rotate 180 bm = Bitmap.createBitmap((int) (mPx + mBuffer), mPx, Bitmap.Config.ARGB_8888); c = new Canvas(bm); shape = ContextCompat.getDrawable(context, R.drawable.map_stop_icon); shape.setBounds(0, 0, mPx, bm.getHeight()); arrowPaintFill.setShader(new LinearGradient(bm.getWidth(), bm.getHeight() / 2, bm.getWidth() - mArrowHeightPx, bm.getHeight() / 2, r.getColor(R.color.theme_primary), r.getColor(R.color.theme_accent), Shader.TileMode.MIRROR)); rotationX = bm.getWidth() / 2f; rotationY = bm.getHeight() / 2f; } else if (direction.equals(NORTH_EAST)) { directionAngle = 45f; // Arrow is drawn pointing N, so rotate 45 degrees bm = Bitmap.createBitmap((int) (mPx + mBuffer), (int) (mPx + mBuffer), Bitmap.Config.ARGB_8888); c = new Canvas(bm); shape = ContextCompat.getDrawable(context, R.drawable.map_stop_icon); shape.setBounds(0, (int) mBuffer, mPx, bm.getHeight()); // Shade with darkest color at tip of arrow arrowPaintFill.setShader(new LinearGradient(bm.getWidth(), 0, bm.getWidth() - mBuffer, mBuffer, r.getColor(R.color.theme_primary), r.getColor(R.color.theme_accent), Shader.TileMode.MIRROR)); // Rotate around middle of circle rotationX = (float) mPx / 2; rotationY = bm.getHeight() - (float) mPx / 2; } else { throw new IllegalArgumentException(direction); } shape.draw(c); if (direction.equals(NO_DIRECTION)) { // Everything after this point is for drawing the arrow image, so return the bitmap as-is for no arrow return bm; } /** * Draw the arrow - all dimensions should be relative to px so the arrow is drawn the same * size for all orientations */ // Height of the cutout in the bottom of the triangle that makes it an arrow (0=triangle) final float CUTOUT_HEIGHT = mPx / 12; Path path = new Path(); float x1 = 0, y1 = 0; // Tip of arrow float x2 = 0, y2 = 0; // lower left float x3 = 0, y3 = 0; // cutout in arrow bottom float x4 = 0, y4 = 0; // lower right if (direction.equals(NORTH) || direction.equals(SOUTH) || direction.equals(NORTH_EAST) || direction.equals(SOUTH_EAST) || direction.equals(NORTH_WEST) || direction.equals(SOUTH_WEST)) { // Arrow is drawn pointing NORTH // Tip of arrow x1 = mPx / 2; y1 = 0; // lower left x2 = (mPx / 2) - (mArrowWidthPx / 2); y2 = mArrowHeightPx; // cutout in arrow bottom x3 = mPx / 2; y3 = mArrowHeightPx - CUTOUT_HEIGHT; // lower right x4 = (mPx / 2) + (mArrowWidthPx / 2); y4 = mArrowHeightPx; } else if (direction.equals(EAST) || direction.equals(WEST)) { // Arrow is drawn pointing WEST // Tip of arrow x1 = 0; y1 = mPx / 2; // lower left x2 = mArrowHeightPx; y2 = (mPx / 2) - (mArrowWidthPx / 2); // cutout in arrow bottom x3 = mArrowHeightPx - CUTOUT_HEIGHT; y3 = mPx / 2; // lower right x4 = mArrowHeightPx; y4 = (mPx / 2) + (mArrowWidthPx / 2); } path.setFillType(Path.FillType.EVEN_ODD); path.moveTo(x1, y1); path.lineTo(x2, y2); path.lineTo(x3, y3); path.lineTo(x4, y4); path.lineTo(x1, y1); path.close(); // Rotate arrow around (rotationX, rotationY) point Matrix matrix = new Matrix(); matrix.postRotate(directionAngle, rotationX, rotationY); path.transform(matrix); c.drawPath(path, arrowPaintFill); c.drawPath(path, mArrowPaintStroke); return bm; }
From source file:com.jjoe64.graphview.series.LineGraphSeries.java
/** * plots the series// ww w .j av a2 s . c o m * draws the line and the background * * @param graphView graphview * @param canvas canvas * @param isSecondScale flag if it is the second scale */ @Override public void draw(GraphView graphView, Canvas canvas, boolean isSecondScale) { resetDataPoints(); // get data double maxX = graphView.getViewport().getMaxX(false); double minX = graphView.getViewport().getMinX(false); double maxY; double minY; if (isSecondScale) { maxY = graphView.getSecondScale().getMaxY(false); minY = graphView.getSecondScale().getMinY(false); } else { maxY = graphView.getViewport().getMaxY(false); minY = graphView.getViewport().getMinY(false); } Iterator<E> values = getValues(minX, maxX); // draw background double lastEndY = 0; double lastEndX = 0; // draw data mPaint.setStrokeWidth(mStyles.thickness); mPaint.setColor(getColor()); mPaintBackground.setColor(mStyles.backgroundColor); Paint paint; if (mCustomPaint != null) { paint = mCustomPaint; } else { paint = mPaint; } mPath.reset(); if (mStyles.drawBackground) { mPathBackground.reset(); } double diffY = maxY - minY; double diffX = maxX - minX; float graphHeight = graphView.getGraphContentHeight(); float graphWidth = graphView.getGraphContentWidth(); float graphLeft = graphView.getGraphContentLeft(); float graphTop = graphView.getGraphContentTop(); lastEndY = 0; lastEndX = 0; // needed to end the path for background double lastUsedEndX = 0; double lastUsedEndY = 0; float firstX = -1; float firstY = -1; float lastRenderedX = Float.NaN; int i = 0; float lastAnimationReferenceX = graphLeft; boolean sameXSkip = false; float minYOnSameX = 0f; float maxYOnSameX = 0f; while (values.hasNext()) { E value = values.next(); double valY = value.getY() - minY; double ratY = valY / diffY; double y = graphHeight * ratY; double valueX = value.getX(); double valX = valueX - minX; double ratX = valX / diffX; double x = graphWidth * ratX; double orgX = x; double orgY = y; if (i > 0) { // overdraw boolean isOverdrawY = false; boolean isOverdrawEndPoint = false; boolean skipDraw = false; if (x > graphWidth) { // end right double b = ((graphWidth - lastEndX) * (y - lastEndY) / (x - lastEndX)); y = lastEndY + b; x = graphWidth; isOverdrawEndPoint = true; } if (y < 0) { // end bottom // skip when previous and this point is out of bound if (lastEndY < 0) { skipDraw = true; } else { double b = ((0 - lastEndY) * (x - lastEndX) / (y - lastEndY)); x = lastEndX + b; } y = 0; isOverdrawY = isOverdrawEndPoint = true; } if (y > graphHeight) { // end top // skip when previous and this point is out of bound if (lastEndY > graphHeight) { skipDraw = true; } else { double b = ((graphHeight - lastEndY) * (x - lastEndX) / (y - lastEndY)); x = lastEndX + b; } y = graphHeight; isOverdrawY = isOverdrawEndPoint = true; } if (lastEndX < 0) { // start left double b = ((0 - x) * (y - lastEndY) / (lastEndX - x)); lastEndY = y - b; lastEndX = 0; } // we need to save the X before it will be corrected when overdraw y float orgStartX = (float) lastEndX + (graphLeft + 1); if (lastEndY < 0) { // start bottom if (!skipDraw) { double b = ((0 - y) * (x - lastEndX) / (lastEndY - y)); lastEndX = x - b; } lastEndY = 0; isOverdrawY = true; } if (lastEndY > graphHeight) { // start top // skip when previous and this point is out of bound if (!skipDraw) { double b = ((graphHeight - y) * (x - lastEndX) / (lastEndY - y)); lastEndX = x - b; } lastEndY = graphHeight; isOverdrawY = true; } float startX = (float) lastEndX + (graphLeft + 1); float startY = (float) (graphTop - lastEndY) + graphHeight; float endX = (float) x + (graphLeft + 1); float endY = (float) (graphTop - y) + graphHeight; float startXAnimated = startX; float endXAnimated = endX; if (endX < startX) { // dont draw from right to left skipDraw = true; } // NaN can happen when previous and current value is out of y bounds if (!skipDraw && !Float.isNaN(startY) && !Float.isNaN(endY)) { // animation if (mAnimated) { if ((Double.isNaN(mLastAnimatedValue) || mLastAnimatedValue < valueX)) { long currentTime = System.currentTimeMillis(); if (mAnimationStart == 0) { // start animation mAnimationStart = currentTime; mAnimationStartFrameNo = 0; } else { // anti-lag: wait a few frames if (mAnimationStartFrameNo < 15) { // second time mAnimationStart = currentTime; mAnimationStartFrameNo++; } } float timeFactor = (float) (currentTime - mAnimationStart) / ANIMATION_DURATION; float factor = mAnimationInterpolator.getInterpolation(timeFactor); if (timeFactor <= 1.0) { startXAnimated = (startX - lastAnimationReferenceX) * factor + lastAnimationReferenceX; startXAnimated = Math.max(startXAnimated, lastAnimationReferenceX); endXAnimated = (endX - lastAnimationReferenceX) * factor + lastAnimationReferenceX; ViewCompat.postInvalidateOnAnimation(graphView); } else { // animation finished mLastAnimatedValue = valueX; } } else { lastAnimationReferenceX = endX; } } // draw data point if (!isOverdrawEndPoint) { if (mStyles.drawDataPoints) { // draw first datapoint Paint.Style prevStyle = paint.getStyle(); paint.setStyle(Paint.Style.FILL); canvas.drawCircle(endXAnimated, endY, mStyles.dataPointsRadius, paint); paint.setStyle(prevStyle); } registerDataPoint(endX, endY, value); } if (mDrawAsPath) { mPath.moveTo(startXAnimated, startY); } // performance opt. if (Float.isNaN(lastRenderedX) || Math.abs(endX - lastRenderedX) > .3f) { if (mDrawAsPath) { mPath.lineTo(endXAnimated, endY); } else { // render vertical lines that were skipped if (sameXSkip) { sameXSkip = false; renderLine(canvas, new float[] { lastRenderedX, minYOnSameX, lastRenderedX, maxYOnSameX }, paint); } renderLine(canvas, new float[] { startXAnimated, startY, endXAnimated, endY }, paint); } lastRenderedX = endX; } else { // rendering on same x position // save min+max y position and render it as line if (sameXSkip) { minYOnSameX = Math.min(minYOnSameX, endY); maxYOnSameX = Math.max(maxYOnSameX, endY); } else { // first sameXSkip = true; minYOnSameX = Math.min(startY, endY); maxYOnSameX = Math.max(startY, endY); } } } if (mStyles.drawBackground) { if (isOverdrawY) { // start draw original x if (firstX == -1) { firstX = orgStartX; firstY = startY; mPathBackground.moveTo(orgStartX, startY); } // from original start to new start mPathBackground.lineTo(startXAnimated, startY); } if (firstX == -1) { firstX = startXAnimated; firstY = startY; mPathBackground.moveTo(startXAnimated, startY); } mPathBackground.lineTo(startXAnimated, startY); mPathBackground.lineTo(endXAnimated, endY); } lastUsedEndX = endXAnimated; lastUsedEndY = endY; } else if (mStyles.drawDataPoints) { //fix: last value not drawn as datapoint. Draw first point here, and then on every step the end values (above) float first_X = (float) x + (graphLeft + 1); float first_Y = (float) (graphTop - y) + graphHeight; if (first_X >= graphLeft && first_Y <= (graphTop + graphHeight)) { if (mAnimated && (Double.isNaN(mLastAnimatedValue) || mLastAnimatedValue < valueX)) { long currentTime = System.currentTimeMillis(); if (mAnimationStart == 0) { // start animation mAnimationStart = currentTime; } float timeFactor = (float) (currentTime - mAnimationStart) / ANIMATION_DURATION; float factor = mAnimationInterpolator.getInterpolation(timeFactor); if (timeFactor <= 1.0) { first_X = (first_X - lastAnimationReferenceX) * factor + lastAnimationReferenceX; ViewCompat.postInvalidateOnAnimation(graphView); } else { // animation finished mLastAnimatedValue = valueX; } } Paint.Style prevStyle = paint.getStyle(); paint.setStyle(Paint.Style.FILL); canvas.drawCircle(first_X, first_Y, mStyles.dataPointsRadius, paint); paint.setStyle(prevStyle); } } lastEndY = orgY; lastEndX = orgX; i++; } if (mDrawAsPath) { // draw at the end canvas.drawPath(mPath, paint); } if (mStyles.drawBackground && firstX != -1) { // end / close path if (lastUsedEndY != graphHeight + graphTop) { // dont draw line to same point, otherwise the path is completely broken mPathBackground.lineTo((float) lastUsedEndX, graphHeight + graphTop); } mPathBackground.lineTo(firstX, graphHeight + graphTop); if (firstY != graphHeight + graphTop) { // dont draw line to same point, otherwise the path is completely broken mPathBackground.lineTo(firstX, firstY); } //mPathBackground.close(); canvas.drawPath(mPathBackground, mPaintBackground); } }
From source file:p5e610.graphview.series.LineGraphSeries.java
/** * plots the series/*from ww w . j a v a2 s . c o m*/ * draws the line and the background * * @param graphView graphview * @param canvas canvas * @param isSecondScale flag if it is the second scale */ @Override public void draw(GraphView graphView, Canvas canvas, boolean isSecondScale) { resetDataPoints(); // get data double maxY = Double.NEGATIVE_INFINITY; double maxX = Double.NEGATIVE_INFINITY; double minY = Double.POSITIVE_INFINITY; double minX = Double.POSITIVE_INFINITY; boolean minXSet = graphView.getViewport().getMinX(false) != null; boolean maxXSet = graphView.getViewport().getMaxX(false) != null; boolean minYSet = graphView.getViewport().getMinY(false) != null; boolean maxYSet = graphView.getViewport().getMaxY(false) != null; if (minXSet) minX = graphView.getViewport().getMinX(false); if (maxXSet) { maxX = graphView.getViewport().getMaxX(false); } if (minYSet) { minY = graphView.getViewport().getMinY(false); } if (maxYSet) { maxY = graphView.getViewport().getMaxY(false); } for (E val : mData) { double currX = val.getX(); double currY = val.getY(); if (currX > maxX && !maxXSet) maxX = currX; if (currY > maxY && !maxYSet) maxY = currY; if (currX < minX && !minXSet) minX = currX; if (currY < minY && !minYSet) minY = currY; } Iterator<E> values = getValues(minX, maxX); // draw background double lastEndY = 0; double lastEndX = 0; // draw data mPaint.setStrokeWidth(mStyles.thickness); mPaint.setColor(getColor()); mPaintBackground.setColor(mStyles.backgroundColor); Paint paint; if (mCustomPaint != null) { paint = mCustomPaint; } else { paint = mPaint; } mPath.reset(); if (mStyles.drawBackground) { mPathBackground.reset(); } double diffY = maxY - minY; double diffX = maxX - minX; float graphHeight = graphView.getGraphContentHeight(); float graphWidth = graphView.getGraphContentWidth(); float graphLeft = graphView.getGraphContentLeft(); float graphTop = graphView.getGraphContentTop(); lastEndY = 0; lastEndX = 0; // needed to end the path for background double lastUsedEndX = 0; double lastUsedEndY = 0; float firstX = -1; float firstY = -1; float lastRenderedX = Float.NaN; int i = 0; float lastAnimationReferenceX = graphLeft; boolean sameXSkip = false; float minYOnSameX = 0f; float maxYOnSameX = 0f; while (values.hasNext()) { E value = values.next(); double valY = value.getY() - minY; double ratY = valY / diffY; double y = graphHeight * ratY; double valueX = value.getX(); double valX = valueX - minX; double ratX = valX / diffX; double x = graphWidth * ratX; double orgX = x; double orgY = y; if (i > 0) { // overdraw boolean isOverdrawY = false; boolean isOverdrawEndPoint = false; boolean skipDraw = false; if (x > graphWidth) { // end right double b = ((graphWidth - lastEndX) * (y - lastEndY) / (x - lastEndX)); y = lastEndY + b; x = graphWidth; isOverdrawEndPoint = true; } if (y < 0) { // end bottom // skip when previous and this point is out of bound if (lastEndY < 0) { skipDraw = true; } else { double b = ((0 - lastEndY) * (x - lastEndX) / (y - lastEndY)); x = lastEndX + b; } y = 0; isOverdrawY = isOverdrawEndPoint = true; } if (y > graphHeight) { // end top // skip when previous and this point is out of bound if (lastEndY > graphHeight) { skipDraw = true; } else { double b = ((graphHeight - lastEndY) * (x - lastEndX) / (y - lastEndY)); x = lastEndX + b; } y = graphHeight; isOverdrawY = isOverdrawEndPoint = true; } if (lastEndX < 0) { // start left double b = ((0 - x) * (y - lastEndY) / (lastEndX - x)); lastEndY = y - b; lastEndX = 0; } // we need to save the X before it will be corrected when overdraw y float orgStartX = (float) lastEndX + (graphLeft + 1); if (lastEndY < 0) { // start bottom if (!skipDraw) { double b = ((0 - y) * (x - lastEndX) / (lastEndY - y)); lastEndX = x - b; } lastEndY = 0; isOverdrawY = true; } if (lastEndY > graphHeight) { // start top // skip when previous and this point is out of bound if (!skipDraw) { double b = ((graphHeight - y) * (x - lastEndX) / (lastEndY - y)); lastEndX = x - b; } lastEndY = graphHeight; isOverdrawY = true; } float startX = (float) lastEndX + (graphLeft + 1); float startY = (float) (graphTop - lastEndY) + graphHeight; float endX = (float) x + (graphLeft + 1); float endY = (float) (graphTop - y) + graphHeight; float startXAnimated = startX; float endXAnimated = endX; // if (endX < startX) { // // dont draw from right to left // skipDraw = true; // } // NaN can happen when previous and current value is out of y bounds if (!skipDraw && !Float.isNaN(startY) && !Float.isNaN(endY)) { // animation if (mAnimated) { if ((Double.isNaN(mLastAnimatedValue) || mLastAnimatedValue < valueX)) { long currentTime = System.currentTimeMillis(); if (mAnimationStart == 0) { // start animation mAnimationStart = currentTime; mAnimationStartFrameNo = 0; } else { // anti-lag: wait a few frames if (mAnimationStartFrameNo < 15) { // second time mAnimationStart = currentTime; mAnimationStartFrameNo++; } } float timeFactor = (float) (currentTime - mAnimationStart) / ANIMATION_DURATION; float factor = mAnimationInterpolator.getInterpolation(timeFactor); if (timeFactor <= 1.0) { startXAnimated = (startX - lastAnimationReferenceX) * factor + lastAnimationReferenceX; startXAnimated = Math.max(startXAnimated, lastAnimationReferenceX); endXAnimated = (endX - lastAnimationReferenceX) * factor + lastAnimationReferenceX; ViewCompat.postInvalidateOnAnimation(graphView); } else { // animation finished mLastAnimatedValue = valueX; } } else { lastAnimationReferenceX = endX; } } // draw data point if (!isOverdrawEndPoint) { if (mStyles.drawDataPoints) { // draw first datapoint Paint.Style prevStyle = paint.getStyle(); paint.setStyle(Paint.Style.FILL); canvas.drawCircle(endXAnimated, endY, mStyles.dataPointsRadius, paint); paint.setStyle(prevStyle); } registerDataPoint(endX, endY, value); } if (mDrawAsPath) { mPath.moveTo(startXAnimated, startY); } // performance opt. if (Float.isNaN(lastRenderedX) || Math.abs(endX - lastRenderedX) > .3f) { if (mDrawAsPath) { mPath.lineTo(endXAnimated, endY); } else { // render vertical lines that were skipped if (sameXSkip) { sameXSkip = false; renderLine(canvas, new float[] { lastRenderedX, minYOnSameX, lastRenderedX, maxYOnSameX }, paint); } renderLine(canvas, new float[] { startXAnimated, startY, endXAnimated, endY }, paint); } lastRenderedX = endX; } else { // rendering on same x position // save min+max y position and render it as line if (sameXSkip) { minYOnSameX = Math.min(minYOnSameX, endY); maxYOnSameX = Math.max(maxYOnSameX, endY); } else { // first sameXSkip = true; minYOnSameX = Math.min(startY, endY); maxYOnSameX = Math.max(startY, endY); } } } if (mStyles.drawBackground) { if (isOverdrawY) { // start draw original x if (firstX == -1) { firstX = orgStartX; firstY = startY; mPathBackground.moveTo(orgStartX, startY); } // from original start to new start mPathBackground.lineTo(startXAnimated, startY); } if (firstX == -1) { firstX = startXAnimated; firstY = startY; mPathBackground.moveTo(startXAnimated, startY); } mPathBackground.lineTo(startXAnimated, startY); mPathBackground.lineTo(endXAnimated, endY); } lastUsedEndX = endXAnimated; lastUsedEndY = endY; } else if (mStyles.drawDataPoints) { //fix: last value not drawn as datapoint. Draw first point here, and then on every step the end values (above) float first_X = (float) x + (graphLeft + 1); float first_Y = (float) (graphTop - y) + graphHeight; if (first_X >= graphLeft && first_Y <= (graphTop + graphHeight)) { if (mAnimated && (Double.isNaN(mLastAnimatedValue) || mLastAnimatedValue < valueX)) { long currentTime = System.currentTimeMillis(); if (mAnimationStart == 0) { // start animation mAnimationStart = currentTime; } float timeFactor = (float) (currentTime - mAnimationStart) / ANIMATION_DURATION; float factor = mAnimationInterpolator.getInterpolation(timeFactor); if (timeFactor <= 1.0) { first_X = (first_X - lastAnimationReferenceX) * factor + lastAnimationReferenceX; ViewCompat.postInvalidateOnAnimation(graphView); } else { // animation finished mLastAnimatedValue = valueX; } } Paint.Style prevStyle = paint.getStyle(); paint.setStyle(Paint.Style.FILL); canvas.drawCircle(first_X, first_Y, mStyles.dataPointsRadius, paint); paint.setStyle(prevStyle); } } lastEndY = orgY; lastEndX = orgX; i++; } if (mDrawAsPath) { // draw at the end canvas.drawPath(mPath, paint); } if (mStyles.drawBackground && firstX != -1) { // end / close path if (lastUsedEndY != graphHeight + graphTop) { // dont draw line to same point, otherwise the path is completely broken mPathBackground.lineTo((float) lastUsedEndX, graphHeight + graphTop); } mPathBackground.lineTo(firstX, graphHeight + graphTop); if (firstY != graphHeight + graphTop) { // dont draw line to same point, otherwise the path is completely broken mPathBackground.lineTo(firstX, firstY); } //mPathBackground.close(); canvas.drawPath(mPathBackground, mPaintBackground); } }