定制系统无限循环系统桌面的Workspace CycleWorkspace

1.最近公司项目有个需求需要定制系统桌面并且实现无限循环滑动,通过主窗口的layout我们可以得到系统桌面的分页是通过Workspace来实现的;

2.通过代码可以知道Workspace 继承自PagedView,而pagedview的效果和viewpager其实类似,那么久简单了,那么我们通过复制首尾两屏的页面数据然后分别插入首尾两个部分就行,这里应用了这位小朋友的图片来做说明。

3.那么接下来就是首尾两页数据的数据备份了,方式1就是在bind数据的时候记录首尾两页数据的子项了,然后再add到相对于新增的首尾两个celllayout里面去,但是这样的话太麻烦了尤其是还要去更新各种拖动移除后的数据;

4.通过源码中的bindItems 方法可以得知,每个子item项目的tag其实就是bindItems,所以就不用去记录首尾两页数据的数据了,直接通过view获取item,然后在逐个去添加就好了;

5.废话不多说了,直接上代码


package com.android.launcher3;

import android.content.Context;

import android.util.AttributeSet;

import android.util.Log;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import com.android.launcher3.dragndrop.DragOptions;

import com.android.launcher3.folder.Folder;

import com.android.launcher3.folder.FolderIcon;

import com.android.launcher3.touch.ItemLongClickListener;

/**

* 定义一个可以循环滚动的Workspace

*/

public class CycleWorkspaceextends Workspace {

private static final StringTAG ="CycleWorkspace";

//第一页的ID

    public static final int FIRST_SCREEN_ID = -1001;

//最后一页的ID

    public static final int LAST_SCREEN_ID =1001;

CellLayoutmEndCellLayout,mStartCellLayout;

public CycleWorkspace(Context context, AttributeSet attrs) {

super(context, attrs);

}

public CycleWorkspace(Context context, AttributeSet attrs,int defStyle) {

super(context, attrs, defStyle);

}

/**

    * copy 一份最后的页面存放在首位

    */

    public void addFirstCellLayout(){

//Log.e(TAG,"ScreenOrderID ="+mScreenOrder.get(mScreenOrder.size()-1));

        CellLayout cellLayout=  getScreenWithId(mScreenOrder.get(mScreenOrder.size()-1));

if (cellLayout.getChildCount()>0) {

ViewGroup viewGroup = (ViewGroup) cellLayout.getChildAt(0);

//Log.e(TAG, "addFirstCellLayout viewGroups=" + viewGroup.getChildCount());

            if (mStartCellLayout ==null) {

mStartCellLayout = copyInsertNewWorkspaceScreen(0);

mStartCellLayout.setId(FIRST_SCREEN_ID);

}else {

if (getChildAt(0).getId() !=FIRST_SCREEN_ID) {

addView(mStartCellLayout,0);

}

}               

mStartCellLayout.removeAllViews();

if (viewGroup.getChildCount() >0) {

//设置endCellLayout的view

for (int i =0; i < viewGroup.getChildCount(); i++) {

ItemInfo item = (ItemInfo) viewGroup.getChildAt(i).getTag();

View view =null;

if (iteminstanceof WorkspaceItemInfo) {

WorkspaceItemInfo info = (WorkspaceItemInfo) item;

view =mLauncher.createShortcut(viewGroup, info);

}else if (iteminstanceof FolderInfo) {

view = FolderIcon.fromXml(R.layout.folder_icon,mLauncher,viewGroup, (FolderInfo) item);

}else if (iteminstanceof LauncherAppWidgetInfo) {

view =mLauncher.inflateAppWidget((LauncherAppWidgetInfo) item);

}

if (view ==null) {

continue;

}

addCopyInScreen(view, item.cellX, item.cellY, item.spanX, item.spanY,mStartCellLayout);

}

}

}

}

/**

    * copy 首页一份最后的页面存放在最后面

    */

