如何在Android中播放GIF

uqcuzwp8  于 2023-02-06  发布在  Android
关注(0)|答案(9)|浏览(165)

你好stackoverflow我正在尝试开发一个android应用程序来播放我自己的GIF,这里是代码片段

    • 主要活动. java**
public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
}
}
    • 动画视图. 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();
    }
}
}
    • 主文件. 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>
    • 清单. 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运行,请帮助我解决这个谜.
谢谢

ryoqjall

ryoqjall1#

    • 2017年更新答案**

要在Android中播放GIF,请使用Glide库加载任何图像或GIF。

Glide.with(context)
.load(YOUR_GIF)
.into(YOUR_IMAGE_VIEW);

使用Glide可以加载普通图像、服务器图像甚至GIF。另外,还可以查看Picasso android图像加载库,该库类似于Glide,但截至目前(2017年4月16日)Picasso尚不支持在android中加载GIF

######################################################################

    • 旧答案**
  • 对于所有想在应用程序中播放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" />
6l7fqoea

6l7fqoea2#

使用Glide将项目raw文件夹或外部URL中的任何gif加载到ImageView, ImageButtons或类似的[Glide targets][2]

Glide.with(getActivity()).load(R.raw.alarm).asGif().into(btnAlert);
fae0ux8s

fae0ux8s3#

如果你可以使用WebView,GIF将直接在它上面播放。但是我不确定,在你的情况下,你是否想把它放在WebView中。

2w2cym1i

2w2cym1i4#

将此添加到您的依赖项(build.gradle)

allprojects {
    repositories {
        mavenCentral()
    }
}
dependencies {
    implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.15'
}

在xml中使用它来显示你的gif

<pl.droidsonroids.gif.GifTextView
                    android:id="@+id/gifTextView2"
                    android:layout_width="230dp"
                    android:layout_height="200dp"
                    android:layout_weight="1"
                    android:src="@drawable/dev_option_gif"
                    />

更多信息请访问:https://github.com/koral--/android-gif-drawable

bxfogqkk

bxfogqkk5#

Android提供了android.graphics.Movie类,这个类能够解码和播放InputStreams,所以对于这种方法,我们创建了一个类GifMovieView,让它继承View,详细教程在http://droid-blog.net/2011/10/14/tutorial-how-to-use-animated-gifs-in-android-part-1/

a6b3iqyw

a6b3iqyw6#

源代码https://drive.google.com/open?id=0BzBKpZ4nzNzUZy1BVlZSbExvYUU
android:清单文件中硬件加速=“false”

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");
        }
    }
}
rseugnpd

rseugnpd7#

对于运行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();
        }
    }

使用此选项可提供更多可用于图像的控制和功能,例如:

  • 检查gif是否正在运行
  • 开始和停止播放。
  • 应用颜色过滤器
  • 更改图像形状

以及更多

7dl7o3gd

7dl7o3gd8#

你也可以使用Coil库,它对GIF图像的控制比Glide要少一些,但如果你只想加载一次GIF并显示,它仍然提供了简单的实现。如果你想重复这个过程,你需要再次触发drawable或者只是再次调用load函数。无论如何,即使再次调用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)
e7arh2l6

e7arh2l69#

Android中的动画GIF是一个很难的主题。这是一个已经被大量讨论过的问题,开发人员仍然很难将GIF赋予生命。使用glidepl.droidsonroids.gif:android-gif-drawable在构建gradle时遇到了一些问题。所以我找到了一个不使用任何依赖项的方法。我使用这个方法在我的视图中加载GIF:

动画图片.java:

package com.app.samplegif;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Movie;
import android.graphics.Paint;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.view.View;

import com.app.samplegif.R;

import java.io.IOException;
import java.io.InputStream;

@SuppressLint("NewApi")
public class GifAnimView extends View {
    private Context _context;
    private  Movie gifMovie;
    private String gifName = "not set";
    private InputStream gifStream;

    private int width;
    private int height;

    private long startTime;
private Paint paint;

public GifAnimView(Context context, AttributeSet attrs) {
    super(context,attrs);
    initGif(context,attrs);
    _context = context;
 }

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    if (gifStream == null || gifMovie == null) {
        canvas.drawColor(Color.WHITE);
        canvas.drawText(gifName,width/2, height /2,paint);
        return;
    }
    long now = SystemClock.uptimeMillis();
    int relTime = (int) ((now - startTime) % gifMovie.duration());
    gifMovie.setTime(relTime);
    gifMovie.draw(canvas, 0, 0);
    this.invalidate();
}

private void initGif(Context context, AttributeSet attrs) {
    TypedArray a = context.obtainStyledAttributes(attrs,
            R.styleable.GifAnimView, 0, 0);
            gifName = a.getString(R.styleable.GifAnimView_gifSrc);

    try {
        gifStream =context.getAssets().open(gifName);
        gifMovie = Movie.decodeStream(gifStream);
        startTime = SystemClock.uptimeMillis();
    } catch (IOException e) {
        e.printStackTrace();
    }

    paint = new Paint();
    paint.setTextSize(40);
    paint.setTextAlign(Paint.Align.CENTER);
    paint.setStyle(Paint.Style.FILL);
    a.recycle();
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    this.width = w;
    this.height = h;
    super.onSizeChanged(w, h, oldw, oldh);
}  

}

res/values文件夹中创建attrs.xml

<?xml version="1.0" encoding="utf-8"?>
  <resources>
    <declare-styleable name="GifAnimView">
        <attr name="gifSrc" format="string" localization="suggested" />
    </declare-styleable>
  </resources>

your.gif文件复制到src/main/assets/文件夹中
**activity_main.xml:**您可以使用app:gifSrc属性作为assets文件夹中存在gif的名称。

// ....
 <com.app.samplegif.GifAnimView
    android:id="@+id/gif_view"
    android:layout_width="200dp"
    android:layout_height="200dp"
    android:layout_marginLeft="30dp"
    android:layout_marginTop="20dp"
    app:gifSrc="your.gif" />

 // ....

相关问题