点击打开进入应用的动画(点击非Android View)

android点击一个View进入一个应用,通常会有好几种动画,可以通过xml控制,也可以通过其内部提供的ActivityOptions类来控制。那么最近我们的载体(一个桌面)需要使用ActivityOptions.makeScaleUpAnimation的动画方式来进入一个应用,如果我们点击的是一个View v,那么正常的程序可以是酱紫:

Intent intent = 。。。
int[] pos = new int[2];
v.getLocationOnScreen(pos);
intent.setSourceBounds(new Rect(pos[0], pos[1], pos[0] + v.getWidth(), pos[1] + v.getHeight()));
ActivityOptions opts = ActivityOptions.makeScaleUpAnimation(v, 0, 0, v.getMeasuredWidth(),
                        v.getMeasuredHeight());
 startActivity(intent, opts.toBundle());

 上述效果就是点击一个图标(一个View)然后就进入到一个应用,中间的这个过程的动画效果就是伤处的opts控制滴,所以这种方法还是蛮简单的。那么问题来了,我点击的不是View怎么办?其实在桌面上的东西都是View,只不过我们的东西有点特别,opengl实现的,整体的内容是一个View,但是内部的空间没有一个是View的子类,那怎么办咯?例如amigo随变桌面里的创意时钟就是酱紫的,这整张图是一个View,内部的却不是View,又要求以点击的部位弹出应用,而不是以整个View弹出:


首先可以看到startActivity的第一个参数intent需要的内容,它就是需要4个int类型的值,而且分别是左上角的x坐标,左上角的y坐标,长度,宽度,好吧,这4个值都可以自己给值了。

再看到startActivity的第二个参数,一个Bundle对象,然后我们就进入到了ActivityOptions的源码看到toBundle方法,其实就是要传一些键值对:

 public Bundle toBundle() {
        if (mAnimationType == ANIM_DEFAULT) {
            return null;
        }
        Bundle b = new Bundle();
        if (mPackageName != null) {
            b.putString(KEY_PACKAGE_NAME, mPackageName);
        }
        b.putInt(KEY_ANIM_TYPE, mAnimationType);
        switch (mAnimationType) {
            case ANIM_CUSTOM:
            case ...
...
}

        return b;
    }

  再看makeScaleUpAnimation方法:

    public static ActivityOptions makeScaleUpAnimation(View source,
            int startX, int startY, int width, int height) {
        ActivityOptions opts = new ActivityOptions();
        opts.mPackageName = source.getContext().getPackageName();
        opts.mAnimationType = ANIM_SCALE_UP;
        int[] pts = new int[2];
        source.getLocationOnScreen(pts);
        opts.mStartX = pts[0] + startX;
        opts.mStartY = pts[1] + startY;
        opts.mWidth = width;
        opts.mHeight = height;
        return opts;
    }

 可以看到这个View v的作用:1.获取当前应用的包名;2.获取这个view在屏幕上的左上角的坐标

结合上述两个源码,我们再次进入到toBundle,找到mAnimationType = ANIM_SCALE_UP需要的简直对:

b.putString(KEY_PACKAGE_NAME, mPackageName);//这个自己可以获取
  b.putInt(KEY_ANIM_TYPE, mAnimationType);//ANIM_SCALE_UP常量
 case ANIM_SCALE_UP:
                b.putInt(KEY_ANIM_START_X, mStartX);
                b.putInt(KEY_ANIM_START_Y, mStartY);
                b.putInt(KEY_ANIM_WIDTH, mWidth);
                b.putInt(KEY_ANIM_HEIGHT, mHeight);
     break;

 好吧,由此可见需要的键值对一共有6个,另外需要的就是动画起始的坐标和初始框框的长度与宽度,其中长度和宽度我们可以自己给个固定的值,那么接下来就是mStartX和mStartY怎么获取?

其实它的源码写的很清楚了

 int[] pts = new int[2];
View.getLocationOnScreen(pts);

 通过上述方法可以得到一个View控制的左上角的坐标,但是这里的值并非我们想要的,我们需要点击例如上图的右下角那个图标呢? 不可能以整个View来弹出吧,所以还需要详细的点击的坐标。好在onTouchEvent(MotionEvent event)中的event可以得到当前点击的view中的坐标

event.getX()得到该点击在View中的坐标,又View在屏幕上的左上角的坐标是pts[0],那就是说 x=event.getX()+pts[0]就是我所点击的点在屏幕上的x坐标,由此y=event.getY()+pts[1]是我所点击的点在屏幕上的Y坐标,再给个定值长度和宽度=20,那就可以得到想要的Bundle了。

 Bundle b = new Bundle();
 b.putString(KEY_PACKAGE_NAME, packageName);
 b.putInt(KEY_ANIM_TYPE, ANIM_SCALE_UP);
 b.putInt(KEY_ANIM_START_X, x);
 b.putInt(KEY_ANIM_START_Y, y);
 b.putInt(KEY_ANIM_WIDTH, constVlaue);
 b.putInt(KEY_ANIM_HEIGHT, constVlaue);
Context.startActivity(intent, b);

 好吧,虽然废话了一大把,但还是写出来作为一个记录,让自己以后养成查看源码的习惯,不要害怕,,,

猜你喜欢

转载自flycatdeng.iteye.com/blog/2211763
今日推荐