推广 热搜: 公司  快速  中国  企业  上海  未来    政策  系统  公司2 

incallui android,Android M InCallUI动画简析手机动画「incallui android,Android M InCallUI动画简析」

   日期:2025-02-17     作者:2kgazl    caijiyuan   评论:0    移动:http://www78564.xrbh.cn/mobile/news/34519.html
核心提示:本篇回答下面几个问题:1. 显示动画的流程是怎样的?2. 为什么有些手机的动画不一样甚至没有动画?写这一篇主

本篇回答下面几个问题

1. 显示动画的流程是怎样的

2. 为什么有些手机的动画不一样甚至没有动画

写这一篇主要用两个原因:

1. 发现Android M上新增了一个类CircularRevealFragment.java,那么新的东西就想看看它是干什么的

2. 我手机上没有打电话的动画

代码中两处动画,一处是InCallActivity显示动画,就是那个由一个点展开的动画,另一个是CallCard的动画,就是由下方升到上方的动画。

InCallActivity启动动画

在InCallActivity.java的internalResolveIntent()方法内(这个方法接收处理intent,必走),跳至 CircularRevealFragment.java

touchPoint即动画展开的那个点。可以看到这个touchPoint有两个取值的地方,这个有点类似于双保险,TouchPointManager中getPoint()取出来的值是点击的时候就保存到TouchPointManager中的,而(Point) extras.getParcelable(TouchPointManager.TOUCH_POINT);是在构造拨号的intent的时候存进去的

Point touchPoint = null;

if (TouchPointManager.getInstance().hasValidPoint()) {

// Use the most immediate touch point in the InCallUi if available

touchPoint = TouchPointManager.getInstance().getPoint();

} else {

// Otherwise retrieve the touch point from the call intent

if (call != null) {

touchPoint = (Point) extras.getParcelable(TouchPointManager.TOUCH_POINT);

}

}

// Start animation for new outgoing call

CircularRevealFragment.startCircularReveal(getFragmentManager(), touchPoint,

InCallPresenter.getInstance());

touchPoint每次点击的时候都应当set一次,举个DialtacsActivity.java里的例子,当然还有其他地方设置(能点的地方就应该设置一次)

@Override

public boolean dispatchTouchEvent(MotionEvent ev) {

if (ev.getAction() == MotionEvent.ACTION_DOWN) {

TouchPointManager.getInstance().setPoint((int) ev.getRawX(), (int) ev.getRawY());

}

return super.dispatchTouchEvent(ev);

}

CircularRevealFragment.java新增类

public static void startCircularReveal(FragmentManager fm, Point touchPoint,

onCircularRevealCompleteListener listener) {

if (fm.findFragmentByTag(TAG) == null) {

fm.beginTransaction().add(R.id.main,

new CircularRevealFragment(touchPoint, listener), TAG)

.commitAllowingStateLoss();

} else {

Log.w(TAG, "An instance of CircularRevealFragment already exists");

}

}

然后在 CircularRevealFragment.java的onResume()方法内

@Override

public void onResume() {

super.onResume();

if (!mAnimationStarted) {

// only run the animation once for each instance of the fragment

startOutgoingAnimation(InCallPresenter.getInstance().getThemeColors());//带了一个 ThemeColors展开动画

}

mAnimationStarted = true;

}

这里观察到一个现象,插卡和不插卡通话背景是不同的,双卡手机上两张卡拨打出去的动画背景可能也是不同的,就是因为上面的getThemeColors()返回的值也就是颜色不同。返回值的来源不具体跟了,设置这个颜色的地方在Settings>Sim Card 设置页点开sim卡有个颜色选择,背景色就是这里的颜色。

下面的方法新建动画并启动动画

public void startOutgoingAnimation(MaterialPalette palette) {

//略过本次不关心的

view.getViewTreeObserver().addonPreDrawListener(new onPreDrawListener() {

@Override

public boolean onPreDraw() {

final ViewTreeObserver vto = view.getViewTreeObserver();

if (vto.isAlive()) {

vto.removeonPreDrawListener(this);

}

final Animator animator = getRevealAnimator(mTouchPoint);//获得动画

animator.addListener(new AnimatorListenerAdapter() {

@Override

public void onAnimationEnd(Animator animation) {

view.setClipToOutline(false);

if (mListener != null) {

android.util.Log.i(TAG, "onAnimationEnd: animation a");

mListener.onCircularRevealComplete(getFragmentManager());//动画结束后调

}

}

});

android.util.Log.i(TAG, "onPreDraw: animation 3");

animator.start();//动画开始了

return false;

}

});

}

好的诸位下面就是动画生成的地方,注意动画类型,这里携带了touchPoint

private Animator getRevealAnimator(Point touchPoint) {

final Activity activity = getActivity();

final View view = activity.getWindow().getDecorView();

final Display display = activity.getWindowManager().getDefaultDisplay();

final Point size = new Point();

display.getSize(size);

int startX = size.x / 2;

int startY = size.y / 2;

if (touchPoint != null) {

startX = touchPoint.x;

startY = touchPoint.y;

}

final Animator valueAnimator = ViewAnimationUtils.createCircularReveal(view,

startX, startY, 0, Math.max(size.x, size.y));

valueAnimator.setDuration(getResources().getInteger(R.integer.reveal_animation_duration));//设置动画时长

return valueAnimator;

}

