packages\apps\Launcher3\res\xml\folder_shapes.xml
packages\apps\Launcher3\src\com\android\launcher3\graphics\IconShape.java
上述文件的解析在 IconShape中
private static List<IconShape> getAllShapes(Context context) {
ArrayList<IconShape> result = new ArrayList<>();
try (XmlResourceParser parser = context.getResources().getXml(R.xml.folder_shapes)) {
// Find the root tag
int type;
while ((type = parser.next()) != XmlPullParser.END_TAG
&& type != XmlPullParser.END_DOCUMENT
&& !"shapes".equals(parser.getName()));
final int depth = parser.getDepth();
int[] radiusAttr = new int[] {R.attr.folderIconRadius};
while (((type = parser.next()) != XmlPullParser.END_TAG ||
parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
if (type == XmlPullParser.START_TAG) {
AttributeSet attrs = Xml.asAttributeSet(parser);
TypedArray a = context.obtainStyledAttributes(attrs, radiusAttr);
IconShape shape = getShapeDefinition(parser.getName(), a.getFloat(0, 1));
a.recycle();
result.add(shape);
}
}
} catch (IOException | XmlPullParserException e) {
throw new RuntimeException(e);
}
return result;
}
@TargetApi(Build.VERSION_CODES.O)
protected static void pickBestShape(Context context) {
// Pick any large size
final int size = 200;
Region full = new Region(0, 0, size, size);
Region iconR = new Region();
AdaptiveIconDrawable drawable = new AdaptiveIconDrawable(
new ColorDrawable(Color.BLACK), new ColorDrawable(Color.BLACK));
drawable.setBounds(0, 0, size, size);
iconR.setPath(drawable.getIconMask(), full);
Path shapePath = new Path();
Region shapeR = new Region();
// Find the shape with minimum area of divergent region.
int minArea = Integer.MAX_VALUE;
IconShape closestShape = null;
for (IconShape shape : getAllShapes(context)) {
shapePath.reset();
shape.addToPath(shapePath, 0, 0, size / 2f);
shapeR.setPath(shapePath, full);
shapeR.op(iconR, Op.XOR);
int area = GraphicsUtils.getArea(shapeR);
if (area < minArea) {
minArea = area;
closestShape = shape;
}
}
if (closestShape != null) {
sInstance = closestShape;
}
// Initialize shape properties
sNormalizationScale = IconNormalizer.normalizeAdaptiveIcon(drawable, size, null);
}