定制系統(tǒng)無限循環(huán)系統(tǒng)桌面的Workspace CycleWorkspace

1.最近公司項(xiàng)目有個(gè)需求需要定制系統(tǒng)桌面并且實(shí)現(xiàn)無限循環(huán)滑動(dòng)俏讹,通過主窗口的layout我們可以得到系統(tǒng)桌面的分頁是通過Workspace來實(shí)現(xiàn)的伟葫;

2.通過代碼可以知道Workspace 繼承自PagedView穿稳,而pagedview的效果和viewpager其實(shí)類似,那么久簡(jiǎn)單了恰梢,那么我們通過復(fù)制首尾兩屏的頁面數(shù)據(jù)然后分別插入首尾兩個(gè)部分就行藻烤,這里應(yīng)用了這位小朋友的圖片來做說明。

3.那么接下來就是首尾兩頁數(shù)據(jù)的數(shù)據(jù)備份了妥泉,方式1就是在bind數(shù)據(jù)的時(shí)候記錄首尾兩頁數(shù)據(jù)的子項(xiàng)了椭微,然后再add到相對(duì)于新增的首尾兩個(gè)celllayout里面去,但是這樣的話太麻煩了尤其是還要去更新各種拖動(dòng)移除后的數(shù)據(jù)盲链;

4.通過源碼中的bindItems 方法可以得知蝇率,每個(gè)子item項(xiàng)目的tag其實(shí)就是bindItems迟杂,所以就不用去記錄首尾兩頁數(shù)據(jù)的數(shù)據(jù)了,直接通過view獲取item本慕,然后在逐個(gè)去添加就好了排拷;

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;

/**

* 定義一個(gè)可以循環(huán)滾動(dòng)的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) {

//設(shè)置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){//處理滑動(dòng)完成后頁面切換锅尘,實(shí)現(xiàn)循環(huán)效果

? ? ? ? ? ? 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();

}

//記錄拖動(dòng)前的分頁數(shù)量

private int mPageCount=0;

@Override

? ? public void onDragStart(DragObject dragObject, DragOptions options) {

if (CYCLE_MODE && getPageCount()>2){//移除首位兩個(gè)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();

//如果添加了分頁或者不變則切換當(dāng)前的分頁位置监氢,如果減少了位置則保持不變,避免出現(xiàn)空屏(子view 還未繪制完)的情況

? ? ? ? ? ? if (pageCount<=mPageCount){

++cur;

setCurrentPage(cur);

}

}

}

}


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末藤违,一起剝皮案震驚了整個(gè)濱河市浪腐,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌顿乒,老刑警劉巖议街,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異璧榄,居然都是意外死亡特漩,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門骨杂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來涂身,“玉大人,你說我怎么就攤上這事搓蚪「蚴郏” “怎么了?”我有些...
    開封第一講書人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵妒潭,是天一觀的道長(zhǎng)悍抑。 經(jīng)常有香客問我,道長(zhǎng)杜耙,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任拂盯,我火速辦了婚禮佑女,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘谈竿。我一直安慰自己团驱,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開白布空凸。 她就那樣靜靜地躺著嚎花,像睡著了一般。 火紅的嫁衣襯著肌膚如雪呀洲。 梳的紋絲不亂的頭發(fā)上紊选,一...
    開封第一講書人閱讀 51,287評(píng)論 1 301
  • 那天啼止,我揣著相機(jī)與錄音,去河邊找鬼兵罢。 笑死献烦,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的卖词。 我是一名探鬼主播巩那,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼此蜈!你這毒婦竟也來了即横?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤裆赵,失蹤者是張志新(化名)和其女友劉穎东囚,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體顾瞪,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡舔庶,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了陈醒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片惕橙。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖钉跷,靈堂內(nèi)的尸體忽然破棺而出弥鹦,到底是詐尸還是另有隱情,我是刑警寧澤爷辙,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布彬坏,位于F島的核電站,受9級(jí)特大地震影響膝晾,放射性物質(zhì)發(fā)生泄漏栓始。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一血当、第九天 我趴在偏房一處隱蔽的房頂上張望幻赚。 院中可真熱鬧,春花似錦臊旭、人聲如沸落恼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽佳谦。三九已至,卻和暖如春滋戳,著一層夾襖步出監(jiān)牢的瞬間钻蔑,已是汗流浹背啥刻。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留矢棚,地道東北人郑什。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像蒲肋,于是被迫代替她去往敵國(guó)和親蘑拯。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354