Launcher3 5.1 客制化定制问题修改(更新7.0MTK和高通的修改)

本文全部是基于将双层界面修改成单层桌面的问题

最近客户提出要客制化定制Launcher3
对最近的修改做个笔记

1.修改默认壁纸

替换 frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.jpg即可(注意找到对应的分辨率)

2.将双层桌面改成单层桌面

LauncherAppState.java

    public static boolean isDisableAllApps() {
      ...
      return true 即可
    }

3.删除谷歌搜索

Launcher.java

 public View getQsbBar() {
  ...
   return null; 即可
  }

注意上面会隐藏谷歌搜索,但是还会占着位置
想要不占位置
DeviceProfile.java

private void updateIconSize(float scale, int drawablePadding, Resources resources,
                                DisplayMetrics dm) {      
   ...   
     // Search Bar
  ...
        searchBarSpaceHeightPx = getSearchBarTopOffset()
                + resources.getDimensionPixelSize(R.dimen.dynamic_grid_search_bar_height);
    
         将searchBarSpaceHeightPx=0;即可 
}

Launcher里面好多东西都是动态计算的,所以这里计算为0就行

4.修改主屏幕大小位置 (即图标 几*几)

DynamicGrid.java

public DynamicGrid(Context context, Resources resources,
                       int minWidthPx, int minHeightPx,
                       int widthPx, int heightPx,
                       int awPx, int ahPx) {
        DisplayMetrics dm = resources.getDisplayMetrics();
        ArrayList deviceProfiles =
                new ArrayList();
        boolean hasAA = !LauncherAppState.isDisableAllApps();
        DEFAULT_ICON_SIZE_PX = pxFromDp(DEFAULT_ICON_SIZE_DP, dm);
        // Our phone profiles include the bar sizes in each orientation
        deviceProfiles.add(new DeviceProfile("Super Short Stubby",
                255, 300,  2, 3,  48, 13, (hasAA ? 3 : 5), 48, R.xml.default_workspace_4x4));
        deviceProfiles.add(new DeviceProfile("Shorter Stubby",
                255, 400,  3, 3,  48, 13, (hasAA ? 3 : 5), 48, R.xml.default_workspace_4x4));
       
         /*chc edit*/     
        (客户要求2 * 2  ,找到对应的屏幕大小  修改 parameters 第4,5个即可 )     
        parameters  6:可以调整Icon的大小
        parameters  8:控制hotseatd的数量
        parameters  9:控制hotseatd的Icon大小
       deviceProfiles.add(new DeviceProfile("Short Stubby",
                275, 420,  2, 2,  70, 23, (hasAA ? 3 : 3), 53, R.xml.default_workspace_4x4));
      /*chc end */      


        deviceProfiles.add(new DeviceProfile("Stubby",
                255, 450,  2, 3,  48, 13, (hasAA ? 5 : 5), 48, R.xml.default_workspace_4x4));
        deviceProfiles.add(new DeviceProfile("Nexus S",
                296, 491.33f,  4, 4,  48, 13, (hasAA ? 5 : 5), 48, R.xml.default_workspace_4x4));
        /// M: add 294 X 460 profile
        deviceProfiles.add(new DeviceProfile("294 X 460",
                294, 460,  3, 3,  50, 25, (hasAA ? 5 : 5), 59, R.xml.default_workspace_4x4));
        deviceProfiles.add(new DeviceProfile("Nexus 4",
                335, 567,  4, 4,  DEFAULT_ICON_SIZE_DP, 13, (hasAA ? 5 : 5), 56, R.xml.default_workspace_4x4));
        deviceProfiles.add(new DeviceProfile("Nexus 5",
                359, 567,  4, 4,  DEFAULT_ICON_SIZE_DP, 13, (hasAA ? 5 : 5), 56, R.xml.default_workspace_4x4));
        deviceProfiles.add(new DeviceProfile("Large Phone",
                406, 694,  5, 5,  64, 14.4f,  5, 56, R.xml.default_workspace_5x5));
        // The tablet profile is odd in that the landscape orientation
        // also includes the nav bar on the side
        deviceProfiles.add(new DeviceProfile("Nexus 7",
                575, 904,  5, 6,  72, 14.4f,  7, 60, R.xml.default_workspace_5x6));
        // Larger tablet profiles always have system bars on the top & bottom
        deviceProfiles.add(new DeviceProfile("Nexus 10",
                727, 1207,  5, 6,  76, 14.4f,  7, 64, R.xml.default_workspace_5x6));
        deviceProfiles.add(new DeviceProfile("20-inch Tablet",
                1527, 2527,  7, 7,  100, 20,  7, 72, R.xml.default_workspace_4x4));
        mMinWidth = dpiFromPx(minWidthPx, dm);
        mMinHeight = dpiFromPx(minHeightPx, dm);
        mProfile = new DeviceProfile(context, deviceProfiles,
                mMinWidth, mMinHeight,
                widthPx, heightPx,
                awPx, ahPx,
                resources);
    }

5.禁止hotseat里面的Icon拖动,并且禁止形成文件夹

Launcher.java

public boolean onLongClick(View v) {
        ...
        CellLayout.CellInfo longClickCellInfo = null;
        View itemUnderLongClick = null;
        if (v.getTag() instanceof ItemInfo) {
            ItemInfo info = (ItemInfo) v.getTag();
            longClickCellInfo = new CellLayout.CellInfo(v, info);;
            itemUnderLongClick = longClickCellInfo.cell;
            resetAddInfo();
        }   
        /*chc add */     在此处进行判断是否在hotseat进行长按   
        boolean isHotseatbutten=false;
        if(longClickCellInfo!=null){
            isHotseatbutten= longClickCellInfo.container==-100? false:true;   //每一个Icon都有一个container的属性
//hostSeat:是-101  其他的是-100 

        }
        if(isHotseatbutten){
            return false;
        }
        /*chc end*/             
         final boolean inHotseat = isHotseatLayout(v);  //不知为何原因 此isHotseatLayout(v)并不能判断时候在hotseat区域 
         ...
    
        return true;
    }

禁止文件夹的形成
Workspace.java

boolean createUserFolderIfNecessary(View newView, long container, CellLayout target,
            int[] targetCell, float distance, boolean external, DragView dragView,
            Runnable postAnimationRunnable) {
    ...
    /*chc add*/
        if(container==-101){
           return false;
        }
        /*chc end*/  
    ...
}

6.将文件夹修改为4宫格

FolderIcon.java

1:修改圆形成为正方形
FolderIcon.xml


     

2.修改缩略图为2*2

 // The number of icons to display in the
    private static final int NUM_ITEMS_IN_PREVIEW = 4;  //此处为文件夹显示缩略图的数量
 // The amount of vertical spread between items in the stack [0...1]
    private static final float PERSPECTIVE_SHIFT_FACTOR = 1.20f;  //值越大 缩略图越小


    private PreviewItemDrawingParams computePreviewItemDrawingParams(int index,
            PreviewItemDrawingParams params) {
              /*chc add */
                int index_order = index;
                final int previewPadding = FolderRingAnimator.sPreviewPadding;
               /*chc end*/

        // We want to imagine our coordinates from the bottom left, growing up and to the
        // right. This is natural for the x-axis, but for the y-axis, we have to invert things.
        float transY = mAvailableSpaceInPreview - (offset + scaledSize + scaleOffsetCorrection);
        float transX = offset + scaleOffsetCorrection;
        
         
        /*chc add */     在此处计算图标的位置 , 下面是自己计算图标的位置
            transX=1 * previewPadding +2;
            transY=mAvailableSpaceInPreview - (mBaselineIconSize*2 + scaleOffsetCorrection)+previewPadding;
        if(index_order==1){
            transX=mBaselineIconSize+previewPadding*3;
            transY=mAvailableSpaceInPreview - (mBaselineIconSize*2 + scaleOffsetCorrection)+previewPadding;
        }else if(index_order==2){           
            transX=1 * previewPadding +2;
            transY=mAvailableSpaceInPreview - (mBaselineIconSize + scaleOffsetCorrection)+previewPadding*2;
        }else if(index_order==3){
            transX=mBaselineIconSize+previewPadding*3;
            transY=mAvailableSpaceInPreview - (mBaselineIconSize + scaleOffsetCorrection)+previewPadding*2;
        }
        
        /*chc end*/
        
        return params;
    }


  public FolderRingAnimator(Launcher launcher, FolderIcon folderIcon) {
         ....
                sSharedOuterRingDrawable = res.getDrawable(R.drawable.bg_rect);
                sSharedInnerRingDrawable = res.getDrawable(R.drawable.bg_rect);
                sSharedFolderLeaveBehind = res.getDrawable(R.drawable.bg_rect);  //此处替换文件夹托动处形成动画的图片 
            
      ...
            }
        }

7.Launcher修改成单层删除了google搜索无法显示删除APP按钮

问题3将google搜索return 成了null, 为了不占位置并且将他的高度修改成了0
所以导致了APP删除按钮的不显示
原因是google搜索包含了APP删除的按钮

所以现将问题3修改回来
Launcher.java

 public View getQsbBar() {
   ...
      if (widgetId != -1) {
                if (true) {   //chc  edit isSmallLandTablet()  to  true  这个是判断searchView 的加载模式
                                // 改成true是默认让他直接加载不要动态加载
                    mQsbView = getLayoutInflater().inflate(R.layout.qsb, mSearchDropTargetBar, false);  
                ..
                } else {
                    mQsb = mAppWidgetHost.createView(this, widgetId, searchProvider);                                  
                }
                    ///M.
                }
  }

修改qsb.xml

  
   
   
        android:src="@drawable/ic_home_search_normal_holo"
        android:adjustViewBounds="true" />

    
    
        />

修改完成删除App按钮可能会有点大
为了整体美观
修改问题3的search的高度进行适当调整
此问题结束

8.将安装的APP拖动至删除APP按钮 无法显示删除对话框,并且删除后重启有会还原

原因是将安装的APP 进行删除流程的时候判断成了Weight,所以导致删不了,并且不能弹出删除对话框

修改Launcher的加载模式进行对安装的APP进行flag标记
LauncherModel.java

private boolean loadWorkspace(){
 ...
while (!mStopped && c.moveToNext()) {
...
if (info != null) {
              //add by chc
         if(intent.getAction() != null && intent.getAction().equals(Intent.ACTION_MAIN)){
     try {
                                       
        final String packageName = intent.getComponent().getPackageName();
        //List app = mLauncherApps.getActivityList(packageName, user);
        PackageInfo pi = manager.getPackageInfo(packageName, 0);
        if (!pi.applicationInfo.enabled) {
            // If we return null here, the corresponding item will be removed from the launcher
            // db and will not appear in the workspace.
            //return null;
            }
                                  
        final int appFlags = manager.getApplicationInfo(packageName, 0).flags;
        if ((appFlags & android.content.pm.ApplicationInfo.FLAG_SYSTEM) == 0) {
                info.flags |= AppInfo.DOWNLOADED_FLAG;                        
            if ((appFlags & android.content.pm.ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
                    info.flags |= AppInfo.UPDATED_SYSTEM_APP_FLAG;
                }
            }
            //  info.firstInstallTime = manager.getPackageInfo(packageName, 0).firstInstallTime;
    } catch (NameNotFoundException e) {
        Log.d(TAG, "getPackInfo failed for componentName " + intent.getComponent());
            //return null;
    }
}
   // chc  add end
}

}

DeleteDropTarget.java
这里面是对删除的流程,在这里判断是否是安装的App,如果是安装的 就调用startApplicationUninstallActivity()进行删除

private void completeDrop(DragObject d) {
    if (isAllAppsApplication(d.dragSource, item)) {
    }
    ...
    else if (isWorkspaceOrFolderApplication(d)) {
     / /chc add if the dragview is install app that this methed will uninstalled else the shutcut delete it 
             if(item.itemType != LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT){
                 ShortcutInfo shortcut = (ShortcutInfo) item;
                 final UserHandleCompat user = shortcut.user;
                 final ComponentName componentName = shortcut.intent.getComponent();
                 mLauncher.startApplicationUninstallActivity(componentName, shortcut.flags, user);
               }else{
                   LauncherModel.deleteItemFromDatabase(mLauncher, item);
               }
              //chc add end 
    }

}

此问题到此结束

9.将hotSeat中间图标变大 两边的缩小

CellLayout.java

 public boolean addViewToCellLayout(View child, int index, int childId, LayoutParams params,
            boolean markCells) {
       ...
        child.setScaleX(getChildrenScale());
        child.setScaleY(getChildrenScale());
        /*chc add */
        if(mIsHotseat){
            Log.d("cuihangchao","childId"+childId);
            if(lp.cellX!=1){
             child.setScaleX(0.8f);
                child.setScaleY(0.8f);
            }
        }
        /*chc end*/

        // Generate an id for each view, this assumes we have at most 256x256 cells
     ...
        return false;
    }

在此处判断hotseat是否是Hotseat上面的图标
然后根据ID, 将需要变动的进行响应的缩放
这样修改完成之后还有坑
会将大图标拖动到小图标上,或进行大图渲染,无法变成小图。重启后会还原。

最终修改方案
ShortcutAndWidgetContainer.java

@Override
    protected void dispatchDraw(Canvas canvas) {
        @SuppressWarnings("all") // suppress dead code warning
        final boolean debug = false;
       /*chc add */
        for (int i = getChildCount() - 1; i >= 0; i--) {
                final View child = getChildAt(i);           
                final CellLayout.LayoutParams lps = (CellLayout.LayoutParams) child.getLayoutParams();
                if(mIsHotseatLayout){   
                if(lps.cellX!=1){
                    child.setScaleX(0.7f);
                    child.setScaleY(0.7f);
                }
            }           
        }
        /*chc end*/ 
                                    
        if (debug) {
            // Debug drawing for hit space
            Paint p = new Paint();
            p.setColor(0x6600FF00);
            for (int i = getChildCount() - 1; i >= 0; i--) {
                final View child = getChildAt(i);
                final CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();

                canvas.drawRect(lp.x, lp.y, lp.x + lp.width, lp.y + lp.height, p);
            }
        }
        super.dispatchDraw(canvas);
    }

拖动的时候会不停的进入此方法,
所以在此方法里面进行判断,
将不会影响到渲染的效果

改这个问题的时候踩了好多的坑。
哎,踩了好多的坑

此问题到此结束

大概上面的修改launcher 的样子


Launcher3 5.1 客制化定制问题修改(更新7.0MTK和高通的修改)_第1张图片
图片发自App

MTK 7.0 Launcher3修改单层桌面

2.1删除Google搜索(packages\apps\Launcher3\res\values\dimens.xml )

 6dp  //留下 (卸载 移除 的高度,因为搜索和他们是包含的) 

Launcher.xml(注意找到对应分辨率)


  

com/android/launcher3/SearchDropTargetBar

 @Override
    public void onDragStart(DragSource source, Object info, int dragAction) {
        animateToState(State.DROP_TARGET, DEFAULT_DRAG_FADE_DURATION);          
          this.setVisibility(View.VISIBLE);  //拖动的时候将自己显示
          mQSB.setVisibility(View.GONE); //将QSB隐藏
         
    }


 @Override
    public void onDragEnd() {
        if (!mDeferOnDragEnd) {
            animateToState(State.SEARCH_BAR, DEFAULT_DRAG_FADE_DURATION);
        } else {
            mDeferOnDragEnd = false;
        }
       this.setVisibility(View.GONE);  //拖动结束的时候将自己隐藏
    }

 public void enableAccessibleDrag(boolean enable) {
        if (mQSB != null) {
            mQSB.setVisibility(View.GONE);  //直接将qsb自己隐藏,
        }
        mInfoDropTarget.enableAccessibleDrag(enable);
        mDeleteDropTarget.enableAccessibleDrag(enable);
        mUninstallDropTarget.enableAccessibleDrag(enable);
    }



删除移除按钮,单层桌面不需要移除
com/android/launcher3/DeleteDropTarget

@Override
    protected boolean supportsDrop(DragSource source, Object info) {
          if (info instanceof ShortcutInfo) {
                ShortcutInfo item = (ShortcutInfo) info;            
                return item.itemType !=           LauncherSettings.BaseLauncherColumns.ITEM_TYPE_APPLICATION;
            }
                  
          return info instanceof LauncherAppWidgetInfo;
    
        //return source.supportsDeleteDropTarget() && supportsDrop(info);
    }
到此,搜索就移除了,但是不影响拖动可卸载的应用进行卸载

2.2 将所有的应用加载到Workspace

/*chc add*/ 
    public void customBindWorkspaceItems() {
            final Context context = mApp.getContext();
            ArrayList tmpInfos;
            ArrayList added = new ArrayList();
            synchronized (sBgLock) {
                for (AppInfo app : mBgAllAppsList.data) {
                    tmpInfos = getItemInfoForComponentName(app.componentName, app.user);
                    if (tmpInfos.isEmpty()) {
                        // We are missing an application icon, so add this to the workspace
                        if(app.itemType!=LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) { //不进行加载xml配置的Item
                            Log.d("Cuihangchao","app.title="+app.title);
                           added.add(app);
                        }
                        // This is a rare event, so lets log it
                        Log.e(TAG, "Missing Application on load: " + app);
                    }
                }
                if (!added.isEmpty()) {
                    addAndBindAddedWorkspaceItems(context,added);  //添加到Workspace
                }
            }
    
    }


LoaderTask的run()进行添加 

 public void run() {
            synchronized (mLock) {
          ...
            keep_running: {
                if (DEBUG_LOADERS) Log.d(TAG, "step 1: loading workspace");
                loadAndBindWorkspace();

                if (mStopped) {
                    LauncherLog.d(TAG, "LoadTask break in the middle, this = " + this);
                    break keep_running;
                }

                waitForIdle();

                // second step
                if (DEBUG_LOADERS) Log.d(TAG, "step 2: loading all apps");
                loadAndBindAllApps();

                customBindWorkspaceItems();//chc add
            }
  3.新的应用安装增加到workspace

  PackageUpdatedTask 的run
  
  ...
public void run() {
            synchronized (mLock) {
     if (added != null) {
                
        final ArrayList addedInfos = new ArrayList(added); //chc add
                addAndBindAddedWorkspaceItems(context, addedInfos);//chc add
                
                addAppsToAllApps(context, added);
                for (AppInfo ai : added) {
                    addedOrUpdatedApps.put(ai.componentName, ai);
                }
            }
...
}

到此,所有的应用都会加载到Workspace上面,不影响预制XML里面的应用进行重复加载    

2.3删除Allapp按钮

void resetLayout() {
        mContent.removeAllViewsInLayout();

        if(false){  //chc add 大家可以自己定义宏
            // Add the Apps button
            Context context = getContext();

            LayoutInflater inflater = LayoutInflater.from(context);
            TextView allAppsButton = (TextView)
                    inflater.inflate(R.layout.all_apps_button, mContent, false);
            Drawable d = context.getResources().getDrawable(R.drawable.all_apps_button_icon);

            mLauncher.resizeIconDrawable(d);
            int scaleDownPx = getResources().getDimensionPixelSize(R.dimen.all_apps_button_scale_down);
            Rect bounds = d.getBounds();
            d.setBounds(bounds.left, bounds.top + scaleDownPx / 2, bounds.right - scaleDownPx,
                    bounds.bottom - scaleDownPx / 2);
            allAppsButton.setCompoundDrawables(null, d, null, null);

            allAppsButton.setContentDescription(context.getString(R.string.all_apps_button_label));
            allAppsButton.setOnKeyListener(new HotseatIconKeyEventListener());
            if (mLauncher != null) {
                mLauncher.setAllAppsButton(allAppsButton);
                allAppsButton.setOnTouchListener(mLauncher.getHapticFeedbackTouchListener());
                allAppsButton.setOnClickListener(mLauncher);
                allAppsButton.setOnLongClickListener(mLauncher);
                allAppsButton.setOnFocusChangeListener(mLauncher.mFocusHandler);
            }

            // Note: We do this to ensure that the hotseat is always laid out in the orientation of
            // the hotseat in order regardless of which orientation they were added
            int x = getCellXFromOrder(mAllAppsButtonRank);
            int y = getCellYFromOrder(mAllAppsButtonRank);
            CellLayout.LayoutParams lp = new CellLayout.LayoutParams(x,y,1,1);
            lp.canReorder = false;
            mContent.addViewToCellLayout(allAppsButton, -1, allAppsButton.getId(), lp, true);
        }
    }
//修复Bug。快速扔图标 图标变灰,并且不消失
  DragController.java

public boolean onTouchEvent(MotionEvent ev) {
  ...
case MotionEvent.ACTION_UP:
            // Ensure that we've processed a move event at the current pointer location.
            handleMoveEvent(dragLayerX, dragLayerY);
            mHandler.removeCallbacks(mScrollRunnable);

            if (mDragging) {
                //PointF vec = isFlingingToDelete(mDragObject.dragSource);  //检测是否是扔图标,                         

                PointF vec=null;// 删除扔图标操作,
                if (!DeleteDropTarget.supportsDrop(mDragObject.dragInfo)) {
                    vec = null;
                }
                Log.d("Cuihangchao","vec="+vec);
                if (vec != null) {
                    dropOnFlingToDeleteTarget(dragLayerX, dragLayerY, vec);
                } else {
                    drop(dragLayerX, dragLayerY);
                }
            }
            endDrag();
...
}
  

到此,7.0的Launcher3就改成单层的了

附8.1修改https://blog.csdn.net/qq_30552095

此文会持续更新,有做Launcher的朋友可以参考参考

你可能感兴趣的:(Launcher3 5.1 客制化定制问题修改(更新7.0MTK和高通的修改))