diff options
author | Tor Norbye <tnorbye@google.com> | 2012-11-11 05:02:09 -0800 |
---|---|---|
committer | Tor Norbye <tnorbye@google.com> | 2012-11-27 17:39:31 -0800 |
commit | 9fa856d059304a084be83feeeabf447a1c1b087b (patch) | |
tree | 0bba4a7b44d38770fbd493c9c7f364890005005e /lint/libs | |
parent | b833b88b813e6881a09d18eb08913e51b0ba46ee (diff) | |
download | sdk-9fa856d059304a084be83feeeabf447a1c1b087b.zip sdk-9fa856d059304a084be83feeeabf447a1c1b087b.tar.gz sdk-9fa856d059304a084be83feeeabf447a1c1b087b.tar.bz2 |
Add lint launcher icon shape check
Change-Id: I789e74b667afbaea4089a62060b7138dadd8da6b
Diffstat (limited to 'lint/libs')
4 files changed, 96 insertions, 2 deletions
diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/BuiltinIssueRegistry.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/BuiltinIssueRegistry.java index e521803..a211029 100644 --- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/BuiltinIssueRegistry.java +++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/BuiltinIssueRegistry.java @@ -55,7 +55,7 @@ public class BuiltinIssueRegistry extends IssueRegistry { private static final List<Issue> sIssues; static { - final int initialCapacity = 128; + final int initialCapacity = 129; List<Issue> issues = new ArrayList<Issue>(initialCapacity); issues.add(AccessibilityDetector.ISSUE); @@ -150,6 +150,7 @@ public class BuiltinIssueRegistry extends IssueRegistry { issues.add(IconDetector.ICON_EXTENSION); issues.add(IconDetector.ICON_COLORS); issues.add(IconDetector.ICON_XML_AND_PNG); + issues.add(IconDetector.ICON_LAUNCHER_SHAPE); issues.add(TypographyDetector.DASHES); issues.add(TypographyDetector.QUOTES); issues.add(TypographyDetector.FRACTIONS); diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/IconDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/IconDetector.java index eb87a5d..f435810 100644 --- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/IconDetector.java +++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/IconDetector.java @@ -333,6 +333,26 @@ public class IconDetector extends ResourceXmlDetector implements Detector.JavaSc ICON_TYPE_SCOPE).setMoreInfo( "http://developer.android.com/design/style/iconography.html"); //$NON-NLS-1$ + /** Wrong launcher icon shape */ + public static final Issue ICON_LAUNCHER_SHAPE = Issue.create( + "IconLauncherShape", //$NON-NLS-1$ + "Checks that launcher icons follow the recommended visual style", + + "According to the Android Design Guide " + + "(http://developer.android.com/design/style/iconography.html) " + + "your launcher icons should \"use a distinct silhouette\", " + + "a \"three-dimensional, front view, with a slight perspective as if viewed " + + "from above, so that users perceive some depth.\"\n" + + "\n" + + "The unique silhouette implies that your launcher icon should not be a filled " + + "square.", + Category.ICONS, + 6, + Severity.WARNING, + IconDetector.class, + ICON_TYPE_SCOPE).setMoreInfo( + "http://developer.android.com/design/style/iconography.html"); //$NON-NLS-1$ + /** Constructs a new {@link IconDetector} check */ public IconDetector() { } @@ -1113,6 +1133,25 @@ public class IconDetector extends ResourceXmlDetector implements Detector.JavaSc return file.getName().contains("-nodpi"); } + private Map<File, BufferedImage> mImageCache; + + @Nullable + private BufferedImage getImage(@Nullable File file) throws IOException { + if (mImageCache == null) { + mImageCache = Maps.newHashMap(); + } else { + BufferedImage image = mImageCache.get(file); + if (image != null) { + return image; + } + } + + BufferedImage image = ImageIO.read(file); + mImageCache.put(file, image); + + return image; + } + private void checkDrawableDir(Context context, File folder, File[] files, Map<File, Dimension> pixelSizes, Map<File, Long> fileSizes) { if (folder.getName().equals(DRAWABLE_FOLDER) @@ -1179,6 +1218,18 @@ public class IconDetector extends ResourceXmlDetector implements Detector.JavaSc } } + if (context.isEnabled(ICON_LAUNCHER_SHAPE)) { + // Look up launcher icon name + for (File file : files) { + String name = file.getName(); + if (isLauncherIcon(name) + && !endsWith(name, DOT_XML) + && !endsWith(name, DOT_9PNG)) { + checkLauncherShape(context, file); + } + } + } + // Check icon sizes if (context.isEnabled(ICON_EXPECTED_SIZE)) { checkExpectedSizes(context, folder, files); @@ -1205,6 +1256,36 @@ public class IconDetector extends ResourceXmlDetector implements Detector.JavaSc } } } + + mImageCache = null; + } + + /** + * Check that launcher icons do not fill every pixel in the image + */ + private void checkLauncherShape(Context context, File file) { + try { + BufferedImage image = getImage(file); + if (image != null) { + // TODO: see if the shape is rectangular but inset from outer rectangle; if so + // that's probably not right either! + for (int y = 0, height = image.getHeight(); y < height; y++) { + for (int x = 0, width = image.getWidth(); x < width; x++) { + int rgb = image.getRGB(x, y); + if ((rgb & 0xFF000000) == 0) { + return; + } + } + } + + String message = "Launcher icons should not fill every pixel of their square " + + "region; see the design guide for details"; + context.report(ICON_LAUNCHER_SHAPE, Location.create(file), + message, null); + } + } catch (IOException e) { + // Pass: ignore files we can't read + } } /** @@ -1231,7 +1312,7 @@ public class IconDetector extends ResourceXmlDetector implements Detector.JavaSc // also check that they actually include a -v11 or -v14 folder with proper // icons, since the below won't flag the older icons. try { - BufferedImage image = ImageIO.read(file); + BufferedImage image = getImage(file); if (image != null) { if (isActionBarIcon) { checkPixels: diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/IconDetectorTest.java b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/IconDetectorTest.java index 4053c33..e2c20ba 100644 --- a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/IconDetectorTest.java +++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/IconDetectorTest.java @@ -49,6 +49,7 @@ public class IconDetectorTest extends AbstractCheckTest { ALL.add(IconDetector.ICON_NODPI); ALL.add(IconDetector.ICON_COLORS); ALL.add(IconDetector.ICON_XML_AND_PNG); + ALL.add(IconDetector.ICON_LAUNCHER_SHAPE); } @Override @@ -444,5 +445,16 @@ public class IconDetectorTest extends AbstractCheckTest { )); } + public void testSquareLauncher() throws Exception { + mEnabled = Collections.singleton(IconDetector.ICON_LAUNCHER_SHAPE); + assertEquals( + "res/drawable-hdpi/ic_launcher_filled.png: Warning: Launcher icons should not fill every pixel of their square region; see the design guide for details [IconLauncherShape]\n" + + "0 errors, 1 warnings\n", + lintProject( + "apicheck/minsdk4.xml=>AndroidManifest.xml", + "res/drawable-hdpi/filled.png=>res/drawable-hdpi/ic_launcher_filled.png", + "res/drawable-mdpi/sample_icon.gif=>res/drawable-mdpi/ic_launcher_2.gif" + )); + } }
\ No newline at end of file diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/drawable-hdpi/filled.png b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/drawable-hdpi/filled.png Binary files differnew file mode 100644 index 0000000..59fd90a --- /dev/null +++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/drawable-hdpi/filled.png |