Android Animation实现元素在屏幕上按照指定轨迹运动,以及出现NullPointerException的解决方案
因项目需要,在Android中实现了一个动画,当在Activity中点击特定按钮时,会在屏幕上添加一个ImageView,并按照指定的起点、终点,沿着特定的轨迹运动(例如直线)。
实现方法
实现思路是在Activity的DecorView中添加一个FrameLayout,然后在FrameLayout中添加ImageView,可通过Margin参数指定ImageView的起始位置。然后设置ImageView的动画,使其能运动到终点。当动画结束后,移除FrameLayout。
核心代码如下。项目GitHub链接 https://github.com/jzj1993/AnimationCrash
public static boolean startAnim(Activity activity, int fromX, int toX, int fromY, int toY) {
try {
final ImageView img = new ImageView(activity);
img.setImageResource(R.mipmap.ic_launcher);
final FrameLayout tempLayout = new FrameLayout(activity);
final FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
lp.setMargins(fromX, fromY, 0, 0);
tempLayout.addView(img, lp);
final ViewGroup container = (ViewGroup) activity.getWindow().getDecorView();
container.addView(tempLayout, new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
final Animation anim = new TranslateAnimation(0, toX - fromX, 0, toY - fromY);
anim.setDuration(500);
anim.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
container.removeView(tempLayout);
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
img.startAnimation(anim);
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
错误描述
在大部分安卓手机上运行正常,但是在部分Android 4.0.x系统中(例如Nexus S Android 4.0.3模拟器),如果连续同时执行多个动画,可能会出现NullPointerException,如下:
com.jzj1993.anim E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.NullPointerException
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2488)
at android.view.View.draw(View.java:10981)
at android.widget.FrameLayout.draw(FrameLayout.java:450)
at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:2126)
at android.view.ViewRootImpl.draw(ViewRootImpl.java:2026)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1634)
at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2442)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4424)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
at dalvik.system.NativeStart.main(Native Method)
解决方法
将以下代码
@Override
public void onAnimationEnd(Animation animation) {
container.removeView(tempLayout);
}
改为:
@Override
public void onAnimationEnd(Animation animation) {
container.post(new Runnable() {
@Override
public void run() {
container.removeView(tempLayout);
}
});
}
原因分析
以下是官方给出的ViewGroup.removeView方法的JavaDoc注释:
public void removeView (View view)
Added in API level 1
Note: do not invoke this method from draw(android.graphics.Canvas), onDraw(android.graphics.Canvas), dispatchDraw(android.graphics.Canvas) or any related method.
猜测在同时执行多个动画时,前一个动画的onAnimationEnd被回调时,后一个动画正在执行,因此DecorView的onDraw方法在执行,可能会导致DecorView.onDraw执行时,onAnimationEnd回调中的DecorView.removeView方法被调用,从而导致错误。没有具体深入的去分析源码,但是经过验证问题确实解决了。
Android Animation实现元素在屏幕上按照指定轨迹运动,以及出现NullPointerException的解决方案相关推荐
- android滑屏轨迹运动,Android Animation实现元素在屏幕上按照指定轨迹运动,以及出现NullPointerException的解决方案...
因项目需要,在Android中实现了一个动画,当在Activity中点击特定按钮时,会在屏幕上添加一个ImageView,并按照指定的起点.终点,沿着特定的轨迹运动(例如直线). 实现方法 实现思路是 ...
- python获取网页元素坐标_html网页元素在屏幕上的坐标获取
今天在用python调用IE获取html网页元素在屏幕上的坐标,当然为了截图啦,(*^__^*) 嘻嘻-- xtop=ie.document.forms[i].elements[j].getBound ...
- Linux 命令之 tail -- 在屏幕上显示指定文件的末尾若干行/显示文件尾部内容/查看文件尾部内容
文章目录 一.命令介绍 二.常用选项 三.参考示例 (一)显示文件 file 的最后 10 行 (二)显示文件 file 的内容,从第 20 行至文件末尾 (三)显示文件file的最后10个字符 (四 ...
- android广播内容显示在屏幕上,在Android本机来电屏幕上弹出窗口,例如真正的来电者Android应用...
我也在努力(在这里理解你可能是错误的).您想要实现的是在Android 4.2(Jelly Bean)中显示该活动.我只是延迟显示活动.我在其他类中使用过PhoneStateListener.我可以在 ...
- thinkpad卡在logo界面_由于win7系统启动卡在Thinkpad LOGO屏幕上而导致无法进入系统的三种解决方案...
最近联想平板卡在主界面,一个Win7 pure版本系统的用户报告说,在打开计算机电源时,发现它卡在了Thinkpad引导LOGO屏幕上,并且无法正常进入系统桌面. win7系统卡在徽标界面上的原因有很 ...
- android广播内容显示在屏幕上,如何将手机屏幕投影到计算机显示器上?
该屏幕广播应用程序摆脱了电缆的束缚,可以将手机的内容投影到电视中的空白空间,以便您可以在电视侧更好地欣赏自己喜欢的视频和图片. 一方面,它用于工作,另一方面,用于家庭生活和娱乐. 实际上,有时无法很好 ...
- android中可以有两个焦点吗,android – 如何通过焦点在屏幕上调整两个片段的大小?...
我有三个片段,前两个填充80%的屏幕,最后一个填充其余的片段(这个片段永远不会改变大小).我希望,在用户(焦点)输入片段后,调整片段的大小,使其填满屏幕的70%(将10%留给另一个).像这样: 可以通 ...
- Android:设计一个在屏幕上移动的小球程序
目录 1.要求 2.结构 3.设计步骤 4.实现效果 1.要求 设计一个自定义组件继承于Android.view.View的图形绘制类TestView,在该视图组件中绘制一个小球:再设计一个实现监听触 ...
- Android 使用 ADB 命令录制屏幕上的视频
ADB 录制使用使用到的 screenrecord 顺便提一下截图使用的是screencap 关于截图可以看这篇文章,点击可以查看 首先需要我们确保adb devices 输入有显示内容 然后在终端 ...
最新文章
- 关于Silverlight安装问题之二
- curl命令的超时时间
- 服务器于本地间进行复制粘贴
- mysql自动dump脚本_MySQL--简单mysqldump脚本
- 【Task5(2天)】模型调参
- linux显示mem进行排序,Linux查看系统负载(CPU和MEM考虑)
- Hashtable、HashMap、TreeMap总结
- 苹果CMSV10绿色毛毛虫主题模板
- freemaker转word xml注意事项
- Golang 删除切片指定元素
- Python yaml模块
- SSH dao层异常 org.hibernate.HibernateException: No Session found for current thread
- iOS手势的传递问题
- python入门到精通 _6文件读写
- execute immediate
- ETR290规范的理解
- Python小白逆袭大神-结营心得-alading
- 【多线程基础】 保证线程安全的总结
- TextField及富文本框的用法
- (java版)删除重复值阿伟学长在开发一款游戏, 他希望玩家已经获得的道具会降低爆率, 避免玩家获得太多重复的道具但玩家背包中道具是乱序且不确定的, 为了减小判断的运算量, 需要先对数据进行去重.
热门文章
- 使用windows server backup备份还原hyper-v 3.0虚拟机
- shell编程中特殊字符的问题总结
- java hasmoreelements_Java IOException.hasMoreElements方法代码示例
- Java31 gt gt gt 2_Java Template.binding方法代碼示例
- honeywell新风系统控制面板说明_新风系统——不开窗也能清新呼吸
- Kate and imperfection CodeForces - 1333F(思维+数学)
- [蓝桥杯][算法提高VIP]数的划分(记忆化搜索)
- 173. 二叉搜索树迭代器(二叉搜索树+栈)
- Interesting Array CodeForces - 483D(思维+线段树)
- Ciel and Robot CodeForces - 322C