Android中如何在Canvas上绘制Squircle(圆角方形)图形
Got it! Let's convert your circle-drawing logic to render a squircle instead—this shape sits neatly between a square and circle, with smooth, rounded corners that don't have the sharp transition of a regular rounded rectangle.
First, a quick recap: a squircle is defined by the equation (x^n + y^n = r^n) (where (n > 2); (n=4) gives the classic squircle shape). Android's Canvas doesn't have a built-in drawSquircle method, but we can build one using either a compatible Path with Bézier curves (works on all Android versions) or the newer Android 13+ API (cleaner, more accurate).
1. Compatible Implementation (All Android Versions)
This uses Bézier curves to approximate a squircle. You can adjust the control point factor to tweak how "square" or "round" the shape looks.
private static Bitmap makeIcon(int size, int color, Bitmap icon) { final Bitmap output = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); final Canvas canvas = new Canvas(output); final Paint paint = new Paint(); // Configure paint for smooth rendering paint.setAntiAlias(true); paint.setColor(color); canvas.drawARGB(0, 0, 0, 0); // Clear the canvas // Build the squircle path using Bézier curves Path squirclePath = new Path(); float centerX = size / 2f; float centerY = size / 2f; float radius = size / 2f; // Control point factor: adjust this to change squareness (0.4-0.6 works well) float squarenessFactor = 0.5f; float offsetX = radius * squarenessFactor; float offsetY = radius * (1 - squarenessFactor); // Draw the squircle path squirclePath.moveTo(centerX, centerY - radius); squirclePath.cubicTo(centerX + offsetX, centerY - radius, centerX + radius, centerY - offsetY, centerX + radius, centerY); squirclePath.cubicTo(centerX + radius, centerY + offsetX, centerX + offsetX, centerY + radius, centerX, centerY + radius); squirclePath.cubicTo(centerX - offsetX, centerY + radius, centerX - radius, centerY + offsetX, centerX - radius, centerY); squirclePath.cubicTo(centerX - radius, centerY - offsetY, centerX - offsetX, centerY - radius, centerX, centerY - radius); squirclePath.close(); // Draw the squircle canvas.drawPath(squirclePath, paint); // Draw the icon (centered on the squircle) if (icon != null) { float iconSize = size * 0.6f; // Adjust icon size relative to squircle float left = centerX - (iconSize / 2f); float top = centerY - (iconSize / 2f); canvas.drawBitmap(icon, left, top, paint); } return output; }
Key Notes:
- squarenessFactor: Values closer to 0 make the shape more circular; values closer to 1 make it more square. Stick to 0.4-0.6 for a classic squircle.
- We replaced the original
drawCirclecall withdrawPathusing our custom squircle path. - The icon drawing logic is preserved and adjusted to center the icon on the squircle.
2. Simplified Implementation (Android 13+, API 33+)
Android 13 introduced Path.addSquircle(), which lets you draw a perfect squircle with a single method call. Use this if you don't need to support older versions.
import android.os.Build; import androidx.annotation.RequiresApi; @RequiresApi(api = Build.VERSION_CODES.TIRAMISU) private static Bitmap makeIconApi33(int size, int color, Bitmap icon) { final Bitmap output = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); final Canvas canvas = new Canvas(output); final Paint paint = new Paint(); paint.setAntiAlias(true); paint.setColor(color); canvas.drawARGB(0, 0, 0, 0); float centerX = size / 2f; float centerY = size / 2f; float radius = size / 2f; float squareness = 0.5f; // 0 = circle, 1 = square // Build squircle path with the native API Path squirclePath = new Path(); squirclePath.addSquircle(centerX, centerY, radius, squareness); canvas.drawPath(squirclePath, paint); // Draw centered icon if (icon != null) { float iconSize = size * 0.6f; float left = centerX - (iconSize / 2f); float top = centerY - (iconSize / 2f); canvas.drawBitmap(icon, left, top, paint); } return output; }
Key Notes:
- squareness parameter: Directly controls the shape—0 gives a perfect circle, 1 gives a square, and 0.5 gives a balanced squircle.
- This method is more accurate than the Bézier approximation and requires less code.
内容的提问来源于stack exchange,提问作者fahmy

