private void buildShadow() { if (mShadowSize <= 0) return; if (mShadowPaint == null) { mShadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG); mShadowPaint.setStyle(Paint.Style.FILL); mShadowPaint.setDither(true); } float startRatio = (float) mRadius / (mRadius + mShadowSize + mShadowOffset); mShadowPaint.setShader( new RadialGradient( 0, 0, mRadius + mShadowSize, new int[] {COLOR_SHADOW_START, COLOR_SHADOW_START, COLOR_SHADOW_END}, new float[] {0f, startRatio, 1f}, Shader.TileMode.CLAMP)); if (mShadowPath == null) { mShadowPath = new Path(); mShadowPath.setFillType(Path.FillType.EVEN_ODD); } else mShadowPath.reset(); float radius = mRadius + mShadowSize; mTempRect.set(-radius, -radius, radius, radius); mShadowPath.addOval(mTempRect, Path.Direction.CW); radius = mRadius - 1; mTempRect.set(-radius, -radius - mShadowOffset, radius, radius - mShadowOffset); mShadowPath.addOval(mTempRect, Path.Direction.CW); if (mGlowPaint == null) { mGlowPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG); mGlowPaint.setStyle(Paint.Style.FILL); mGlowPaint.setDither(true); } startRatio = (mRadius - mShadowSize / 2f) / (mRadius + mShadowSize / 2f); mGlowPaint.setShader( new RadialGradient( 0, 0, mRadius + mShadowSize / 2f, new int[] {COLOR_SHADOW_START, COLOR_SHADOW_START, COLOR_SHADOW_END}, new float[] {0f, startRatio, 1f}, Shader.TileMode.CLAMP)); if (mGlowPath == null) { mGlowPath = new Path(); mGlowPath.setFillType(Path.FillType.EVEN_ODD); } else mGlowPath.reset(); radius = mRadius + mShadowSize / 2f; mTempRect.set(-radius, -radius, radius, radius); mGlowPath.addOval(mTempRect, Path.Direction.CW); radius = mRadius - 1; mTempRect.set(-radius, -radius, radius, radius); mGlowPath.addOval(mTempRect, Path.Direction.CW); }
/** * Creates arrow icon that depends on ExpandDirection * * @param context context * @param width width of icon in pixels * @param height height of icon in pixels * @param color arrow color * @param expandDirection arrow direction * @return icon drawable */ private static Drawable createArrowIcon( Context context, int width, int height, int color, ExpandDirection expandDirection) { Bitmap canvasBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(canvasBitmap); Paint paint = new Paint(); paint.setStyle(Paint.Style.FILL_AND_STROKE); paint.setStrokeWidth(1); paint.setColor(color); paint.setAntiAlias(true); Path path = new Path(); path.setFillType(Path.FillType.EVEN_ODD); switch (expandDirection) { case UP: path.moveTo(0, (height / 3) * 2); path.lineTo(width, (height / 3) * 2); path.lineTo(width / 2, height / 3); path.lineTo(0, (height / 3) * 2); break; case DOWN: path.moveTo(0, height / 3); path.lineTo(width, height / 3); path.lineTo(width / 2, (height / 3) * 2); path.lineTo(0, height / 3); break; } path.close(); canvas.drawPath(path, paint); return new BitmapDrawable(context.getResources(), canvasBitmap); }
private void drawTriangle(Canvas c, float startAngle, float sweepAngle, Rect bounds) { if (mShowArrow) { if (mArrow == null) { mArrow = new Path(); mArrow.setFillType(Path.FillType.EVEN_ODD); } else { mArrow.reset(); } // Adjust the position of the triangle so that it is inset as // much as the arc, but also centered on the arc. float inset = (int) mStrokeInset / 2 * mArrowScale; float x = (float) (mRingCenterRadius * Math.cos(0) + bounds.exactCenterX()); float y = (float) (mRingCenterRadius * Math.sin(0) + bounds.exactCenterY()); // Update the path each time. This works around an issue in SKIA // where concatenating a rotation matrix to a scale matrix // ignored a starting negative rotation. This appears to have // been fixed as of API 21. mArrow.moveTo(0, 0); mArrow.lineTo(mArrowWidth * mArrowScale, 0); mArrow.lineTo((mArrowWidth * mArrowScale / 2), (mArrowHeight * mArrowScale)); mArrow.offset(x - inset, y); mArrow.close(); // draw a triangle mArrowPaint.setColor(mColors[mColorIndex]); c.rotate( startAngle + sweepAngle - ARROW_OFFSET_ANGLE, bounds.exactCenterX(), bounds.exactCenterY()); c.drawPath(mArrow, mArrowPaint); } }
private void buildShadowCorners() { Object obj = new RectF(-mCornerRadius, -mCornerRadius, mCornerRadius, mCornerRadius); Object obj1 = new RectF(((RectF) (obj))); ((RectF) (obj1)).inset(-mShadowSize, -mShadowSize); float f; float f1; float f2; float f3; int i; int j; int k; if (mCornerShadowPath == null) { mCornerShadowPath = new Path(); } else { mCornerShadowPath.reset(); } mCornerShadowPath.setFillType(android.graphics.Path.FillType.EVEN_ODD); mCornerShadowPath.moveTo(-mCornerRadius, 0.0F); mCornerShadowPath.rLineTo(-mShadowSize, 0.0F); mCornerShadowPath.arcTo(((RectF) (obj1)), 180F, 90F, false); mCornerShadowPath.arcTo(((RectF) (obj)), 270F, -90F, false); mCornerShadowPath.close(); f = mCornerRadius / (mCornerRadius + mShadowSize); obj = mCornerShadowPaint; f1 = mCornerRadius; f2 = mShadowSize; i = mShadowStartColor; j = mShadowStartColor; k = mShadowEndColor; obj1 = android.graphics.Shader.TileMode.CLAMP; ((Paint) (obj)) .setShader( new RadialGradient( 0.0F, 0.0F, f1 + f2, new int[] {i, j, k}, new float[] {0.0F, f, 1.0F}, ((android.graphics.Shader.TileMode) (obj1)))); obj = mEdgeShadowPaint; f = -mCornerRadius; f1 = mShadowSize; f2 = -mCornerRadius; f3 = mShadowSize; i = mShadowStartColor; j = mShadowStartColor; k = mShadowEndColor; obj1 = android.graphics.Shader.TileMode.CLAMP; ((Paint) (obj)) .setShader( new LinearGradient( 0.0F, f + f1, 0.0F, f2 - f3, new int[] {i, j, k}, new float[] {0.0F, 0.5F, 1.0F}, ((android.graphics.Shader.TileMode) (obj1)))); mEdgeShadowPaint.setAntiAlias(false); }
private void drawPolygon( BinaryMapDataObject obj, RenderingRuleSearchRequest render, Canvas canvas, RenderingContext rc, TagValuePair pair) { if (render == null || pair == null) { return; } float xText = 0; float yText = 0; int zoom = rc.zoom; Path path = null; // rc.main.color = Color.rgb(245, 245, 245); render.setInitialTagValueZoom(pair.tag, pair.value, zoom, obj); boolean rendered = render.search(RenderingRulesStorage.POLYGON_RULES); if (!rendered || !updatePaint(render, paint, 0, true, rc)) { return; } rc.visible++; int len = obj.getPointsLength(); for (int i = 0; i < obj.getPointsLength(); i++) { PointF p = calcPoint(obj, i, rc); xText += p.x; yText += p.y; if (path == null) { path = new Path(); path.moveTo(p.x, p.y); } else { path.lineTo(p.x, p.y); } } int[][] polygonInnerCoordinates = obj.getPolygonInnerCoordinates(); if (polygonInnerCoordinates != null && path != null) { path.setFillType(FillType.EVEN_ODD); for (int j = 0; j < polygonInnerCoordinates.length; j++) { for (int i = 0; i < polygonInnerCoordinates[j].length; i += 2) { PointF p = calcPoint(polygonInnerCoordinates[j][i], polygonInnerCoordinates[j][i + 1], rc); if (i == 0) { path.moveTo(p.x, p.y); } else { path.lineTo(p.x, p.y); } } } } if (path != null && len > 0) { canvas.drawPath(path, paint); if (updatePaint(render, paint, 1, false, rc)) { canvas.drawPath(path, paint); } textRenderer.renderText(obj, render, rc, pair, xText / len, yText / len, null, null); } }
private void updatePath() { if (bounds.isEmpty()) return; path = null; RectF outerRect = TiUIHelper.insetRect(boundsF, mPadding); if (radius != null) { path = new Path(); path.setFillType(FillType.EVEN_ODD); if (pathWidth > 0) { path.addRoundRect(outerRect, radius, Direction.CW); float padding = 0; float maxPadding = 0; RectF innerRect = new RectF(); maxPadding = Math.min(bounds.width() / 2, bounds.height() / 2); padding = Math.min(pathWidth, maxPadding); innerRect.set( outerRect.left + padding, outerRect.top + padding, outerRect.right - padding, outerRect.bottom - padding); path.addRoundRect(innerRect, innerRadiusFromPadding(outerRect, padding), Direction.CCW); } else { // adjustment not see background under border because of antialias path.addRoundRect(TiUIHelper.insetRect(outerRect, 0.3f), radius, Direction.CW); } } else { if (pathWidth > 0) { path = new Path(); path.setFillType(FillType.EVEN_ODD); path.addRect(outerRect, Direction.CW); int padding = 0; int maxPadding = 0; RectF innerRect = new RectF(); maxPadding = (int) Math.min(bounds.width() / 2, bounds.height() / 2); padding = (int) Math.min(pathWidth, maxPadding); innerRect.set( outerRect.left + padding, outerRect.top + padding, outerRect.right - padding, outerRect.bottom - padding); path.addRect(innerRect, Direction.CCW); } } }
private void drawArrow(Canvas c) { int height = getHeight(); int width = getWidth(); // Create a buffer around the arrow so when it rotates it doesn't get clipped by view edge final float BUFFER = width / 5; // Height of the cutout in the bottom of the triangle that makes it an arrow (0=triangle) final float CUTOUT_HEIGHT = getHeight() / 5; float x1, y1; // Tip of arrow x1 = width / 2; y1 = BUFFER; float x2, y2; // lower left x2 = BUFFER; y2 = height - BUFFER; float x3, y3; // cutout in arrow bottom x3 = width / 2; y3 = height - CUTOUT_HEIGHT - BUFFER; float x4, y4; // lower right x4 = width - BUFFER; y4 = height - BUFFER; Path path = new Path(); 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(); float direction = mHeading - mBearingToStop; // Make sure value is between 0-360 direction = MathUtils.mod(direction, 360.0f); // Rotate arrow around center point Matrix matrix = new Matrix(); matrix.postRotate((float) -direction, width / 2, height / 2); path.transform(matrix); c.drawPath(path, mArrowPaint); c.drawPath(path, mArrowFillPaint); // Update content description, so screen readers can announce direction to stop String[] spokenDirections = getResources().getStringArray(R.array.spoken_compass_directions); String directionName = spokenDirections[MathUtils.getHalfWindIndex(direction)]; setContentDescription(directionName); }
private void drawOvalBackground(Canvas canvas, Rect bitmapRect) { final float left = Edge.LEFT.getCoordinate(); final float top = Edge.TOP.getCoordinate(); final float right = Edge.RIGHT.getCoordinate(); final float bottom = Edge.BOTTOM.getCoordinate(); RectF r = new RectF(left, top, right, bottom); Path path = new Path(); path.addRect( bitmapRect.left, bitmapRect.top, bitmapRect.right, bitmapRect.bottom, Path.Direction.CW); path.addOval(r, Path.Direction.CCW); path.setFillType(Path.FillType.EVEN_ODD); canvas.drawPath(path, mBackgroundPaint); }
private Path convertAwtPathToAndroid(PathIterator pi) { Path path = new Path(); float[] coords = new float[6]; while (!pi.isDone()) { int windingRule = pi.getWindingRule(); if (windingRule == PathIterator.WIND_EVEN_ODD) { path.setFillType(Path.FillType.EVEN_ODD); } else { path.setFillType(Path.FillType.WINDING); } int pathType = pi.currentSegment(coords); switch (pathType) { case PathIterator.SEG_CLOSE: path.close(); break; case PathIterator.SEG_CUBICTO: path.cubicTo(coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]); break; case PathIterator.SEG_LINETO: path.lineTo(coords[0], coords[1]); break; case PathIterator.SEG_MOVETO: path.moveTo(coords[0], coords[1]); break; case PathIterator.SEG_QUADTO: path.quadTo(coords[0], coords[1], coords[2], coords[3]); break; } pi.next(); } return path; }
public void render(Collection<Triangle> triangles, Canvas canvas) { colorGenerator.setCount(triangles.size()); for (Triangle triangle : triangles) { Path path = new Path(); path.setFillType(Path.FillType.EVEN_ODD); path.moveTo(triangle.a.x, triangle.a.y); path.lineTo(triangle.b.x, triangle.b.y); path.lineTo(triangle.c.x, triangle.c.y); path.lineTo(triangle.a.x, triangle.a.y); path.close(); trianglePaint.setColor(colorGenerator.nextColor()); canvas.drawPath(path, trianglePaint); } }
@Override public void calculate( int bitmapWidth, int bitmapHeight, float width, float height, float scale, float translateX, float translateY) { path.reset(); float x = -translateX; float y = -translateY; float scaledTriangleHeight = triangleHeightPx / scale; float resultWidth = bitmapWidth + 2 * translateX; float resultHeight = bitmapHeight + 2 * translateY; float centerY = resultHeight / 2f + y; path.setFillType(Path.FillType.EVEN_ODD); float rectLeft; float rectRight; switch (arrowPosition) { case LEFT: rectLeft = scaledTriangleHeight + x; rectRight = resultWidth + rectLeft; path.addRect(rectLeft, y, rectRight, resultHeight + y, Path.Direction.CW); path.moveTo(x, centerY); path.lineTo(rectLeft, centerY - scaledTriangleHeight); path.lineTo(rectLeft, centerY + scaledTriangleHeight); path.lineTo(x, centerY); break; case RIGHT: rectLeft = x; float imgRight = resultWidth + rectLeft; rectRight = imgRight - scaledTriangleHeight; path.addRect(rectLeft, y, rectRight, resultHeight + y, Path.Direction.CW); path.moveTo(imgRight, centerY); path.lineTo(rectRight, centerY - scaledTriangleHeight); path.lineTo(rectRight, centerY + scaledTriangleHeight); path.lineTo(imgRight, centerY); break; } }
private void buildShadowCorners() { RectF innerBounds = new RectF(-mCornerRadius, -mCornerRadius, mCornerRadius, mCornerRadius); RectF outerBounds = new RectF(innerBounds); outerBounds.inset(-mShadowSize, -mShadowSize); if (mCornerShadowPath == null) { mCornerShadowPath = new Path(); } else { mCornerShadowPath.reset(); } mCornerShadowPath.setFillType(Path.FillType.EVEN_ODD); mCornerShadowPath.moveTo(-mCornerRadius, 0); mCornerShadowPath.rLineTo(-mShadowSize, 0); // outer arc mCornerShadowPath.arcTo(outerBounds, 180f, 90f, false); // inner arc mCornerShadowPath.arcTo(innerBounds, 270f, -90f, false); mCornerShadowPath.close(); float startRatio = mCornerRadius / (mCornerRadius + mShadowSize); mCornerShadowPaint.setShader( new RadialGradient( 0, 0, mCornerRadius + mShadowSize, new int[] {mShadowStartColor, mShadowStartColor, mShadowEndColor}, new float[] {0f, startRatio, 1f}, Shader.TileMode.CLAMP)); // we offset the content shadowSize/2 pixels up to make it more realistic. // this is why edge shadow shader has some extra space // When drawing bottom edge shadow, we use that extra space. mEdgeShadowPaint.setShader( new LinearGradient( 0, -mCornerRadius + mShadowSize, 0, -mCornerRadius - mShadowSize, new int[] {mShadowStartColor, mShadowStartColor, mShadowEndColor}, new float[] {0f, .5f, 1f}, Shader.TileMode.CLAMP)); }
public NMapCalloutBasicOverlay(NMapOverlay itemOverlay, NMapOverlayItem item, Rect itemBounds) { super(itemOverlay, item, itemBounds); mInnerPaint = new Paint(); mInnerPaint.setARGB(225, 75, 75, 75); // gray mInnerPaint.setAntiAlias(true); mBorderPaint = new Paint(); mBorderPaint.setARGB(255, 255, 255, 255); mBorderPaint.setAntiAlias(true); mBorderPaint.setStyle(Style.STROKE); mBorderPaint.setStrokeWidth(2); mTextPaint = new Paint(); mTextPaint.setARGB(255, 255, 255, 255); mTextPaint.setAntiAlias(true); mPath = new Path(); mPath.setFillType(Path.FillType.WINDING); }
protected void onDraw(Canvas canvas) { canvas.drawLine(8, height - 5, width - 8, height - 5, mPaintUnderline); // draw // underline // canvas.drawLine(8, height - 5, 8, height - 10, mPaintUnderline); // draw // left // corner Path path = new Path(); path.setFillType(Path.FillType.EVEN_ODD); path.moveTo(width - 7, height - 4); path.lineTo(width - 25, height - 4); path.lineTo(width - 7, height - 25); // path.lineTo(width - 8, height -5); path.close(); canvas.drawPath(path, mPaintTriangle); super.onDraw(canvas); }
public void draw(Canvas c) { changeState(); setBounds(xCoord - 50, yCoord - 20, xCoord + 50, yCoord + 20); Paint p = new Paint(); Path path = new Path(); path.setFillType(Path.FillType.EVEN_ODD); path.moveTo(xCoord - 50, yCoord); path.arcTo(new RectF(xCoord - 50, yCoord - 20, xCoord + 50, yCoord + 20), 180, 180); path.lineTo(xCoord, yCoord + 20); path.lineTo(xCoord - 50, yCoord); path.close(); p.setColor(Color.CYAN); p.setStyle(Paint.Style.FILL_AND_STROKE); c.drawPath(path, p); p.setColor(Color.BLACK); p.setStyle(Paint.Style.STROKE); c.drawPath(path, p); if (yCoord < 0) { setComplete(true); } }
/** * Creates a bus stop icon with the given direction arrow, or without a direction arrow if the * direction is NO_DIRECTION * * @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; }
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 移动时候的状态 if (VIEW_STATUS == VIEW_ACTIOMOVE_STATUS) { Log.i("CJT", "=========拖动状态========="); float length_temp = (float) Math.sqrt( ((Math.abs(moveX - centerX) * Math.abs(moveX - centerX)) + (Math.abs(moveY - centerY) * Math.abs(moveY - centerY)))); float radius_temp; // if (radius <= length_temp) { // radius_temp = (radius / length_temp) * radius; // } else { // radius_temp = radius/2; // } radius_temp = radius / 2 < (radius / length_temp) * radius ? radius / 2 : (radius / length_temp) * radius; canvas.drawCircle(centerX, centerY, radius_temp, mPaint); canvas.drawCircle(moveX, moveY, radius, mPaint); canvas.drawLine(centerX, centerY, moveX, moveY, mPaint); if (radius_temp / radius < 0.15) { Log.i("CJT", "半径比=" + radius_temp / radius); VIEW_STATUS = VIEW_BREAK_STATUS; } float x, y; y = ((Math.abs(centerX - moveX) / length_temp) * radius) + moveY; x = moveX - ((Math.abs(centerY - moveY) / length_temp) * radius); float lengthX = Math.abs(moveX - x); float lengthY = Math.abs(y - moveY); // if (moveX < centerX && moveY < centerY) { // canvas.drawLine(moveX - lengthX, moveY + lengthY, moveX + lengthX, moveY - // lengthY, mPaint); // } else if (moveX > centerX && moveY < centerY) { // canvas.drawLine(moveX - lengthX, moveY - lengthY, moveX + lengthX, moveY + // lengthY, mPaint); // } else if (moveX > centerX && moveY > centerY) { // canvas.drawLine(moveX - lengthX, moveY + lengthY, moveX + lengthX, moveY - // lengthY, mPaint); // } else if (moveX < centerX && moveY > centerY) { // canvas.drawLine(moveX - lengthX, moveY - lengthY, moveX + lengthX, moveY + // lengthY, mPaint); // } float sx, sy; sy = ((Math.abs(centerX - moveX) / length_temp) * radius_temp) + centerY; sx = centerX - ((Math.abs(centerY - moveY) / length_temp) * radius_temp); float lengthsX = Math.abs(centerX - sx); float lengthsY = Math.abs(sy - centerY); if (moveX < centerX && moveY < centerY) { canvas.drawLine(moveX - lengthX, moveY + lengthY, moveX + lengthX, moveY - lengthY, mPaint); canvas.drawLine( centerX - lengthsX, centerY + lengthsY, centerX + lengthsX, centerY - lengthsY, mPaint); } else if (moveX > centerX && moveY < centerY) { canvas.drawLine(moveX - lengthX, moveY - lengthY, moveX + lengthX, moveY + lengthY, mPaint); canvas.drawLine( centerX - lengthsX, centerY - lengthsY, centerX + lengthsX, centerY + lengthsY, mPaint); } else if (moveX > centerX && moveY > centerY) { canvas.drawLine(moveX - lengthX, moveY + lengthY, moveX + lengthX, moveY - lengthY, mPaint); canvas.drawLine( centerX - lengthsX, centerY + lengthsY, centerX + lengthsX, centerY - lengthsY, mPaint); } else if (moveX < centerX && moveY > centerY) { canvas.drawLine(moveX - lengthX, moveY - lengthY, moveX + lengthX, moveY + lengthY, mPaint); canvas.drawLine( centerX - lengthsX, centerY - lengthsY, centerX + lengthsX, centerY + lengthsY, mPaint); } if (moveX < centerX && moveY < centerY) { // canvas.drawLine(moveX - lengthX, moveY + lengthY, centerX - lengthsX, // centerY + lengthsY, mPaint); // canvas.drawLine(moveX + lengthX, moveY - lengthY, centerX + lengthsX, // centerY - lengthsY, mPaint); mPath.reset(); mPath.moveTo(moveX - lengthX, moveY + lengthY); mPath.quadTo( (moveX + centerX) / 2, (moveY + centerY) / 2, centerX - lengthsX, centerY + lengthsY); mPath.lineTo(centerX + lengthsX, centerY - lengthsY); mPath.quadTo( (moveX + centerX) / 2, (moveY + centerY) / 2, moveX + lengthX, moveY - lengthY); mPath.lineTo(moveX - lengthX, moveY + lengthY); mPath.close(); mPath.setFillType(Path.FillType.WINDING); // mPaint.setStyle(Paint.Style.FILL); canvas.drawPath(mPath, mPaint); // mPaint.setStyle(Paint.Style.STROKE); } else if (moveX > centerX && moveY < centerY) { // canvas.drawLine(moveX - lengthX, moveY - lengthY, centerX - lengthsX, // centerY - lengthsY, mPaint); // canvas.drawLine(moveX + lengthX, moveY + lengthY, centerX + lengthsX, // centerY + lengthsY, mPaint); mPath.reset(); mPath.moveTo(moveX - lengthX, moveY - lengthY); mPath.quadTo( (moveX + centerX) / 2, (moveY + centerY) / 2, centerX - lengthsX, centerY - lengthsY); mPath.lineTo(centerX + lengthsX, centerY + lengthsY); mPath.quadTo( (moveX + centerX) / 2, (moveY + centerY) / 2, moveX + lengthX, moveY + lengthY); mPath.lineTo(moveX - lengthX, moveY - lengthY); canvas.drawPath(mPath, mPaint); } else if (moveX > centerX && moveY > centerY) { // canvas.drawLine(moveX - lengthX, moveY + lengthY, centerX - lengthsX, // centerY + lengthsY, mPaint); // canvas.drawLine(moveX + lengthX, moveY - lengthY, centerX + lengthsX, // centerY - lengthsY, mPaint); mPath.reset(); mPath.moveTo(moveX - lengthX, moveY + lengthY); mPath.quadTo( (moveX + centerX) / 2, (moveY + centerY) / 2, centerX - lengthsX, centerY + lengthsY); mPath.lineTo(centerX + lengthsX, centerY - lengthsY); mPath.quadTo( (moveX + centerX) / 2, (moveY + centerY) / 2, moveX + lengthX, moveY - lengthY); mPath.lineTo(moveX - lengthX, moveY + lengthY); canvas.drawPath(mPath, mPaint); } else if (moveX < centerX && moveY > centerY) { // canvas.drawLine(moveX - lengthX, moveY - lengthY, centerX - lengthsX, // centerY - lengthsY, mPaint); // canvas.drawLine(moveX + lengthX, moveY + lengthY, centerX + lengthsX, // centerY + lengthsY, mPaint); mPath.reset(); mPath.moveTo(moveX - lengthX, moveY - lengthY); mPath.quadTo( (moveX + centerX) / 2, (moveY + centerY) / 2, centerX - lengthsX, centerY - lengthsY); mPath.lineTo(centerX + lengthsX, centerY + lengthsY); mPath.quadTo( (moveX + centerX) / 2, (moveY + centerY) / 2, moveX + lengthX, moveY + lengthY); mPath.lineTo(moveX - lengthX, moveY - lengthY); canvas.drawPath(mPath, mPaint); } // canvas.drawText("99+", moveX, moveY, textPaint); } else if (VIEW_STATUS == VIEW_BREAK_STATUS) { // 断开时候的状态 Log.i("CJT", "=========断开状态========="); canvas.drawCircle(moveX, moveY, radius, mPaint); } else if (VIEW_STATUS == VIEW_ACTION_STATUS) { // 初始状态 Log.i("CJT", "=========初始状态========="); canvas.drawCircle(centerX, centerY, radius, mPaint); // canvas.drawText("99+", centerX, centerY, textPaint); } }
private Intent createShortcutIntent(int position) { String url = getUrl(position); String title = getBookmarkTitle(position); Bitmap touchIcon = getTouchIcon(position); final Intent i = new Intent(); final Intent shortcutIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); long urlHash = url.hashCode(); long uniqueId = (urlHash << 32) | shortcutIntent.hashCode(); shortcutIntent.putExtra(Browser.EXTRA_APPLICATION_ID, Long.toString(uniqueId)); i.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent); i.putExtra(Intent.EXTRA_SHORTCUT_NAME, title); // Use the apple-touch-icon if available if (touchIcon != null) { // Make a copy so we can modify the pixels. We can't use // createScaledBitmap or copy since they will preserve the config // and lose the ability to add alpha. Bitmap bm = Bitmap.createBitmap(mIconSize, mIconSize, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bm); Rect src = new Rect(0, 0, touchIcon.getWidth(), touchIcon.getHeight()); Rect dest = new Rect(0, 0, bm.getWidth(), bm.getHeight()); // Paint used for scaling the bitmap and drawing the rounded rect. Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setFilterBitmap(true); canvas.drawBitmap(touchIcon, src, dest, paint); // Construct a path from a round rect. This will allow drawing with // an inverse fill so we can punch a hole using the round rect. Path path = new Path(); path.setFillType(Path.FillType.INVERSE_WINDING); RectF rect = new RectF(0, 0, bm.getWidth(), bm.getHeight()); rect.inset(1, 1); path.addRoundRect(rect, 8f, 8f, Path.Direction.CW); // Reuse the paint and clear the outside of the rectangle. paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); canvas.drawPath(path, paint); i.putExtra(Intent.EXTRA_SHORTCUT_ICON, bm); } else { Bitmap favicon = getFavicon(position); if (favicon == null) { i.putExtra( Intent.EXTRA_SHORTCUT_ICON_RESOURCE, Intent.ShortcutIconResource.fromContext( BrowserBookmarksPage.this, R.drawable.ic_launcher_shortcut_browser_bookmark)); } else { Bitmap icon = BitmapFactory.decodeResource( getResources(), R.drawable.ic_launcher_shortcut_browser_bookmark_icon); // Make a copy of the regular icon so we can modify the pixels. Bitmap copy = icon.copy(Bitmap.Config.ARGB_8888, true); Canvas canvas = new Canvas(copy); // Make a Paint for the white background rectangle and for // filtering the favicon. Paint p = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); p.setStyle(Paint.Style.FILL_AND_STROKE); p.setColor(Color.WHITE); final float density = getResources().getDisplayMetrics().density; // Create a rectangle that is slightly wider than the favicon final float iconSize = 16 * density; // 16x16 favicon final float padding = 2 * density; // white padding around icon final float rectSize = iconSize + 2 * padding; final Rect iconBounds = new Rect(0, 0, icon.getWidth(), icon.getHeight()); final float x = iconBounds.exactCenterX() - (rectSize / 2); // Note: Subtract 2 dip from the y position since the box is // slightly higher than center. Use padding since it is already // 2 * density. final float y = iconBounds.exactCenterY() - (rectSize / 2) - padding; RectF r = new RectF(x, y, x + rectSize, y + rectSize); // Draw a white rounded rectangle behind the favicon canvas.drawRoundRect(r, 2, 2, p); // Draw the favicon in the same rectangle as the rounded // rectangle but inset by the padding // (results in a 16x16 favicon). r.inset(padding, padding); canvas.drawBitmap(favicon, null, r, p); i.putExtra(Intent.EXTRA_SHORTCUT_ICON, copy); } } // Do not allow duplicate items i.putExtra("duplicate", false); return i; }