android Launcher源码解析04:DeleteZone

       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,主要是重载了两个函数,这两个被重载的函数的功能如下:

       

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值