Java Code Examples for android.graphics.PathMeasure#getPosTan()
The following examples show how to use
android.graphics.PathMeasure#getPosTan() .
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: WeatherTemplateView.java From MaterialCalendar with Apache License 2.0 | 6 votes |
protected PathPoints[] getPoints(Path path, int size) { //Size of 100 indicates that, 100 points // would be extracted from the path PathPoints[] pointArray = new PathPoints[size]; PathMeasure pm = new PathMeasure(path, false); float length = pm.getLength(); float distance = 0f; float speed = length / size; int counter = 0; float[] aCoordinates = new float[2]; while ((distance < length) && (counter < size)) { pm.getPosTan(distance, aCoordinates, null); pointArray[counter] = new PathPoints(aCoordinates[0], aCoordinates[1]); counter++; distance = distance + speed; } return pointArray; }
Example 2
Source File: Foam.java From Android-Plugin-Framework with MIT License | 6 votes |
public void matchVertsToPath(Path path, float extraOffset) { PathMeasure pm = new PathMeasure(path, false); int index = 0; for (int i = 0; i < staticVerts.length / 2; i++) { float yIndexValue = staticVerts[i * 2 + 1]; float xIndexValue = staticVerts[i * 2]; float percentOffsetX = (0.000001f + xIndexValue) / bitmap.getWidth(); float percentOffsetX2 = (0.000001f + xIndexValue) / (bitmap.getWidth() + extraOffset); percentOffsetX2 += pathOffsetPercent; pm.getPosTan(pm.getLength() * (1f - percentOffsetX), coords, null); pm.getPosTan(pm.getLength() * (1f - percentOffsetX2), coords2, null); if (yIndexValue == 0) { setXY(drawingVerts, i, coords[0], coords2[1] + verticalOffset); } else { float desiredYCoord = Math.max(coords2[1], coords2[1] + easedFoamCoords[Math.min(easedFoamCoords.length - 1, index)]); setXY(drawingVerts, i, coords[0], desiredYCoord + verticalOffset); index += 1; } } }
Example 3
Source File: BrokenAnimator.java From BrokenView with MIT License | 6 votes |
/** * Make sure it can be seen in "FILL" mode */ private void warpStraightLines() { PathMeasure pmTemp = new PathMeasure(); for (int i = 0; i < mConfig.complexity; i++) { if(lineRifts[i].isStraight()) { pmTemp.setPath(lineRifts[i], false); lineRifts[i].setStartLength(pmTemp.getLength() / 2); float[] pos = new float[2]; pmTemp.getPosTan(pmTemp.getLength() / 2, pos, null); int xRandom = (int) (pos[0] + Utils.nextInt(-Utils.dp2px(1), Utils.dp2px(1))); int yRandom = (int) (pos[1] + Utils.nextInt(-Utils.dp2px(1), Utils.dp2px(1))); lineRifts[i].reset(); lineRifts[i].moveTo(0,0); lineRifts[i].lineTo(xRandom,yRandom); lineRifts[i].lineToEnd(); } } }
Example 4
Source File: FilterMenuLayout.java From FilterMenu with Apache License 2.0 | 6 votes |
/** * calculate and set position to menu items */ private void calculateMenuItemPosition() { float itemRadius = (expandedRadius + collapsedRadius) / 2, f; RectF area = new RectF( center.x - itemRadius, center.y - itemRadius, center.x + itemRadius, center.y + itemRadius); Path path = new Path(); path.addArc(area, (float) fromAngle, (float) (toAngle - fromAngle)); PathMeasure measure = new PathMeasure(path, false); float len = measure.getLength(); int divisor = getChildCount(); float divider = len / divisor; for (int i = 0; i < getChildCount(); i++) { float[] coords = new float[2]; measure.getPosTan(i * divider + divider * .5f, coords, null); FilterMenu.Item item = (FilterMenu.Item) getChildAt(i).getTag(); item.setX((int) coords[0] - item.getView().getMeasuredWidth() / 2); item.setY((int) coords[1] - item.getView().getMeasuredHeight() / 2); } }
Example 5
Source File: PathInterpolatorDonut.java From RxTools-master with Apache License 2.0 | 6 votes |
public PathInterpolatorDonut(Path path) { final PathMeasure pathMeasure = new PathMeasure(path, false /* forceClosed */); final float pathLength = pathMeasure.getLength(); final int numPoints = (int) (pathLength / PRECISION) + 1; mX = new float[numPoints]; mY = new float[numPoints]; final float[] position = new float[2]; for (int i = 0; i < numPoints; ++i) { final float distance = (i * pathLength) / (numPoints - 1); pathMeasure.getPosTan(distance, position, null /* tangent */); mX[i] = position[0]; mY[i] = position[1]; } }
Example 6
Source File: PathBitmapMesh.java From Depth with MIT License | 6 votes |
public void matchVertsToPath(Path path, float bottomCoord, float extraOffset) { PathMeasure pm = new PathMeasure(path, false); for (int i = 0; i < staticVerts.length / 2; i++) { float yIndexValue = staticVerts[i * 2 + 1]; float xIndexValue = staticVerts[i * 2]; float percentOffsetX = (0.000001f + xIndexValue) / bitmap.getWidth(); float percentOffsetX2 = (0.000001f + xIndexValue) / (bitmap.getWidth() + extraOffset); percentOffsetX2 += pathOffsetPercent; pm.getPosTan(pm.getLength() * (1f - percentOffsetX), coords, null); pm.getPosTan(pm.getLength() * (1f - percentOffsetX2), coords2, null); if (yIndexValue == 0) { setXY(drawingVerts, i, coords[0], coords2[1]); } else { float desiredYCoord = bottomCoord; setXY(drawingVerts, i, coords[0], desiredYCoord); } } }
Example 7
Source File: Foam.java From Depth with MIT License | 6 votes |
public void matchVertsToPath(Path path, float extraOffset) { PathMeasure pm = new PathMeasure(path, false); int index = 0; for (int i = 0; i < staticVerts.length / 2; i++) { float yIndexValue = staticVerts[i * 2 + 1]; float xIndexValue = staticVerts[i * 2]; float percentOffsetX = (0.000001f + xIndexValue) / bitmap.getWidth(); float percentOffsetX2 = (0.000001f + xIndexValue) / (bitmap.getWidth() + extraOffset); percentOffsetX2 += pathOffsetPercent; pm.getPosTan(pm.getLength() * (1f - percentOffsetX), coords, null); pm.getPosTan(pm.getLength() * (1f - percentOffsetX2), coords2, null); if (yIndexValue == 0) { setXY(drawingVerts, i, coords[0], coords2[1] + verticalOffset); } else { float desiredYCoord = Math.max(coords2[1], coords2[1] + easedFoamCoords[Math.min(easedFoamCoords.length - 1, index)]); setXY(drawingVerts, i, coords[0], desiredYCoord + verticalOffset); index += 1; } } }
Example 8
Source File: Foam.java From Depth with MIT License | 6 votes |
public void matchVertsToPath(Path path, float extraOffset) { PathMeasure pm = new PathMeasure(path, false); int index = 0; for (int i = 0; i < staticVerts.length / 2; i++) { float yIndexValue = staticVerts[i * 2 + 1]; float xIndexValue = staticVerts[i * 2]; float percentOffsetX = (0.000001f + xIndexValue) / bitmap.getWidth(); float percentOffsetX2 = (0.000001f + xIndexValue) / (bitmap.getWidth() + extraOffset); percentOffsetX2 += pathOffsetPercent; pm.getPosTan(pm.getLength() * (1f - percentOffsetX), coords, null); pm.getPosTan(pm.getLength() * (1f - percentOffsetX2), coords2, null); if (yIndexValue == 0) { setXY(drawingVerts, i, coords[0], coords2[1] + verticalOffset); } else { float desiredYCoord = Math.max(coords2[1], coords2[1] + easedFoamCoords[Math.min(easedFoamCoords.length - 1, index)]); setXY(drawingVerts, i, coords[0], desiredYCoord + verticalOffset); index += 1; } } }
Example 9
Source File: PathKeyframeAnimation.java From atlas with Apache License 2.0 | 6 votes |
@Override public PointF getValue(Keyframe<PointF> keyframe, float keyframeProgress) { PathKeyframe pathKeyframe = (PathKeyframe) keyframe; Path path = pathKeyframe.getPath(); if (path == null) { return keyframe.startValue; } if (pathMeasureKeyframe != pathKeyframe) { pathMeasure = new PathMeasure(path, false); pathMeasureKeyframe = pathKeyframe; } pathMeasure.getPosTan(keyframeProgress * pathMeasure.getLength(), pos, null); point.set(pos[0], pos[1]); return point; }
Example 10
Source File: PathInterpolatorCompat.java From android-dialer with Apache License 2.0 | 6 votes |
public PathInterpolatorBase(Path path) { final PathMeasure pathMeasure = new PathMeasure(path, false /* forceClosed */); final float pathLength = pathMeasure.getLength(); final int numPoints = (int) (pathLength / PRECISION) + 1; mX = new float[numPoints]; mY = new float[numPoints]; final float[] position = new float[2]; for (int i = 0; i < numPoints; ++i) { final float distance = (i * pathLength) / (numPoints - 1); pathMeasure.getPosTan(distance, position, null /* tangent */); mX[i] = position[0]; mY[i] = position[1]; } }
Example 11
Source File: ScaleView.java From ScaleView with Apache License 2.0 | 6 votes |
/** * 画指示器 * * @param canvas */ private void drawIndicator(Canvas canvas) { PathMeasure mPathMeasure = new PathMeasure(); mPathMeasure.setPath(mArcPath, false); float[] tan = new float[2]; float[] pos = new float[2]; mPathMeasure.getPosTan(mPathMeasure.getLength() * (0.5f), pos, tan); canvas.save(); double angle = calcArcAngle(Math.atan2(tan[1], tan[0])) + 90; canvas.rotate((float) angle, pos[0], pos[1]); //画直线 canvas.drawLine(pos[0], pos[1], pos[0] + 80, pos[1], mIndicatorPaint); Path linePath = new Path(); //画箭头 linePath.moveTo(pos[0] + 80, pos[1] - 20); linePath.lineTo(pos[0] + 80 + 20, pos[1]); linePath.lineTo(pos[0] + 80, pos[1] + 20); canvas.drawPath(linePath, mIndicatorPaint); canvas.restore(); }
Example 12
Source File: ArcNavigationView.java From ArcNavigationView with Apache License 2.0 | 5 votes |
@SuppressWarnings("unused") @SuppressLint("RtlHardcoded") private void adjustChildViews(ViewGroup container) { final int containerChildCount = container.getChildCount(); PathMeasure pathMeasure = new PathMeasure(arcPath, false); DrawerLayout.LayoutParams layoutParams = (DrawerLayout.LayoutParams) getLayoutParams(); for (int i = 0; i < containerChildCount; i++) { View child = container.getChildAt(i); if (child instanceof ViewGroup) { adjustChildViews((ViewGroup) child); } else { float[] pathCenterPointForItem = {0f, 0f}; Rect location = locateView(child); int halfHeight = location.height() / 2; pathMeasure.getPosTan(location.top + halfHeight, pathCenterPointForItem, null); if (layoutParams.gravity == Gravity.END || layoutParams.gravity == Gravity.RIGHT) { int centerPathPoint = getMeasuredWidth() - Math.round(pathCenterPointForItem[0]); if (child.getMeasuredWidth() > centerPathPoint) { child.measure(MeasureSpec.makeMeasureSpec(centerPathPoint - THRESHOLD, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec( child.getMeasuredHeight(), MeasureSpec.EXACTLY)); child.layout(centerPathPoint + THRESHOLD, child.getTop(), child.getRight(), child.getBottom()); } } else if (layoutParams.gravity == Gravity.START || layoutParams.gravity == Gravity.LEFT) { if (child.getMeasuredWidth() > pathCenterPointForItem[0]) { child.measure(MeasureSpec.makeMeasureSpec((Math.round(pathCenterPointForItem[0]) - THRESHOLD), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec( child.getMeasuredHeight(), MeasureSpec.EXACTLY)); child.layout(child.getLeft(), child.getTop(), (Math.round(pathCenterPointForItem[0]) - THRESHOLD), child.getBottom()); } } //set text ellipsize to end to prevent it from overlapping edge if (child instanceof TextView) { ((TextView) child).setEllipsize(TextUtils.TruncateAt.END); } } } }
Example 13
Source File: ObjectAnimatorCompatBase.java From MaterialProgressBar with Apache License 2.0 | 5 votes |
private static void calculateXYValues(@NonNull Path path, @NonNull @Size(NUM_POINTS) int[] xValues, @NonNull @Size(NUM_POINTS) int[] yValues) { PathMeasure pathMeasure = new PathMeasure(path, false /* forceClosed */); float pathLength = pathMeasure.getLength(); float[] position = new float[2]; for (int i = 0; i < NUM_POINTS; ++i) { float distance = (i * pathLength) / (NUM_POINTS - 1); pathMeasure.getPosTan(distance, position, null /* tangent */); xValues[i] = Math.round(position[0]); yValues[i] = Math.round(position[1]); } }
Example 14
Source File: PatternPathMotion.java From android_9.0.0_r45 with Apache License 2.0 | 5 votes |
/** * Sets the Path defining a pattern of motion between two coordinates. * The pattern will be translated, rotated, and scaled to fit between the start and end points. * The pattern must not be empty and must have the end point differ from the start point. * * @param patternPath A Path to be used as a pattern for two-dimensional motion. * @attr ref android.R.styleable#PatternPathMotion_patternPathData */ public void setPatternPath(Path patternPath) { PathMeasure pathMeasure = new PathMeasure(patternPath, false); float length = pathMeasure.getLength(); float[] pos = new float[2]; pathMeasure.getPosTan(length, pos, null); float endX = pos[0]; float endY = pos[1]; pathMeasure.getPosTan(0, pos, null); float startX = pos[0]; float startY = pos[1]; if (startX == endX && startY == endY) { throw new IllegalArgumentException("pattern must not end at the starting point"); } mTempMatrix.setTranslate(-startX, -startY); float dx = endX - startX; float dy = endY - startY; float distance = (float) Math.hypot(dx, dy); float scale = 1 / distance; mTempMatrix.postScale(scale, scale); double angle = Math.atan2(dy, dx); mTempMatrix.postRotate((float) Math.toDegrees(-angle)); patternPath.transform(mTempMatrix, mPatternPath); mOriginalPatternPath = patternPath; }
Example 15
Source File: GestureDescription.java From android_9.0.0_r45 with Apache License 2.0 | 5 votes |
/** * @param path The path to follow. Must have exactly one contour. The bounds of the path * must not be negative. The path must not be empty. If the path has zero length * (for example, a single {@code moveTo()}), the stroke is a touch that doesn't move. * @param startTime The time, in milliseconds, from the time the gesture starts to the * time the stroke should start. Must not be negative. * @param duration The duration, in milliseconds, the stroke takes to traverse the path. * Must be positive. * @param willContinue {@code true} if this stroke will be continued by one in the * next gesture {@code false} otherwise. Continued strokes keep their pointers down when * the gesture completes. */ public StrokeDescription(@NonNull Path path, @IntRange(from = 0) long startTime, @IntRange(from = 0) long duration, boolean willContinue) { mContinued = willContinue; Preconditions.checkArgument(duration > 0, "Duration must be positive"); Preconditions.checkArgument(startTime >= 0, "Start time must not be negative"); Preconditions.checkArgument(!path.isEmpty(), "Path is empty"); RectF bounds = new RectF(); path.computeBounds(bounds, false /* unused */); Preconditions.checkArgument((bounds.bottom >= 0) && (bounds.top >= 0) && (bounds.right >= 0) && (bounds.left >= 0), "Path bounds must not be negative"); mPath = new Path(path); mPathMeasure = new PathMeasure(path, false); if (mPathMeasure.getLength() == 0) { // Treat zero-length paths as taps Path tempPath = new Path(path); tempPath.lineTo(-1, -1); mTapLocation = new float[2]; PathMeasure pathMeasure = new PathMeasure(tempPath, false); pathMeasure.getPosTan(0, mTapLocation, null); } if (mPathMeasure.nextContour()) { throw new IllegalArgumentException("Path has more than one contour"); } /* * Calling nextContour has moved mPathMeasure off the first contour, which is the only * one we care about. Set the path again to go back to the first contour. */ mPathMeasure.setPath(mPath, false); mStartTime = startTime; mEndTime = startTime + duration; mTimeToLengthConversion = getLength() / duration; mId = sIdCounter++; }
Example 16
Source File: ScaleView.java From ScaleView with Apache License 2.0 | 4 votes |
/** * 画刻度线和刻度 * * @param canvas */ private void drawScale(Canvas canvas) { PathMeasure mPathMeasure = new PathMeasure(); mPathMeasure.setPath(mArcPath, false); float[] pos = new float[2]; float[] tan = new float[2]; for (int i = 1; i <= mScaleNumber; i++) { float percentage = i / (float) mScaleNumber;//所占百分比 mPathMeasure.getPosTan(mPathMeasure.getLength() * percentage, pos, tan); double atan2 = Math.atan2(tan[1], tan[0]); double angle = calcArcAngle(atan2) + 90;//刻度线垂直切线,所以旋转90° int scale = Math.round(currentAngle + mScaleMin + i * mScaleSpace); if (scale >= mScaleMin && scale % mDrawLineSpace == 0) { float startX = pos[0]; float startY = pos[1]; float endX = 0; float endY = pos[1]; if (scale % mDrawTextSpace == 0) { endX = pos[0] + 80; mScaleLinePaint.setStrokeWidth(15); mScaleLinePaint.setColor(mScaleLineColor); if (currentAngle >= (-(mScaleNumber / 2) * mScaleSpace)) { canvas.save(); canvas.rotate((float) (angle + 90), pos[0], pos[1]); String mScaleText = scale + mScaleUnit; float scaleTextLength = mScaleTextPaint.measureText(mScaleText, 0, mScaleText.length()); canvas.drawText(mScaleText, pos[0] - scaleTextLength / 2, pos[1] - 130, mScaleTextPaint); canvas.restore(); } } else if (scale % mDrawLineSpace == 0) { mScaleLinePaint.setColor(mScaleTextColor); mScaleLinePaint.setStrokeWidth(10); endX = pos[0] + 50; } canvas.save(); canvas.rotate((float) angle, pos[0], pos[1]); canvas.drawLine(startX, startY, endX, endY, mScaleLinePaint); canvas.restore(); } } }
Example 17
Source File: GISDisplay.java From android_maplib with GNU Lesser General Public License v3.0 | 4 votes |
public void drawTextOnPath( String text, Path path, float hOffset, float vOffset, Paint paint) { if (null == mMainCanvas) { return; } PathMeasure pm = new PathMeasure(path, false); Matrix matrix = new Matrix(); Path charPath = new Path(); Path textPath = new Path(); float pathLength = pm.getLength(); float coordinates[] = new float[2]; float tangent[] = new float[2]; int i = 0; float position = hOffset; while (i < text.length()) { String ch = text.substring(i, i + 1); float charWidth = paint.measureText(ch); float nextPosition = position + charWidth; if (nextPosition > pathLength) { break; } pm.getPosTan(position + charWidth / 2, coordinates, tangent); float rotateAngle = (float) Math.toDegrees( Math.atan2((double) tangent[1], (double) tangent[0])); charPath.reset(); paint.getTextPath(ch, 0, ch.length(), -charWidth / 2, vOffset, charPath); charPath.close(); // workaround matrix.reset(); matrix.postScale(1, -1, 0, 0); matrix.postRotate(rotateAngle, 0, 0); matrix.postTranslate(coordinates[0], coordinates[1]); textPath.addPath(charPath, matrix); ++i; position = nextPosition; } mMainCanvas.drawPath(textPath, paint); // for debug //mMainCanvas.drawTextOnPath(text, path, hOffset, vOffset, paint); }
Example 18
Source File: BrokenAnimator.java From BrokenView with MIT License | 4 votes |
/** * Build warped-lines according to the baselines, like the DiscretePathEffect. */ private void buildBrokenLines(Rect r) { LinePath[] baseLines = new LinePath[mConfig.complexity]; buildBaselines(baseLines, r); PathMeasure pmTemp = new PathMeasure(); for (int i = 0; i < mConfig.complexity; i++) { lineRifts[i] = new LinePath(); lineRifts[i].moveTo(0, 0); lineRifts[i].setEndPoint(baseLines[i].getEndPoint()); pmTemp.setPath(baseLines[i], false); float length = pmTemp.getLength(); final int THRESHOLD = SEGMENT + SEGMENT / 2; if (length > Utils.dp2px(THRESHOLD)) { lineRifts[i].setStraight(false); // First, line to the point at SEGMENT of baseline; // Second, line to the random-point at (SEGMENT+SEGMENT/2) of baseline; // So when we set the start-draw-length to SEGMENT and the paint style is "FILL", // we can make the line become visible faster(exactly, the triangle) float[] pos = new float[2]; pmTemp.getPosTan(Utils.dp2px(SEGMENT), pos, null); lineRifts[i].lineTo(pos[0], pos[1]); lineRifts[i].points.add(new Point((int)pos[0], (int)pos[1])); int xRandom, yRandom; int step = Utils.dp2px(THRESHOLD); do{ pmTemp.getPosTan(step, pos, null); // !!! // Here determine the stroke width of lineRifts xRandom = (int) (pos[0] + Utils.nextInt(-Utils.dp2px(3),Utils.dp2px(2))); yRandom = (int) (pos[1] + Utils.nextInt(-Utils.dp2px(2),Utils.dp2px(3))); lineRifts[i].lineTo(xRandom, yRandom); lineRifts[i].points.add(new Point(xRandom, yRandom)); step += Utils.dp2px(SEGMENT); } while (step < length); lineRifts[i].lineToEnd(); } else { // Too short, it's still a beeline, so we must warp it later {@warpStraightLines()}, // to make sure it is visible in "FILL" mode. lineRifts[i] = baseLines[i]; lineRifts[i].setStraight(true); } lineRifts[i].points.add(lineRifts[i].getEndPoint()); } }
Example 19
Source File: Keyframes.java From PathLayoutManager with Apache License 2.0 | 4 votes |
private void initPath(Path path) { if (path == null || path.isEmpty()) { throw new NullPointerException("path is empty!"); } final PathMeasure pathMeasure = new PathMeasure(path, false); mX = new float[0]; mY = new float[0]; mAngle = new float[0]; do { final float pathLength = pathMeasure.getLength(); final int numPoints = (int) (pathLength / PRECISION) + 1; final float[] x = new float[numPoints]; final float[] y = new float[numPoints]; final float[] angle = new float[numPoints]; final float[] position = new float[2]; final float[] tangent = new float[2]; for (int i = 0; i < numPoints; ++i) { final float distance = (i * pathLength) / (numPoints - 1); pathMeasure.getPosTan(distance, position, tangent); if (position[0] > mMaxX) { mMaxX = position[0]; } if (position[1] > mMaxY) { mMaxY = position[1]; } x[i] = position[0]; y[i] = position[1]; angle[i] = fixAngle((float) (Math.atan2(tangent[1], tangent[0]) * 180F / Math.PI)); } mNumPoints += numPoints; float[] tmpX = new float[mX.length + x.length]; System.arraycopy(mX, 0, tmpX, 0, mX.length); System.arraycopy(x, 0, tmpX, mX.length, x.length); mX = tmpX; float[] tmpY = new float[mY.length + y.length]; System.arraycopy(mY, 0, tmpY, 0, mY.length); System.arraycopy(y, 0, tmpY, mY.length, y.length); mY = tmpY; float[] tmpAngle = new float[mAngle.length + angle.length]; System.arraycopy(mAngle, 0, tmpAngle, 0, mAngle.length); System.arraycopy(angle, 0, tmpAngle, mAngle.length, angle.length); mAngle = tmpAngle; } while (pathMeasure.nextContour()); }
Example 20
Source File: Animator.java From LineAnimation with MIT License | 4 votes |
@Override protected void onDraw(Canvas canvas){ super.onDraw(canvas); paint.setColor(pathColor); paint.setStrokeWidth(pathStrokeWidth); OnPathListener opl = (OnPathListener) context; line = opl.setOnPathUpdateListener(arrowX, arrowY); PathMeasure pm = new PathMeasure(line, false); float aCoordinates[] = {0f, 0f}; float aTan[] = {0f, 0f}; //if(coordinates == null){ coordinates = new ArrayList<>(); coordinatesTan = new ArrayList<>(); for(int x = (int) pm.getLength(); x > 0; x--){ pm.getPosTan(x, aCoordinates, aTan); Coordinates c = new Coordinates(); c.setX((int) aCoordinates[0]); c.setY((int) aCoordinates[1]); coordinates.add(c); Coordinates c2 = new Coordinates(); c2.setXf(aTan[0]); c2.setYf(aTan[1]); coordinatesTan.add(c2); } //} canvas.drawPath(line, paint); motionBitmap(); matrix.reset(); float degrees = (float) (Math.atan2(arrowXTan, arrowYTan) * -180.0 / Math.PI); matrix.postRotate(degrees, arrow.getWidth() / 2, arrow.getHeight() / 2); matrix.postTranslate(arrowX - (arrow.getWidth() / 2), arrowY - (arrow.getHeight() / 2)); canvas.drawBitmap(arrow, matrix, null); if(animateArrow){ invalidate(); } }