對Android4.0中Launcher2一些調試記錄

最近項目打板了,板子跑起來後發現Launcher的所有程序界面不能全屏(兩邊有黑框,只在中上部顯示),但是主界面看上去是全屏顯示的(後面證實也非全屏顯示。)

我們的屏是21寸的,分辨率爲1980*1080。

最開始以爲是uboot裏的屏幕參數沒設置好,後面check之後發現沒問題。沒辦法,只有去看Launcher的代碼。

首先,在我最開始就有一個誤解,這個誤解浪費我很多時間。由於最開始的時候主界面(也就是workspace)是沒有黑框的,所以我一直認爲workspace的代碼是沒問題的。

後面經驗證主界面也沒有按屏幕的實際分辨率顯示!Workspace.java中構造函數有如下代碼:

複製代碼
 1 final float smallestScreenDim = res.getConfiguration().smallestScreenWidthDp;
 2  cellCountX = 1;
 3             while (CellLayout.widthInPortrait(res, cellCountX + 1) <= smallestScreenDim) {
 4                 
 5                 cellCountX++;
 6             }
 7 
 8             cellCountY = 1;
 9             while (actionBarHeight + CellLayout.heightInLandscape(res, cellCountY + 1)
10                 <= smallestScreenDim - systemBarHeight) {
11                 cellCountY++;
12             }
13         }
複製代碼
smallestScreenDim 按字面理解意思應該是屏幕寬度的最小值(以DP爲單位),cellCountX初始化爲1,然後通過一個while循環去計算X、Y方向各能放多少個應用。
我們看看widthInPortrait方法:
複製代碼
1     static int widthInPortrait(Resources r, int numCells) {
2         // We use this method from Workspace to figure out how many rows/columns Launcher should
3         // have. We ignore the left/right padding on CellLayout because it turns out in our design
4         // the padding extends outside the visible screen size, but it looked fine anyway.
5         int cellWidth = r.getDimensionPixelSize(R.dimen.workspace_cell_width);
6         int minGap = Math.min(r.getDimensionPixelSize(R.dimen.workspace_width_gap),
7                 r.getDimensionPixelSize(R.dimen.workspace_height_gap));
8         return minGap * (numCells - 1) + cellHeight * numCells;
9     }

複製代碼
getDimensionPixelSize方法實際上是把dimens.xml中設置的cellWidth大小由dp轉換成px!
widthInPortrait計算後的返回值會與smallestScreenDim進行比較,如果比smallestScreenDim 小,那麼說明能夠再放一個APP,cellCount進行加一。
循環比較之後就會得出在該屏幕上能放多少行,多少列個應用。
既然cellWidth的單位爲px,那與通過他計算後得到的值進行比較的smallestScreenDim單位應該也是px,而不是像他字面所說的dp!

通過加log進一步確認,我發現android4.0默認的smallestScreenDim爲720!也就是720px,而我的屏實際像素寬度爲1920!
將smallestScreenDim強制設置爲1920後all apps界面能全屏了,主界面的workspace也大了很多!說明之前主界面的全屏都是假象。。。
我們可以在代碼裏得到屏幕的寬度,然後賦值給smallestScreenDim以便於支持更多的屏幕。
至於之前的主界面爲什麼沒有黑色的邊框,我估計是壁紙設置的原因,具體細節沒去深究了。