    public void addEndCellLayout(){

CellLayout cellLayout=  getScreenWithId(mScreenOrder.get(0));

//Log.e(TAG, "addEndCellLayout cellLayout=" + cellLayout);

        if (cellLayout.getChildCount()>0) {

if (mEndCellLayout ==null) {

mEndCellLayout = copyNewFirstWorkspaceScreen(getChildCount());

mEndCellLayout.setId(LAST_SCREEN_ID);

}else {

if (getChildAt(getChildCount()-1).getId() !=LAST_SCREEN_ID) {

addView(mEndCellLayout, getChildCount());

}

}

ViewGroup viewGroup = (ViewGroup) cellLayout.getChildAt(0);

//Log.e(TAG, "addEndCellLayout viewGroups=" + viewGroup.getChildCount());

mEndCellLayout.removeAllViews();

            if (viewGroup.getChildCount() >0) {

mEndCellLayout.removeAllViews();

for (int i =0; i < viewGroup.getChildCount(); i++) {

if (i==0){

if (mQsb !=null) {

CellLayout.LayoutParams lp =new CellLayout.LayoutParams(0,0,mEndCellLayout.getCountX(),1);

lp.canReorder =false;

mEndCellLayout.addViewToCellLayout(mQsb,0, R.id.copy_search_container_workspace, lp,true);

}

}else {

ItemInfo item = (ItemInfo) viewGroup.getChildAt(i).getTag();

View view =null;

if (iteminstanceof WorkspaceItemInfo) {

WorkspaceItemInfo info = (WorkspaceItemInfo) item;

view =mLauncher.createShortcut(viewGroup, info);

}else if (iteminstanceof FolderInfo) {

view = FolderIcon.fromXml(R.layout.folder_icon,mLauncher, viewGroup, (FolderInfo) item);

}else if (iteminstanceof LauncherAppWidgetInfo) {

view =mLauncher.inflateAppWidget((LauncherAppWidgetInfo) item);

}

if (view ==null) {

continue;

}

addCopyInScreen(view,  item.cellX, item.cellY, item.spanX, item.spanY,mEndCellLayout);

}

}

}

}

}

private void addCopyInScreen(View child,int x,int y,

int spanX,int spanY,CellLayout layout) {

//Log.e(TAG,"instanceof child ="+(child instanceof FolderIcon));

        if (childinstanceof FolderIcon) {

((FolderIcon) child).setTextVisible(true);

}

LayoutParams genericLp = child.getLayoutParams();

CellLayout.LayoutParams lp;

if (!(genericLpinstanceof CellLayout.LayoutParams)) {

lp =new CellLayout.LayoutParams(x, y, spanX, spanY);

}else {

lp = (CellLayout.LayoutParams) genericLp;

lp.cellX = x;

lp.cellY = y;

lp.cellHSpan = spanX;

lp.cellVSpan = spanY;

}

if (spanX <0 && spanY <0) {

lp.isLockedToGrid =false;

}

// Get the canonical child id to uniquely represent this view in this screen

        ItemInfo info = (ItemInfo) child.getTag();

int childId = info.id;

//Log.e(TAG,"childId ="+childId);

        boolean markCellsAsOccupied = !(childinstanceof Folder);

//Log.e(TAG,"markCellsAsOccupied ="+markCellsAsOccupied);

        if (!layout.addViewToCellLayout(child, -1, childId, lp, markCellsAsOccupied)) {

// TODO: This branch occurs when the workspace is adding views

            // outside of the defined grid

// maybe we should be deleting these items from the LauncherModel?

            Log.e(TAG,"Failed to add to item at (" + lp.cellX +"," + lp.cellY +") to CellLayout");

}

child.setHapticFeedbackEnabled(false);

child.setOnLongClickListener(ItemLongClickListener.INSTANCE_WORKSPACE);

if (childinstanceof DropTarget) {

Log.e(TAG,"addDropTarget ="+child);

mDragController.addDropTarget((DropTarget) child);

}

}

ViewmQsb=null;

public CellLayout copyNewFirstWorkspaceScreen(int insertIndex) {

CellLayout endPage = copyInsertNewWorkspaceScreen(insertIndex);

// Always add a QSB on the first screen.

        if (mQsb ==null) {

// In transposed layout, we add the QSB in the Grid. As workspace does not touch the

// edges, we do not need a full width QSB.

            mQsb = LayoutInflater.from(getContext())

.inflate(R.layout.copy_search_container_workspace, endPage,false);

}

CellLayout.LayoutParams lp =new CellLayout.LayoutParams(0,0, endPage.getCountX(),1);

lp.canReorder =false;

if (!endPage.addViewToCellLayout(mQsb,0, R.id.copy_search_container_workspace, lp,true)) {

Log.e(TAG,"Failed to add to item at (0, 0) to CellLayout");

}

return endPage;

}

public CellLayout copyInsertNewWorkspaceScreen(int insertIndex) {

// Inflate the cell layout, but do not add it automatically so that we can get the newly

// created CellLayout.

        CellLayout newScreen = (CellLayout) LayoutInflater.from(getContext()).inflate(

R.layout.workspace_screen,this,false );

newScreen.getShortcutsAndWidgets().setId(R.id.workspace_page_container);

int paddingLeftRight =mLauncher.getDeviceProfile().cellLayoutPaddingLeftRightPx;

int paddingBottom =mLauncher.getDeviceProfile().cellLayoutBottomPaddingPx;

newScreen.setPadding(paddingLeftRight,0, paddingLeftRight, paddingBottom);

addView(newScreen, insertIndex);

mStateTransitionAnimation.applyChildState(

mLauncher.getStateManager().getState(), newScreen, insertIndex);

if (mLauncher.getAccessibilityDelegate().isInAccessibleDrag()) {

newScreen.enableAccessibleDrag(true, CellLayout.WORKSPACE_ACCESSIBILITY_DRAG);

}

return newScreen;

}

@Override