好的InCallActivity的动画显示完以后,下面接着CallCardFragment的动画。

CallCard动画

在动画执行完InCallActivity的启动动画以后,通过mListener.onCircularRevealComplete(getFragmentManager());调用CallCardFragement.java中的 animateForNewOutgoingCall()

InCallPresenter.java

public void onCircularRevealComplete(FragmentManager fm) {

if (mInCallActivity != null) {

mInCallActivity.showCallCardFragment(true);//显示CallCard

mInCallActivity.getCallCardFragment().animateForNewOutgoingCall();//CallCardFragment中显示动画

CircularRevealFragment.endCircularReveal(mInCallActivity.getFragmentManager());

}

}

CallCardFragment.java

关注一下动画类型

@Override

public void animateForNewOutgoingCall() {

//略过本次不关心的

observer.addonGlobalLayoutListener(new onGlobalLayoutListener() {

@Override

public void onGlobalLayout() {

//略过本次不关心的

final Animator animator = getShrinkAnimator(parent.getHeight(), originalHeight);//注意动画类型

animator.addListener(new AnimatorListenerAdapter() {

@Override

public void onAnimationEnd(Animator animation) {

mPrimaryCallCardContainer.setTag(R.id.view_tag_callcard_actual_height,

null);

setViewStatePostAnimation(listener);

mIsAnimating = false;

InCallPresenter.getInstance().onShrinkAnimationComplete();//动画结束后

}

});

animator.start();//开始动画

}

});

}

getShrinkAnimator()动画生成

private Animator getShrinkAnimator(int startHeight, int endHeight) {

final ObjectAnimator shrinkAnimator =

ObjectAnimator.ofInt(mPrimaryCallCardContainer, "bottom", startHeight, endHeight);

shrinkAnimator.setDuration(mShrinkAnimationDuration);//设置动画时长

shrinkAnimator.addListener(new AnimatorListenerAdapter() {

@Override

public void onAnimationStart(Animator animation) {

mFloatingActionButton.setEnabled(true);

}

});

shrinkAnimator.setInterpolator(AnimUtils.EASE_IN);

return shrinkAnimator;

}

动画时长来源

mShrinkAnimationDuration = getResources().getInteger(R.integer.shrink_animation_duration);

好了现在我们回头看看文章开头的两个问题是否得到了解答。

前面的流程基本上就是动画生成,设置属性,显示动画的流程

非要话个图的话大概就是下面这样

0818b9ca8b590ca3270a3433284dd417.png

如果我们把Android M上的动画代码跟Android L上的代码做对比的话会发现,Android L也有这两个类型的动画,都在CallCardFragment.java里,通过mAnimatorSet.playSequentially(revealAnimator, shrinkAnimator);顺序播放两个动画。

第二个问题的答案貌似还不明显,为什么有些手机的动画不一样

我们观察到的不同有两点:1.背景颜色不同,2.有些似乎没有动画。

第1点不重点解答,上文也提到过颜色取值自SIM卡设置里面选择的颜色,而且颜色不同起码有动画嘛

第2点有又两种情况:1)没用动画;2)动画时间极短,以至于看起来像没有动画。

注意到两次设置动画时间的代码分别是

//InCallActivity或者说叫CircularRevealFragment

valueAnimator.setDuration(getResources().getInteger(R.integer.reveal_animation_duration));

//CallCardFragment

mShrinkAnimationDuration = getResources().getInteger(R.integer.shrink_animation_duration);

那么这两个值的来源呢?

0818b9ca8b590ca3270a3433284dd417.png

从上图中可以看到,这个动画时长默认是333ms的,但是在有些配置文件里面是1,而且都改成了1!从他们所在的文件夹可以看到,这个配置是针对中国移动sim卡的修改(mcc mnc 匹配到中国移动),难道是针对中国移动定制机的修改?苦了我刷CM系统的人们(AOSP没这个配置)。

是哪个家伙做了这样的修改(黑线脸)

0818b9ca8b590ca3270a3433284dd417.png

提交者就不贴出来了,他针对中国移动新增了这4个文件配置动画时长。。

本文地址:http://www78564.xrbh.cn/news/34519.html    迅博思语 http://www78564.xrbh.cn/ , 查看更多

特别提示:本信息由相关用户自行提供,真实性未证实,仅供参考。请谨慎采用,风险自负。

 
 
更多>同类最新资讯
0相关评论

文章列表
相关文章
最新动态
推荐图文
最新资讯
点击排行
网站首页  |  二维码  |  关于我们  |  联系方式  |  使用协议  |  版权隐私  |  网站地图  |  排名推广  |  广告服务  |  积分换礼  |  网站留言  |  RSS订阅  |  违规举报  |  粤ICP备2023022329号