android自定义Folder

android 4.0自定义Folder--UFolder
===============
LauncherSettings & Favorites 增加
static final int ITEM_TYPE_UFOLDER = 5;
用以区分普通Folder

1.在各个地方针对ufolder进行判断,进行定制
1)//加载default_worksapce.xml,并记录到数据库

LauncherProvider.java

 private long addUFolder(SQLiteDatabase db, ContentValues values) {
    values.put(Favorites.ITEM_TYPE, Favorites.ITEM_TYPE_UFOLDER);
    values.put(Favorites.SPANX, 1);
    values.put(Favorites.SPANY, 1);
    long id = generateNewId();
    values.put(Favorites._ID, id);
    if (dbInsertAndCheck(this, db, TABLE_FAVORITES, null, values) <= 0) {
        return -1;
    } else {
        return id;
    }
}

 private int loadCustomFolder(SQLiteDatabase db, int workspaceResourceId) {
 	...
 	
 	if (TAG_UFOLDER.equals(name)) {
	    String title;
	    int titleResId =  a.getResourceId(R.styleable.Favorite_title, -1);
	    if (titleResId != -1) {
	        title = mContext.getResources().getString(titleResId);
	    } else {
	        title = mContext.getResources().getString(R.string.folder_name);
	    }
	    values.put(LauncherSettings.Favorites.TITLE, title);
	    long folderId = addUFolder(db, values);
	    added = folderId >= 0;

	    ArrayList<Long> folderItems = new ArrayList<Long>();
	    
	    values.clear();
	    values.put(LauncherSettings.Favorites.CONTAINER, folderId);
	    // get the download app list
	    getCustomAppList();
		for (AppInfo appInfo : appList) {
	    	long id = addCustumAppShortcut(db, values, packageManager, intent, appInfo);
	    	if (id >= 0) {
	    		folderItems.add(id);
	    	}
	    }
	    // We can only have folders with >= 2 items, so we need to remove the
	    // folder and clean up if less than 2 items were included, or some
	    // failed to add, and less than 2 were actually added
	    //if (folderItems.size() < 2 && folderId >= 0) {
	        // We just delete the folder and any items that made it
	        /*deleteId(db, folderId);
	        if (folderItems.size() > 0) {
	            deleteId(db, folderItems.get(0));
	        }
	        added = false;*/
	    //}
	}
 	.....
 }
//获取系统下载的app列表
private ArrayList<AppInfo> appList = new ArrayList<AppInfo>();
private void getCustomAppList() {
	List<PackageInfo> packages = mContext.getPackageManager().getInstalledPackages(PackageManager.GET_ACTIVITIES);
	for (int i = 0; i < packages.size(); i++) {
		PackageInfo packageInfo = packages.get(i);
		if ((packageInfo.applicationInfo.flags & ApplicationInfo.DOWNLOADED_FLAG) == 0) {
			ActivityInfo aInfo;
			try {
				aInfo = packageInfo.activities[0];
			} catch (Exception e) {
				Log.w(TAG, "Got exception for getCustomAppList", e);
				continue;
			}
			AppInfo tmpInfo = new AppInfo();
			tmpInfo.appName = packageInfo.applicationInfo.loadLabel(mContext.getPackageManager()).toString();
			tmpInfo.appIcon = packageInfo.applicationInfo.loadIcon(mContext.getPackageManager());
			tmpInfo.packageName = packageInfo.packageName;
			tmpInfo.versionName = packageInfo.versionName;
			tmpInfo.versionCode = packageInfo.versionCode;
			if (aInfo != null) tmpInfo.className = aInfo.name;
			// Only display the non-system app info
			appList.add(tmpInfo);
		}
	}
}
        
