如何让android个图片资源(jpg)在Drawable中快速变化为一个短动画?

How to make android image assets (jpg) change fast in Drawable for a short animation?

我想制作一个带有由图像组成的简短滚动动画的掷骰子应用程序。我为 20 个可能的结果中的每一个创建了 100 张 JPG 图片(骰子是 d20)。问题是我无法知道抛出后所需文件的确切文件名,因为它是随机的。所以我不能使用 setImageResource,因为我需要它的确切文件名。

我决定尝试使用资产,因为我可以在那里选择 .getString 而不是确切的文件名(所有 JPG 的命名格式为 d20+结果编号+动画帧数)。该应用程序看似运行良好,但屏幕上的图片直到全部结束后才发生变化,然后只出现动画的最后一张图像,并且格式更小。

谁能指出我的错误?

代码如下:

import android.content.res.AssetManager;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ImageView;
import java.io.IOException;
import java.io.InputStream;
import java.util.Random;

public class MainActivity extends AppCompatActivity {



@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

}
public Random random = new Random();


public void Throw(View view) throws InterruptedException {
    ImageView dice = findViewById(R.id.imageD20);
    dice.setImageResource(R.drawable.d2002030);
    int result = random.nextInt(19); // throwing dice...
    long startTime = 0;
    long delayTime = 0;
    String fileNameStr = new String();


    for (int i = 0; i<=100; i++) {       // animation
        fileNameStr = getResources().getString(R.string.fileName, result, i + 1);
       InputStream img = null;
       AssetManager mngr = this.getAssets();
        try {
           InputStream ims = getAssets().open(fileNameStr);
           Drawable image = Drawable.createFromStream(ims, null);
           dice.setImageDrawable(image);
                      }
        catch(IOException ex) {
            ex.printStackTrace();
        }
        startTime = System.currentTimeMillis();
        delayTime = startTime+10;
        while(System.currentTimeMillis() < delayTime);
   }


}
}

和资源(从我获取文件名字符串的地方):

<resources>
<string name="app_name">D20dice</string>
<string name="fileName">""d20%1d%2d".jpg"</string>
</resources>

我通过 getResources().getIdentifier() 找到了如何在没有资产的情况下使用常规资源实现它。有了它,我可以找到带有字符串变量的资源 ID。下面有一个Throw的新代码:

 public void Throw(View view) throws InterruptedException {
    ImageView dice = findViewById(R.id.imageD20);
    dice.setImageResource(R.drawable.d2002030);
    int result = random.nextInt(19); // throwing dice...
    long startTime = 0;
    long delayTime = 0;
    String fileNameStr = new String();
    int resID;

    for (int i = 0; i<=100; i++) {       // animation

        fileNameStr = getResources().getString(R.string.fileName, result, i + 1);

        resID = getResources().getIdentifier(fileNameStr , "drawable", getPackageName());

        dice.setImageResource(resID);
        dice.invalidate();
        startTime = System.currentTimeMillis();
        delayTime = startTime+10;
        while(System.currentTimeMillis() < delayTime);
    }

}

但还是一样,它只显示第一张和最后一张图片(但最后一张图片至少现在大小合适)。

我已经尝试过 AnimationDrawable:现在对于第一次投掷,我只再次看到第一帧和最后一帧,而在第二次投掷时,应用程序崩溃了。这是这段代码:

 public void Throw(View view) throws InterruptedException {
    ImageView dice = findViewById(R.id.imageD20);
    dice.setImageResource(R.drawable.d2002030);
    int result = random.nextInt(19); // throwing dice...
    String fileNameStr = new String();
    Drawable frame;
    AnimationDrawable diceAnimation = new AnimationDrawable();
    diceAnimation.setOneShot(true);

    int resID;

    for (int i = 0; i<=100; i++) {       // animation

        fileNameStr = getResources().getString(R.string.fileName, result, i + 1);

        resID = getResources().getIdentifier(fileNameStr , "drawable", getPackageName());
        frame = getResources().getDrawable(resID);
        diceAnimation.addFrame(frame, 200);
         }


    dice.setBackground(diceAnimation);
    diceAnimation.start();


}

问题可能出在我最初使用setImageResource设置背景,然后将动画加载到背景中(setBackground(diceAnimation))。但是即使问题已经解决了,动画还是在开始前延迟了很长时间才开始播放。看起来,对于 AnimationDrawble 100 帧 320x240 来说太多了。我终于解决了这个问题,将所有动画转换成GIF并通过连接输出它们 android-gif-drawable: https://github.com/koral--/android-gif-drawable