    protected void onPageEndTransition() {

super.onPageEndTransition();

Log.e(TAG,"onPageEndTransition");

if (CYCLE_MODE && getPageCount()>1){//处理滑动完成后页面切换,实现循环效果

            if (getCurrentPage() == getPageCount() -1) {

addFirstCellLayout();

CellLayout curCellLayout = (CellLayout) getPageAt(getCurrentPage());

if (curCellLayout !=null && curCellLayout.getId() ==LAST_SCREEN_ID) {

//切换到第一页

                    setCurrentPage(1);

}

}else if (getCurrentPage() ==0) {

addEndCellLayout();

CellLayout curCellLayout = (CellLayout) getPageAt(getCurrentPage());

if (curCellLayout !=null && curCellLayout.getId() ==FIRST_SCREEN_ID) {

//切换到最后一页

                    setCurrentPage(getChildCount() -2);

}

}

}

}

@Override

    protected void onPageBeginTransition() {

super.onPageBeginTransition();

}

//记录拖动前的分页数量

private int mPageCount=0;

@Override

    public void onDragStart(DragObject dragObject, DragOptions options) {

if (CYCLE_MODE && getPageCount()>2){//移除首位两个View

            removeViewAt(getChildCount()-1);

removeViewAt(0);}

super.onDragStart(dragObject, options);

mPageCount=getPageCount();

Log.e(TAG,"onDragStart mPageCount="+mPageCount);

}

@Override

    public void onDragEnd() {

super.onDragEnd();

int pageCount=getPageCount();

Log.e(TAG,"onDragEnd currentPage="+getCurrentPage() +",pageCount="+pageCount );

if (CYCLE_MODE && getPageCount()>1){

int cur =getCurrentPage();

addFirstCellLayout();

addEndCellLayout();

//如果添加了分页或者不变则切换当前的分页位置,如果减少了位置则保持不变,避免出现空屏(子view 还未绘制完)的情况

            if (pageCount<=mPageCount){

++cur;

setCurrentPage(cur);

}

}

}

}


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342