//把列表插入数据库,LauncherModel loadWorkspace  就能加载了      
private long addCustumAppShortcut(SQLiteDatabase db, ContentValues values,
		PackageManager packageManager, Intent intent, AppInfo appInfo) {
	long id = -1;
	ActivityInfo info;
	String packageName = appInfo.packageName;
    String className = appInfo.className;
    try {
        ComponentName cn;
        try {
            cn = new ComponentName(packageName, className);
            info = packageManager.getActivityInfo(cn, 0);
        } catch (PackageManager.NameNotFoundException nnfe) {
            String[] packages = packageManager.currentToCanonicalPackageNames(
                new String[] { packageName });
            cn = new ComponentName(packages[0], className);
            info = packageManager.getActivityInfo(cn, 0);
        }
        id = generateNewId();
        intent.setComponent(cn);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
                Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
        values.put(Favorites.INTENT, intent.toUri(0));
        values.put(Favorites.TITLE, appInfo.appName);
        values.put(Favorites.ITEM_TYPE, Favorites.ITEM_TYPE_APPLICATION);
        values.put(Favorites.SPANX, 1);
        values.put(Favorites.SPANY, 1);
        values.put(Favorites._ID, generateNewId());
        if (dbInsertAndCheck(this, db, TABLE_FAVORITES, null, values) < 0) {
            return -1;
        }
    } catch (PackageManager.NameNotFoundException e) {
        Log.w(TAG, "Unable to add favorite: " + packageName +
                "/" + className, e);
    }
	return id;
}


2) 加载ufolder

LauncherModel.java

private void loadWorkspace() {
	.....

	 while (!mStopped && c.moveToNext()) {
	    try {
	        int itemType = c.getInt(itemTypeIndex);
	        switch (itemType) {
	        case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
	        case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
	        ...
	        case LauncherSettings.Favorites.ITEM_TYPE_UFOLDER:
            	isUFolder = true;
            case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
                id = c.getLong(idIndex);
                FolderInfo folderInfo = findOrMakeFolder(sFolders, id);

                //设置 ufolder 的itemType
                // 这里用了个boolean isUFolder 判断,因为好像只有case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
                // 才能生成folder.(应该会后更好的解决方法)
                if (isUFolder) folderInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_UFOLDER;
                folderInfo.title = c.getString(titleIndex);
                folderInfo.id = id;
                container = c.getInt(containerIndex);
                folderInfo.container = container;
                folderInfo.screen = c.getInt(screenIndex);
                folderInfo.cellX = c.getInt(cellXIndex);
                folderInfo.cellY = c.getInt(cellYIndex);

                // check & update map of what's occupied
                if (!checkItemPlacement(occupied, folderInfo)) {
                    break;
                }
                switch (container) {
                    case LauncherSettings.Favorites.CONTAINER_DESKTOP:
                    case LauncherSettings.Favorites.CONTAINER_HOTSEAT:
                        sWorkspaceItems.add(folderInfo);
                        break;
                }

                sItemsIdMap.put(folderInfo.id, folderInfo);
                sFolders.put(folderInfo.id, folderInfo);
                
                isUFolder = false;
                break;
                ........   	

	}                        

}


3)定义 ufloder 图标

Launcher.java

public void bindItems(ArrayList<ItemInfo> shortcuts, int start, int end) {
        setLoadOnResume();

        final Workspace workspace = mWorkspace;
        for (int i=start; i<end; i++) {
            final ItemInfo item = shortcuts.get(i);

            // Short circuit if we are loading dock items for a configuration which has no dock
            if (item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT &&
                    mHotseat == null) {
                continue;
            }

            switch (item.itemType) {
                case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
                case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
                    View shortcut = createShortcut((ShortcutInfo)item);
                    workspace.addInScreen(shortcut, item.container, item.screen, item.cellX,
                            item.cellY, 1, 1, false);
                    break;
                case LauncherSettings.Favorites.ITEM_TYPE_UFOLDER:
                	//ufolder icon layout ufolder_icon.xml
                	FolderIcon newUFolder = FolderIcon.fromXml(R.layout.ufolder_icon, this,
                            (ViewGroup) workspace.getChildAt(workspace.getCurrentPage()),
                            (FolderInfo) item, mIconCache);
                    // 就是通过这在workspace中显示folder的        
                    workspace.addInScreen(newUFolder, item.container, item.screen, item.cellX,
                            item.cellY, 1, 1, false);
                	break;
                case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
                    FolderIcon newFolder = FolderIcon.fromXml(R.layout.folder_icon, this,
                            (ViewGroup) workspace.getChildAt(workspace.getCurrentPage()),
                            (FolderInfo) item, mIconCache);
                    workspace.addInScreen(newFolder, item.container, item.screen, item.cellX,
                            item.cellY, 1, 1, false);
                    break;
            }
        }
        workspace.requestLayout();
    }


Workspace.java

private void onDropExternal(final int[] touchXY, final Object dragInfo,
            final CellLayout cellLayout, boolean insertAtFirst, DragObject d) {

	switch (info.itemType) {
	    case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
	    case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
	        if (info.container == NO_ID && info instanceof ApplicationInfo) {
	            // Came from all apps -- make a copy
	            info = new ShortcutInfo((ApplicationInfo) info);
	        }
	        view = mLauncher.createShortcut(R.layout.application, cellLayout,
	                (ShortcutInfo) info);
	        break;
	    case LauncherSettings.Favorites.ITEM_TYPE_UFOLDER:
	    	 view = FolderIcon.fromXml(R.layout.ufolder_icon, mLauncher, cellLayout,
	                 (FolderInfo) info, mIconCache);
	         break;
	    case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
	        view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher, cellLayout,
	                (FolderInfo) info, mIconCache);
	        break;
	    default:
	        throw new IllegalStateException("Unknown item type: " + info.itemType);
	    }

}


