Issue
I want to make a rolling dice app with short rolling animations consisting of images. I have created 100 JPG images for each of 20 possible results (the dice is d20). The thing is that I cannot know exact filenames of the needed files after the throw, as it is random. So I cannot use setImageResource
, as I need exact filename for it.
I decided to try using assets, as I can choose .getString
there instead of exact filename (all JPGs are named in format d20+result number+number of animation frame). The app works seemingly fine, but pictures on the screen do not change until all is over, and then only last image of animation appears and in smaller format that it should be.
Could anyone point on my mistake?
Here is the code:
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);
}
}
}
And resources (from where I get filename string):
<resources>
<string name="app_name">D20dice</string>
<string name="fileName">""d20%1$02d%2$03d".jpg"</string>
</resources>
I found out how to make it without assets, just with regular resources through getResources().getIdentifier(). With it I can find resource ID with string variable. There is a new code for Throw hereunder:
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);
}
}
But still the same, it shows only first and last picture (but last picture at least in the proper size now).
I`ve tried AnimationDrawable: now for the first throw I see the first and the last frame only again, and on the second throw application crashes. Here is this code:
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();
}
Solution
The problem probably was in that I initially set the background with setImageResource, and then loaded animation into the background (setBackground (diceAnimation)). But even after the problem had been solved, animation was played after a long delay before the start. it seems, that for AnimationDrawble 100 frames 320x240 is too much. I finally solved the problem by transforming all the animations into GIF and outputting them via the connected android-gif-drawable: https://github.com/koral--/android-gif-drawable
Answered By - i-Shadow
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.