当前位置: 代码迷 >> Android >> 点击打开进去应用的动画(点击非Android View)
  详细解决方案

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

热度:90   发布时间:2016-04-28 00:57:30.0
点击打开进入应用的动画(点击非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);

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

?

  相关解决方案