===============

2.ufolder 的其他额外功能
1)当自定义的folder,所包含的内容<=1时,不从Launcher界面删除,也不删除数据库的记录

Folder.java

private void replaceFolderWithFinalItem() {
	if (mInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_UFOLDER)
		return;
    ItemInfo finalItem = null;

    if (getItemCount() == 1) {
        finalItem = mInfo.contents.get(0);
    }

    // Remove the folder completely
    CellLayout cellLayout = mLauncher.getCellLayout(mInfo.container, mInfo.screen);
    cellLayout.removeView(mFolderIcon);
    if (mFolderIcon instanceof DropTarget) {
        mDragController.removeDropTarget((DropTarget) mFolderIcon);
    }
    mLauncher.removeFolder(mInfo);

    if (finalItem != null) {
        LauncherModel.addOrMoveItemInDatabase(mLauncher, finalItem, mInfo.container,
                mInfo.screen, mInfo.cellX, mInfo.cellY);
    }
    LauncherModel.deleteItemFromDatabase(mLauncher, mInfo);

    // Add the last remaining child to the workspace in place of the folder
    if (finalItem != null) {
        View child = mLauncher.createShortcut(R.layout.application, cellLayout,
                (ShortcutInfo) finalItem);

        mLauncher.getWorkspace().addInScreen(child, mInfo.container, mInfo.screen, mInfo.cellX,
                mInfo.cellY, mInfo.spanX, mInfo.spanY);
    }
}


2).ufolder onDrop 时,不能删除。
在workspace中移动ufolder时,不显示DeleteDropTarget。就是那个 (X Remove) 图标

DeleteDropTarget extends ButtonDropTarget

public void onDragStart(DragSource source, Object info, int dragAction) {
    boolean isVisible = true;
    boolean isUninstall = false;
    
    if (info instanceof FolderInfo) {
    	FolderInfo folderInfo = (FolderInfo) info;
    	if (folderInfo.itemType == 5) {
    		isVisible = false;
        }
    }

    ......
}    

// 删除对应的DragObject
private void completeDrop(DragObject d) {
    ItemInfo item = (ItemInfo) d.dragInfo;
    if (isAllAppsApplication(d.dragSource, item)) {
        // Uninstall the application if it is being dragged from AppsCustomize
        mLauncher.startApplicationUninstallActivity((ApplicationInfo) item);
    } else if (isWorkspaceOrFolderApplication(d)) {
        LauncherModel.deleteItemFromDatabase(mLauncher, item);
    } else if (isWorkspaceFolder(d)) {
        // Remove the folder from the workspace and delete the contents from launcher model
        FolderInfo folderInfo = (FolderInfo) item;
        mLauncher.removeFolder(folderInfo);
        LauncherModel.deleteFolderContentsFromDatabase(mLauncher, folderInfo);
    } else if (isWorkspaceOrFolderWidget(d)) {
        // Remove the widget from the workspace
        mLauncher.removeAppWidget((LauncherAppWidgetInfo) item);
        LauncherModel.deleteItemFromDatabase(mLauncher, item);

        final LauncherAppWidgetInfo launcherAppWidgetInfo = (LauncherAppWidgetInfo) item;
        final LauncherAppWidgetHost appWidgetHost = mLauncher.getAppWidgetHost();
        if (appWidgetHost != null) {
            // Deleting an app widget ID is a void call but writes to disk before returning
            // to the caller...
            new Thread("deleteAppWidgetId") {
                public void run() {
                    appWidgetHost.deleteAppWidgetId(launcherAppWidgetInfo.appWidgetId);
                }
            }.start();
        }
    }
}


3).监控app install事件,ufolder 自动添加刚安装的app

Lancher.java

/**
 * A package was installed.
 *
 * Implementation of the method from LauncherModel.Callbacks.
 */
public void bindAppsAdded(ArrayList<ApplicationInfo> apps) {
    setLoadOnResume();
    removeDialog(DIALOG_CREATE_SHORTCUT);
    mWorkspace.addItems(apps);

    if (mAppsCustomizeContent != null) {
        mAppsCustomizeContent.addApps(apps);
    }
}


Workspace.java

void addItems(final ArrayList<ApplicationInfo> apps) {
	final ArrayList<ShortcutInfo> addContentInfo = new ArrayList<ShortcutInfo>();
	final int appCount = apps.size();
	for (int i = 0; i < appCount; i++) {
		addContentInfo.add(apps.get(i).makeShortcut());
	}
	ArrayList<CellLayout> cellLayouts = getWorkspaceAndHotseatCellLayouts();
	for (final CellLayout layoutParent: cellLayouts) {
		final ViewGroup layout = layoutParent.getChildrenLayout();
		// Avoid ANRs by treating each screen separately
        post(new Runnable() {
        	public void run() {
        		final ArrayList<View> childrenToAdd = new ArrayList<View>();
        		childrenToAdd.clear();
        		
        		int childCount = layout.getChildCount();
        		for (int j = 0; j < childCount; j++) {
                    final View view = layout.getChildAt(j);
                    Object tag = view.getTag();
                    
                    if (tag instanceof FolderInfo) {
                    	final FolderInfo info = (FolderInfo) tag;
                    	if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_UFOLDER) {
                            for (ShortcutInfo appInfo : addContentInfo) {
                            	// add in folder and insert data to database
                            	info.add(appInfo);
                            }
                    	}
                    }
        		}
        	}
        });
	}
}


 

===================
其他有关Folder的记录:
1.FolderIcon.java
computePreviewItemDrawingParams()
计算Folder上预览图标的参数,在dispatchDraw()中绘制,默认画三个。

2.两个shortcut拖到一起时会形成个folder
Workspace.java
createUserFolderIfNecessary();

在onDrogOver()中

if (userFolderPending && dragOverView != mLastDragOverView) {
    mFolderCreationAlarm.setOnAlarmListener(new
            FolderCreationAlarmListener(mDragTargetLayout, mTargetCell[0], mTargetCell[1]));
    mFolderCreationAlarm.setAlarm(FOLDER_CREATION_TIMEOUT);
}

public void onAlarm(Alarm alarm) {
    if (mDragFolderRingAnimator == null) {
        mDragFolderRingAnimator = new FolderRingAnimator(mLauncher, null);
    }
    mDragFolderRingAnimator.setCell(cellX, cellY);
    mDragFolderRingAnimator.setCellLayout(layout);
    mDragFolderRingAnimator.animateToAcceptState();
    Resources res = mLauncher.getResources();
    //生成folder的动画
    FolderRingAnimator.sSharedInnerRingDrawable = res.getDrawable(R.drawable.portal_ring_inner_holo);
    FolderRingAnimator.sSharedOuterRingDrawable = res.getDrawable(R.drawable.portal_ring_outer_holo); 
    layout.showFolderAccept(mDragFolderRingAnimator);
    mCreateUserFolderOnDrop = true;
}



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值