大纲
主要想实现的是在一个页面中播放一个动画、就像突然洒金币的效果。
我想要的效果是一个activity覆盖一个activity,并透明。
本文章主要讲如何在动画activity中播放gif动画:(第一种需要把gif转换成一帧一帧的格式,后两种方式是需要把gif--转换成mp4)
- 通过逐帧动画
- 内存泄漏、heap size 常识大小 -xms -xmx
- 通过webview播放
为了效果更好,应该对webview进行以下处理:- webview背景透明
- webview右下角缩放按钮
- webview隐藏滚动条
- 屏幕单机、双击放大、滑动无响应事件
- 定时销毁动画activity
- webview屏幕适配
- 通过videoview播放(将gif--mp4)
- 自定义videoview 让播放布满整个屏幕
- videoview隐藏进度条
- videoview播放本地文件 获取res/raw的绝对地址
- 通过surfaceview播放(将gif--mp4)
- 学习地址:点这里
- 通过glide开源库直接播放gif 自行查阅
通过逐帧动画
首先了解:android动画分类
逐帧播放应该是最简单的一种的,就是把连续的图片连起来播放,设置每帧的时间
有两种方式、一种是xml 一种是代码方式实现,
本例我选择代码方式,用一个imageview作为承载,
// 核心代码如下:
private AnimationDrawable anim;
private ImageView imageView;
private void init() {
LayoutInflater inflater= (LayoutInflater)
getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.red_packets_frame_animation_view_layout,this);
imageView=findViewById(R.id.imageView);
anim=new AnimationDrawable();
}
public void play_animation(){
for (int i=10;i<=15;i++){
int id=getResources().getIdentifier("a"+i,"drawable",getContext().getPackageName());
Drawable drawable=getResources().getDrawable(id);
anim.addFrame(drawable,100);//100ms
anim.setOneShot(true);//true 不循环播放
}
imageView.setImageDrawable(anim);
anim.stop();
anim.start();
}
但是这种方式真的很容易出oom!如果帧拆分的图片过多,尽量不要使用这种方式,另外补充一点,还有一种Movie类,也像帧播放一样,适用于播放一些小gif,自行了解。
还有提到的oom, 用heap工具可以看到占用内存过多泄漏,在这里简单了解一下常识,
-xms 初始heap size 一般为物理内存的1/64
-xmx 最大heap size 最大为物理内存的1/4
- JVM内存首先受限于实际的最大物理内存,(运行内存RAM 2\3\4G)
JVM初始分配的内存由-Xms指定,默认是物理内存的1/64;JVM最大分配的内存由-Xmx指定,默认是物理内存的1/4。默认空余堆内存 小于 40%时,JVM就会增大堆直到-Xmx的最大限制;空余堆内存大于70%时,JVM会减少堆直到-Xms的最小限制。因此服务器一般设置-Xms、 -Xmx相等以避免在每次GC 后调整堆的大小.
关于修改堆大小可以看看这篇文章
通过webview播放
在webview播放动画本来是非常简单的一件事,但是如想达到我们想要的效果要修改的地方还是很多的。
- webview背景透明
- webview右下角缩放按钮
- webview隐藏滚动条
- 屏幕单机、双击放大、滑动无响应事件
- 定时销毁动画activity (通过开启了一个新的线程,根据动画时间销毁activity)
- webview屏幕适配
//核心代码
public class AnimationActivity extends Activity {
private WebView webView;
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_animation2);
webView=findViewById(R.id.webview);
webView.setVerticalScrollBarEnabled(false); //垂直滚动条不显示
webView.setHorizontalScrollBarEnabled(false);//水平不显示
WebSettings webSettings=webView.getSettings();
webSettings.setDisplayZoomControls(false);//隐藏webview缩放按钮
webSettings.setJavaScriptEnabled(true);
webSettings.setUseWideViewPort(true);//屏幕适配:设置webview推荐使用的窗口,设置为true
webSettings.setLoadWithOverviewMode(true);//设置webview加载的页面的模式,也设置为true
webSettings.setAllowFileAccess(true);
webSettings.setSupportZoom(true);//是否支持缩放
webSettings.setBuiltInZoomControls(true);//添加对js功能的支持
webView.setWebViewClient(new WebViewClient());
webView.setBackgroundColor(0);
String gifPath = "file:///android_asset/animation.gif";
webView.loadUrl(gifPath);
handler=new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case 0:
webView.destroy();
AnimationActivity2.this.finish();
}
}
};
new Thread(){
@Override
public void run() {
long startTime = System.currentTimeMillis();
Log.i("test","System.currentTimeMillis()1:"+System.currentTimeMillis());
try {
this.currentThread().sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
Log.i("test","System.currentTimeMillis()2:"+System.currentTimeMillis());
if (endTime - startTime >4000){
//startTime = endTime;
Message message=new Message();
message.what=0;
handler.sendMessage(message);
}
}
} .start();
}
@Override
public void onBackPressed() {
super.onBackPressed();
webView.destroy();
finish();
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()){
case MotionEvent.ACTION_SCROLL:
return true;
case MotionEvent.ACTION_MOVE:
return true;
case MotionEvent.ACTION_POINTER_DOWN:
return true;
case MotionEvent.ACTION_MASK:
return true;
case MotionEvent.ACTION_DOWN:
return true;
default:
break;
}
return super.dispatchTouchEvent(ev);
}
}
记得设置activity透明,这样透明的gif的效果就浮现在另一个activity上,效果相对较好。
android:theme="@android:style/Theme.Translucent.NoTitleBar"
通过videoview播放
因为videoview有默认尺寸,而我们想实现全屏动画,需要改变它默认大小 所以要重写相对方法,获得全屏尺寸
private int screenWidth;
private int screenHeigh;
//提供一个接口 让activity传入尺寸
public void setMetrics(int width,int height){
screenWidth=width;
screenHeigh=height;
}
//重新绘制
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(screenWidth, screenHeigh);
}
//核心代码如下
public class AnimationActivity3 extends Activity {
private GifVideoView gifVideoView;
private MediaController mc;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_animation3);
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int width=dm.widthPixels;
int heigh=dm.heightPixels;
gifVideoView=findViewById(R.id.gifVideoView);
mc = new MediaController(this);
mc.setVisibility(View.INVISIBLE);
gifVideoView.setMetrics(width,heigh);
gifVideoView.setBackgroundColor(0);
gifVideoView.setMediaController(mc);
Uri uri=Uri.parse( "android.resource://"+getPackageName()+"/"+R.raw.test);
gifVideoView.setVideoURI(uri);
gifVideoView.start();
gifVideoView.requestFocus();
//视频编码格式不支持的情况
gifVideoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mediaPlayer, int what, int extra) {
if(what==MediaPlayer.MEDIA_ERROR_SERVER_DIED){
Log.v("view exception","Media Error,Server Died"+extra);
}else if(what==MediaPlayer.MEDIA_ERROR_UNKNOWN){
Log.v("video exception","Media Error,Error Unknown "+extra);
}
return true;
}
});
}
@Override
public void onBackPressed() {
super.onBackPressed();
finish();
}
}
小demo效果如图: