Hello stackoverflow
我正在尝试开发一个Android应用程序来播放我自己的GIF
,这里是代码片段
MainActivity.java
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
AnimationView.java
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Movie;
import android.util.AttributeSet;
import android.view.View;
public class AnimationView extends View {
private Movie mMovie;
private long mMovieStart;
private static final boolean DECODE_STREAM = true;
private int mDrawLeftPos;
private int mHeight, mWidth;
private static byte[] streamToBytes(InputStream is) {
ByteArrayOutputStream os = new ByteArrayOutputStream(1024);
byte[] buffer = new byte[1024];
int len;
try {
while ((len = is.read(buffer)) >= 0) {
os.write(buffer, 0, len);
}
} catch (java.io.IOException e) {
}
return os.toByteArray();
}
public AnimationView(Context context, AttributeSet attrs) {
super(context, attrs);
setFocusable(true);
java.io.InputStream is;
is = context.getResources().openRawResource(R.drawable.scanning);
if (DECODE_STREAM) {
mMovie = Movie.decodeStream(is);
} else {
byte[] array = streamToBytes(is);
mMovie = Movie.decodeByteArray(array, 0, array.length);
}
}
@Override
protected void onMeasure( int widthMeasureSpec, int heightMeasureSpec )
{
int p_top = this.getPaddingTop(), p_bottom = this.getPaddingBottom();
mWidth = mMovie.width();
mHeight = mMovie.height();
// Calculate new desired height
final int desiredHSpec = MeasureSpec.makeMeasureSpec( mHeight + p_top + p_bottom , MeasureSpec.EXACTLY );
setMeasuredDimension( widthMeasureSpec, desiredHSpec );
super.onMeasure( widthMeasureSpec, desiredHSpec );
// Update the draw left position
mDrawLeftPos = Math.max( ( this.getWidth() - mWidth ) / 2, 0) ;
}
@Override
public void onDraw(Canvas canvas) {
long now = android.os.SystemClock.uptimeMillis();
if (mMovieStart == 0) { // first time
mMovieStart = now;
}
if (mMovie != null) {
int dur = mMovie.duration();
if (dur == 0) {
dur = 3000;
}
int relTime = (int) ((now - mMovieStart) % dur);
// Log.d("", "real time :: " +relTime);
mMovie.setTime(relTime);
mMovie.draw(canvas, mDrawLeftPos, this.getPaddingTop());
invalidate();
}
}
}
main.xml中
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFFFFF"
android:orientation="vertical" >
<com.example.androidgifwork.AnimationView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true" />
</LinearLayout>
的Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.androidgifwork"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:name="com.example.androidgifwork.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
当我运行上面的代码段时,GIF
根本没有运行,但当我删除android:targetSdkVersion="19"
GIF
时,请帮助我解决这个问题。
由于
答案 0 :(得分:53)
2017更新的答案
要在Android中使用GIF,请使用Glide库加载任何图片或GIF。
Glide.with(context)
.load(YOUR_GIF)
.into(YOUR_IMAGE_VIEW);
使用 Glide 从服务器加载普通图像,图像,甚至加载GIF。另请查看Picasso android图片加载库,类似于 Glide ,但截至目前( 2017年4月16日)毕加索不支持<在Android中加载strong> GIF 。
############################################### #######################
OLD ANSWER
对于想要在您的应用中播放GIF的所有人,请找到以下代码
的 PlayGifView.java 强>
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Movie;
import android.os.Build;
import android.util.AttributeSet;
import android.view.View;
public class PlayGifView extends View{
private static final int DEFAULT_MOVIEW_DURATION = 1000;
private int mMovieResourceId;
private Movie mMovie;
private long mMovieStart = 0;
private int mCurrentAnimationTime = 0;
@SuppressLint("NewApi")
public PlayGifView(Context context, AttributeSet attrs) {
super(context, attrs);
/**
* Starting from HONEYCOMB have to turn off HardWare acceleration to draw
* Movie on Canvas.
*/
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
}
public void setImageResource(int mvId){
this.mMovieResourceId = mvId;
mMovie = Movie.decodeStream(getResources().openRawResource(mMovieResourceId));
requestLayout();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if(mMovie != null){
setMeasuredDimension(mMovie.width(), mMovie.height());
}else{
setMeasuredDimension(getSuggestedMinimumWidth(), getSuggestedMinimumHeight());
}
}
@Override
protected void onDraw(Canvas canvas) {
if (mMovie != null){
updateAnimtionTime();
drawGif(canvas);
invalidate();
}else{
drawGif(canvas);
}
}
private void updateAnimtionTime() {
long now = android.os.SystemClock.uptimeMillis();
if (mMovieStart == 0) {
mMovieStart = now;
}
int dur = mMovie.duration();
if (dur == 0) {
dur = DEFAULT_MOVIEW_DURATION;
}
mCurrentAnimationTime = (int) ((now - mMovieStart) % dur);
}
private void drawGif(Canvas canvas) {
mMovie.setTime(mCurrentAnimationTime);
mMovie.draw(canvas, 0, 0);
canvas.restore();
}
}
在您的活动类中,使用以下代码播放GIF
PlayGifView pGif = (PlayGifView) findViewById(R.id.viewGif);
pGif.setImageResource(<Your GIF file name Eg: R.drawable.infinity_gif>);
XML布局
<yourPacckageName.PlayGifView
android:id="@+id/viewGif"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
答案 1 :(得分:5)
使用Glide将项目的raw
文件夹或外部网址中的任何gif加载到ImageView, ImageButtons
或类似的[Glide targets][2]
Glide.with(getActivity()).load(R.raw.alarm).asGif().into(btnAlert);
答案 2 :(得分:1)
如果您可以使用WebView,GIF将直接在其上播放。但我不确定,在您的情况下是否要将其放入Webview中。
答案 3 :(得分:1)
这是旧的我知道,但在这里,您可以使用WebView,创建一个将播放gif并在webview中传递URL的html,它将像魅力一样工作。
答案 4 :(得分:0)
Android提供了android.graphics.Movie类。该类能够解码和播放InputStream。因此,对于这种方法,我们创建了一个类GifMovieView并让它从View继承,详细的教程在http://droid-blog.net/2011/10/14/tutorial-how-to-use-animated-gifs-in-android-part-1/
给出答案 5 :(得分:0)
源代码 https://drive.google.com/open?id=0BzBKpZ4nzNzUZy1BVlZSbExvYUU
** android:hardwareAccelerated =&#34; false&#34;在清单文件**
package com.keshav.gifimageexampleworking;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
public class MainActivity extends AppCompatActivity
{
private GifImageView gifImageView;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
gifImageView = (GifImageView) findViewById(R.id.GifImageView);
gifImageView.setGifImageResource(R.drawable.success1);
}
@Override
protected void onResume()
{
super.onResume();
//refresh long-time task in background thread
new Thread(new Runnable() {
@Override
public void run() {
try {
//dummy delay for 2 second
Thread.sleep(8000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//update ui on UI thread
runOnUiThread(new Runnable() {
@Override
public void run() {
gifImageView.setGifImageResource(R.drawable.success);
}
});
}
}).start();
}
}
package com.keshav.gifimageexampleworking;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Movie;
import android.net.Uri;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import java.io.FileNotFoundException;
import java.io.InputStream;
public class GifImageView extends View {
private InputStream mInputStream;
private Movie mMovie;
private int mWidth, mHeight;
private long mStart;
private Context mContext;
public GifImageView(Context context) {
super(context);
this.mContext = context;
}
public GifImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public GifImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.mContext = context;
if (attrs.getAttributeName(1).equals("background")) {
int id = Integer.parseInt(attrs.getAttributeValue(1).substring(1));
setGifImageResource(id);
}
}
private void init() {
setFocusable(true);
mMovie = Movie.decodeStream(mInputStream);
mWidth = mMovie.width();
mHeight = mMovie.height();
requestLayout();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(mWidth, mHeight);
}
@Override
protected void onDraw(Canvas canvas) {
long now = SystemClock.uptimeMillis();
if (mStart == 0) {
mStart = now;
}
if (mMovie != null) {
int duration = mMovie.duration();
if (duration == 0) {
duration = 1000;
}
int relTime = (int) ((now - mStart) % duration);
mMovie.setTime(relTime);
mMovie.draw(canvas, 10, 10);
invalidate();
}
}
public void setGifImageResource(int id) {
mInputStream = mContext.getResources().openRawResource(id);
init();
}
public void setGifImageUri(Uri uri) {
try {
mInputStream = mContext.getContentResolver().openInputStream(uri);
init();
} catch (FileNotFoundException e) {
Log.e("GIfImageView", "File not found");
}
}
}
答案 6 :(得分:0)
将此添加到您的依赖项(build.gradle)
allprojects {
repositories {
mavenCentral()
}
}
dependencies {
implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.15'
implementation 'com.google.android.gms:play-services-ads:18.1.1'
}
并在xml中使用它来显示您的gif
<pl.droidsonroids.gif.GifTextView
android:id="@+id/gifTextView2"
android:layout_width="230dp"
android:layout_height="200dp"
android:layout_weight="1"
android:background="@drawable/dev_option_gif"
/>
答案 7 :(得分:0)
对于运行API 29(Pie)及更高版本的设备,您可以使用AnimatedImageDrawable播放GIF和WebP动画图像。
这里是一个示例:
ImageView imgGif = findViewById(R.id.imgGif);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
try {
drawable = ImageDecoder.decodeDrawable(ImageDecoder.createSource(getResources(), R.drawable.giphy));
imgGif.setImageDrawable(drawable);
if (drawable instanceof AnimatedImageDrawable) {
((AnimatedImageDrawable) drawable).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
使用此选项可提供更多可用于图像的控件和功能,例如:
更改图像形状
还有很多more
答案 8 :(得分:0)
您还可以使用Coil库,该库比Glide对Gif图像的控制要少一些。但是,如果您只想加载一次GIF并显示,仍然可以提供简单的实现。可能的是,如果要重复该操作,则需要再次触发drawable或再次调用load函数。无论如何,即使再次调用负载,资源也应在后台缓存(有待调查的事情,而不是100%确定)。 Everything you need正在添加依赖项:
implementation "io.coil-kt:coil-gif:1.0.0"
并指定您的解码机制:
val imageLoader = ImageLoader.Builder(context)
.componentRegistry {
if (SDK_INT >= 28) {
add(ImageDecoderDecoder())
} else {
add(GifDecoder())
}
}
.build()
这完全可以直接在图像视图中加载图像/ gif:
app_logo.load("needed_gif_url")
别忘了,将所需的图像加载器传递给每个需要使用解码器的请求,例如GIF。或者只是将您的自定义imageLoader设置为每个请求的默认值:
Coil.setImageLoader(imageLoader)