android Launcher源碼解析04:DeleteZone

來源:互聯網
上載者:User

       DeleteZone是launcher中比較簡單的一部分,其操作為

  • 長按案頭上某個表徵圖後,會出現如下內容:1)dock欄消失;2)原dock欄位置出現一個垃圾箱圖案;
  • 將該表徵圖拖動到垃圾箱位置後,會發現如下內容:1)垃圾箱表徵圖變為開啟;2)垃圾箱周圍出現一片紅色地區;3)表徵圖變為紅色;
  • 將該表徵圖放到垃圾箱位置後,該表徵圖會被從案頭中刪除;
        查看DeleteZone的源碼,只要搞清楚了以上3個步驟是如何?的,那麼就理解了他的代碼了。 1)建構函式
public DeleteZone(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public DeleteZone(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);                final int srcColor = context.getResources().getColor(R.color.delete_color_filter);        mTrashPaint.setColorFilter(new PorterDuffColorFilter(srcColor, PorterDuff.Mode.SRC_ATOP));        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DeleteZone, defStyle, 0);        mOrientation = a.getInt(R.styleable.DeleteZone_direction, ORIENTATION_HORIZONTAL);        a.recycle();    }    @Override    protected void onFinishInflate() {        super.onFinishInflate();        mTransition = (TransitionDrawable) getDrawable();    }

        這裡主要完成三項工作:1)構造對象;2)建立紅色地區的濾鏡顏色為紅色;3)判斷方向,這個是在launcher.xml中設定的方向。

    <com.xuxm.demo.launcher.DeleteZone        android:id="@+id/delete_zone"        android:layout_width="@dimen/delete_zone_size"        android:layout_height="@dimen/delete_zone_size"        android:paddingTop="@dimen/delete_zone_padding"        android:layout_gravity="top|center_horizontal"        android:scaleType="center"        android:src="@drawable/delete_zone_selector"        android:visibility="invisible"        launcher:direction="horizontal"        />

         同時需要注意到這裡的圖片並不是一張圖片,而是一個TransitionDrawable,其內容為:

<transition xmlns:android="http://schemas.android.com/apk/res/android">    <item android:drawable="@drawable/trashcan"  />    <item android:drawable="@drawable/trashcan_hover"  /></transition>

          這裡,他可以動態切換顯示的圖片,這也是你看到的垃圾箱關閉與開啟兩種顯示方式的根源。其實現在這幾個函數中實現:

   public void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset,            DragView dragView, Object dragInfo) {        mTransition.reverseTransition(TRANSITION_DURATION);        dragView.setPaint(mTrashPaint);    }    public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,            DragView dragView, Object dragInfo) {    }    public void onDragExit(DragSource source, int x, int y, int xOffset, int yOffset,            DragView dragView, Object dragInfo) {        mTransition.reverseTransition(TRANSITION_DURATION);        dragView.setPaint(null);    }

        這裡,當被拖動表徵圖進入到DeleteZone地區時,表徵圖變為垃圾箱開啟中狀態,如果表徵圖離開了DeleteZone地區時,垃圾箱恢複為垃圾箱關閉狀態;dragView.setPaint(mTrashPaint);這一句是設定被拖動表徵圖顯示為紅色。