後面發現系統默認的圖標在大屏幕上顯示效果不太好,有點偏小,直接修改res/values-sw600dp/dimens.xml中的app_icon_size。
改完make之後發現圖標並沒有變大。。。
跟蹤代碼Launcher.java[onCreate]--->[setLauncher]--->LauncherApplication[onCreate]--->[new LauncherModel]--->[createIconBitmap]
複製代碼
  1 static Bitmap createIconBitmap(Drawable icon, Context context) {
  2         synchronized (sCanvas) { // we share the statics :-(
  3             if (sIconWidth == -1) {
  4                 initStatics(context);
  5             }
  6 
  7             int width = sIconWidth;
  8             int height = sIconHeight;
  9             
 10             Log.i("Info","In createIconBitmap width is: "+width);
 11             Log.i("Info","In createIconBitmap height is: "+height);
 12             if (icon instanceof PaintDrawable) {
 13                 Log.i("Info","Icon type is PaintDrawable" );
 14                 PaintDrawable painter = (PaintDrawable) icon;
 15                 painter.setIntrinsicWidth(width);
 16                 painter.setIntrinsicHeight(height);
 17             } else if (icon instanceof BitmapDrawable) {
 18                 // Ensure the bitmap has a density.
 19                 Log.i("Info","Icon type is BitmapDrawable" );
 20                 BitmapDrawable bitmapDrawable = (BitmapDrawable) icon;
 21                 Bitmap bitmap = bitmapDrawable.getBitmap();
 22                 if (bitmap.getDensity() == Bitmap.DENSITY_NONE) {
 23                     bitmapDrawable.setTargetDensity(context.getResources().getDisplayMetrics());
 24                 }
 25             }
 26             int sourceWidth = icon.getIntrinsicWidth();
 27             int sourceHeight = icon.getIntrinsicHeight();
 28             Log.i("Info","IntrinsicWidth is: "+sourceWidth);
 29             Log.i("Info","IntrinsicHeight is: "+sourceHeight);
 30             if (sourceWidth > 0 && sourceHeight > 0) {
 31                 // There are intrinsic sizes.
 32                 if (width < sourceWidth || height < sourceHeight) {
 33                     // It's too big, scale it down.
 34                     final float ratio = (float) sourceWidth / sourceHeight;
 35                     if (sourceWidth > sourceHeight) {
 36                         height = (int) (width / ratio);
 37                     } else if (sourceHeight > sourceWidth) {
 38                         width = (int) (height * ratio);
 39                     }
 40                 } else if (sourceWidth < width && sourceHeight < height) {
 41                     // Don't scale up the icon
 42                     //width = sourceWidth;
 43                     //height = sourceHeight;
 44                     width = sIconWidth;
 45                     height = sIconHeight;
 46                 }
 47             }
 48 
 49             // no intrinsic size --> use default size
 50             int textureWidth = sIconTextureWidth;
 51             int textureHeight = sIconTextureHeight;
 52             Log.i("Info","textureWidth is: "+textureWidth);
 53             Log.i("Info","textureHeight is: "+textureHeight);
 54 
 55             final Bitmap bitmap = Bitmap.createBitmap(textureWidth, textureHeight,
 56                     Bitmap.Config.ARGB_8888);
 57             final Canvas canvas = sCanvas;
 58             canvas.setBitmap(bitmap);
 59 
 60             final int left = (textureWidth-width) / 2;
 61             final int top = (textureHeight-height) / 2;
 62 
 63             if (false) {
 64                 // draw a big box for the icon for debugging
 65                 canvas.drawColor(sColors[sColorIndex]);
 66                 if (++sColorIndex >= sColors.length) sColorIndex = 0;
 67                 Paint debugPaint = new Paint();
 68                 debugPaint.setColor(0xffcccc00);
 69                 canvas.drawRect(left, top, left+width, top+height, debugPaint);
 70             }
 71 
 72             sOldBounds.set(icon.getBounds());
 73             icon.setBounds(left, top, left+width, top+height);
 74             icon.draw(canvas);
 75             icon.setBounds(sOldBounds);
 76             canvas.setBitmap(null);
 77 
 78             return bitmap;
 79         }
 80     }
 81 private static void initStatics(Context context) {
 82         final Resources resources = context.getResources();
 83         final DisplayMetrics metrics = resources.getDisplayMetrics();
 84         final float density = metrics.density;
 85 
 86         //default is 72*density
 87         sIconWidth = sIconHeight = (int) resources.getDimension(R.dimen.app_icon_size);
 88         sIconTextureWidth = sIconTextureHeight = sIconWidth;
 89 
 90         sBlurPaint.setMaskFilter(new BlurMaskFilter(5 * density, BlurMaskFilter.Blur.NORMAL));
 91         sGlowColorPressedPaint.setColor(0xffffc300);
 92         sGlowColorPressedPaint.setMaskFilter(TableMaskFilter.CreateClipTable(0, 30));
 93         sGlowColorFocusedPaint.setColor(0xffff8e00);
 94         sGlowColorFocusedPaint.setMaskFilter(TableMaskFilter.CreateClipTable(0, 30));
 95 
 96         ColorMatrix cm = new ColorMatrix();
 97         cm.setSaturation(0.2f);
 98         sDisabledPaint.setColorFilter(new ColorMatrixColorFilter(cm));
 99         sDisabledPaint.setAlpha(0x88);
100     }
複製代碼


經過分析,發現在這個方法裏對圖片大小進行了判斷,如果大於默認的圖片大小96dp,那麼強制將圖片大小設置爲96dp!
稍作修改圖標就能放大了,細節不說了,大家看看代碼就知道了。
http://www.cnblogs.com/leon19870907/archive/2012/04/20/2459593.html
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章