2)刪除表徵圖     當你將表徵圖放到垃圾箱地區後,就會刪除該表徵圖。這裡需要區別不同的表徵圖來源區域和不同的表徵圖類型,分別進行刪除。如果是對於檔案夾,需要先將檔案夾中的內容刪除,然後再刪除該檔案夾。
 public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,            DragView dragView, Object dragInfo) {        final ItemInfo item = (ItemInfo) dragInfo;        if (item.container == -1) return;        if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {            if (item instanceof LauncherAppWidgetInfo) {                mLauncher.removeAppWidget((LauncherAppWidgetInfo) item);            }        } else {            if (source instanceof UserFolder) {                final UserFolder userFolder = (UserFolder) source;                final UserFolderInfo userFolderInfo = (UserFolderInfo) userFolder.getInfo();                // Item must be a ShortcutInfo otherwise it couldn't have been in the folder                // in the first place.                userFolderInfo.remove((ShortcutInfo)item);            }        }        if (item instanceof UserFolderInfo) {            final UserFolderInfo userFolderInfo = (UserFolderInfo)item;            LauncherModel.deleteUserFolderContentsFromDatabase(mLauncher, userFolderInfo);            mLauncher.removeFolder(userFolderInfo);        } else if (item instanceof LauncherAppWidgetInfo) {            final LauncherAppWidgetInfo launcherAppWidgetInfo = (LauncherAppWidgetInfo) item;            final LauncherAppWidgetHost appWidgetHost = mLauncher.getAppWidgetHost();            if (appWidgetHost != null) {                final int appWidgetId = launcherAppWidgetInfo.appWidgetId;                // 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();            }        }        LauncherModel.deleteItemFromDatabase(mLauncher, item);    }

         之前在測試公司產品時,發現直接將表徵圖從檔案夾中直接拖動到垃圾箱刪除後,會發現檔案夾內顯示出現問題,究其原因就是未考慮到直接從檔案夾中刪除中的問題。

3)長按表徵圖開始拖動及結束拖動
public void onDragStart(DragSource source, Object info, int dragAction) {        final ItemInfo item = (ItemInfo) info;        if (item != null) {            mTrashMode = true;            createAnimations();            final int[] location = mLocation;            getLocationOnScreen(location);            /**             * mRight\mLeft\mBottom\mTop屬保護域,             * 需通過getRight()\getLeft()\getBottom()\getTop()來訪問             * modify by author             */            mRegion.set(location[0], location[1], location[0] + getRight() - getLeft(),                    location[1] + getBottom() - getTop());            mDragController.setDeleteRegion(mRegion);            mTransition.resetTransition();            startAnimation(mInAnimation);            mHandle.startAnimation(mHandleOutAnimation);            setVisibility(VISIBLE);        }    }

        之類首先獲得垃圾箱表徵圖的地區大小,據此設定DeleteZone位置的地區,同時初始化動畫對象createAnimations()。

    public void onDragEnd() {        if (mTrashMode) {            mTrashMode = false;            mDragController.setDeleteRegion(null);            startAnimation(mOutAnimation);            mHandle.startAnimation(mHandleInAnimation);            setVisibility(GONE);        }    }

        取消拖動地區效果,並且將dock欄回複,隱藏垃圾箱;4)初始化動畫

private void createAnimations() {        if (mInAnimation == null) {            mInAnimation = new FastAnimationSet();            final AnimationSet animationSet = mInAnimation;            animationSet.setInterpolator(new AccelerateInterpolator());            animationSet.addAnimation(new AlphaAnimation(0.0f, 1.0f));            if (mOrientation == ORIENTATION_HORIZONTAL) {                animationSet.addAnimation(new TranslateAnimation(Animation.ABSOLUTE, 0.0f,                        Animation.ABSOLUTE, 0.0f, Animation.RELATIVE_TO_SELF, 1.0f,                        Animation.RELATIVE_TO_SELF, 0.0f));            } else {                animationSet.addAnimation(new TranslateAnimation(Animation.RELATIVE_TO_SELF,                        1.0f, Animation.RELATIVE_TO_SELF, 0.0f, Animation.ABSOLUTE, 0.0f,                        Animation.ABSOLUTE, 0.0f));            }            animationSet.setDuration(ANIMATION_DURATION);        }        if (mHandleInAnimation == null) {            mHandleInAnimation = new AlphaAnimation(0.0f, 1.0f);            mHandleInAnimation.setDuration(ANIMATION_DURATION);        }        if (mOutAnimation == null) {            mOutAnimation = new FastAnimationSet();            final AnimationSet animationSet = mOutAnimation;            animationSet.setInterpolator(new AccelerateInterpolator());            animationSet.addAnimation(new AlphaAnimation(1.0f, 0.0f));            if (mOrientation == ORIENTATION_HORIZONTAL) {                animationSet.addAnimation(new FastTranslateAnimation(Animation.ABSOLUTE, 0.0f,                        Animation.ABSOLUTE, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f,                        Animation.RELATIVE_TO_SELF, 1.0f));            } else {                animationSet.addAnimation(new FastTranslateAnimation(Animation.RELATIVE_TO_SELF,                        0.0f, Animation.RELATIVE_TO_SELF, 1.0f, Animation.ABSOLUTE, 0.0f,                        Animation.ABSOLUTE, 0.0f));            }            animationSet.setDuration(ANIMATION_DURATION);        }        if (mHandleOutAnimation == null) {            mHandleOutAnimation = new AlphaAnimation(1.0f, 0.0f);            mHandleOutAnimation.setFillAfter(true);            mHandleOutAnimation.setDuration(ANIMATION_DURATION);        }    }

        這裡主要設定三個動畫對象,dock隱藏動畫,mHandleInAnimation和mHandleOutAnimation;垃圾箱表徵圖動畫對象mInAnimation和mOutAnimation;

5)自訂Animation這裡自訂了兩個Animation,主要是重載了兩個函數,這兩個被重載的函數的功能如下:       

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.