Displaying a sequence of images with a time delay - android

I wanted to display 9 images one after the other. I have included the 9 images as an array:
imageHolders = new ArrayList<ImageView>();
imageHolders.add((ImageView) view.findViewById(R.id.imgOne));
imageHolders.add((ImageView) view.findViewById(R.id.imgTwo));
imageHolders.add((ImageView) view.findViewById(R.id.imgThree));
imageHolders.add((ImageView) view.findViewById(R.id.imgFour));
imageHolders.add((ImageView) view.findViewById(R.id.imgFive));
imageHolders.add((ImageView) view.findViewById(R.id.imgSix));
imageHolders.add((ImageView) view.findViewById(R.id.imgSeven));
imageHolders.add((ImageView) view.findViewById(R.id.imgEight));
imageHolders.add((ImageView) view.findViewById(R.id.imgNine));
This is what I have tried:
public void handleMessage(Message msg) {
int currentImage = 0;
int nextImage = 0;
// Logic to change the images
for (final ImageView imageView : imageHolders) {
currentImage = Integer.parseInt(imageView.getTag().toString());
if (currentImage > 1) {
nextImage = currentImage - 1;
} else {
nextImage = 9;
}
imageView.setTag(""+nextImage);
new CountDownTimer(10000, 1000) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
imageView.setVisibility(VISIBLE);
}
}.start();
}
super.handleMessage(msg);
}
}
There is a delay between the first and the second images. I am not able to introduce a delay between the rest. I have no clue about introducing the delay. Any suggestions would be appreciated.

you could just use AnimationDrawable which does this for you , and allows you to set a duration of time (in milliseconds) using android:duration attribute .

The AnimationDrawable is probably the best answer, but for another solution you can look at AsyncTask.
http://developer.android.com/reference/android/os/AsyncTask.html
Then, you can in the background just sleep for some set amount of time, then display the next image.
You may want an event though to handle when this task is done, and in the listener you call the next one.

If you want to make just a simple static animation (all images at the same position) you can use AnimationDrawable but you can't easly change it dynamically - like change speed or something.
I just wrote a simple class for this so I can set multiple animations for one ImageView and change speed.
public class ImageSequence extends ImageView {
ArrayList<Drawable> draws = new ArrayList<Drawable>();
ArrayList<Integer> bnds = new ArrayList<Integer>(); //bounds of sequences - index of first and last frame.
ArrayList<String> names = new ArrayList<String>(); //sequences names.
Timer timer = new Timer(true);
TimerTask task;
int p = -1; //current playback position.
int cS = -1; //current sequence.
public ImageSequence(Context context) {
super(context);
createTask();
}
public void addSequence(String name, int[] res){
names.add(name);
bnds.add(draws.size());
bnds.add(draws.size() + res.length - 1);
for (int i = 0; i < res.length; i++){
draws.add(getContext().getResources().getDrawable(res[i]));
}
}
public void play(String sequence, float speed){
cS = -1;
for(int i = 0; i < names.size(); i++){
if(names.get(i) == sequence){ cS = i; break;}
}
if(cS<0) return;
p = -1;
task.run();
task.cancel();
if(speed <= 0) return;
createTask();
timer.schedule(task, (long) (1000/speed), (long) (1000/speed));
}
public void stop(){
task.cancel();
}
public void cancelTimer(){
timer.cancel();
}
private void createTask() {
task = new TimerTask(){
public void run() {
p++;
mHandler.obtainMessage(1).sendToTarget();
}
};
}
public Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
int l = p;
if(l > bnds.get(cS*2+1) || l < bnds.get(cS*2)) l = bnds.get(cS*2);
p = l;
ImageSequence.this.setImageDrawable(draws.get(l));
}
};
}
From outside you can use it like this:
seq.addSequence("orange", new int[]{R.drawable.ic_oval_diode_orange, R.drawable.ic_oval_diode_off});
seq.addSequence("green", new int[]{R.drawable.ic_oval_diode_green, R.drawable.ic_oval_diode_off});
seq.addSequence("red", new int[]{R.drawable.ic_oval_diode_red, R.drawable.ic_oval_diode_off});
seq.play("red", 4);
I'm not really experienced in Android and Java but it works and it do the job for me. Hope it will help someone.

Related

Why is game over screen lagging?

I have done a game in Android Studio with the goal of avoiding falling objects.
Generally the app is running good, but for some reason when i get to the game over screen and press an edittext to add highscore the game experience a lot of stutter and lag (with the keyboard und keypresses).
I have already called finish() (which can be seen in "FishView") on my main activity so I don't understand how it can be so slow on the game over screen, as it shouldn't have to worry about anything but the game over screen once it's there and the game over screen is very simple.
I'm having a hard time locating where the problem comes from, hence why I'm asking for help here.
Here is some code that I hope is sufficent for locating the problem:
MainActivity (deals with animation, level increase, spawn objects and interaction between objects and rules)
public class MainActivity extends AppCompatActivity implements GarbageListener {
//global variable of FishView
private FishView gameView;
//handle animation task
private final Handler handler = new Handler();
//global variable of screen
private RelativeLayout screen;
//time before level update
private int levelChangeTime = 3; //initialize small garbage in X seconds
private int spawnBossGarbage = 25; //initialize big garbage in X seconds
private int spawnHeart = 40; //initialize heart in X seconds
//pause variables
private Button pauseButton;
private boolean pauseFlag = false;
//left and right button
private Button leftButton;
private Button rightButton;
//List of small garbage on screen
private final List<SmallGarbage> smallGarbages = new ArrayList<>();
//List of big garbage on screen
private List<BigGarbage> bigGarbages = new ArrayList<>();
//List of heart on screen
private List<LifePoint> lifePoints = new ArrayList<>();
//create timer for animation and level increase
private Timer mainTimer;
//create timer fro holding left or right
private Timer movingLeft;
private Timer movingRight;
private final boolean buttonIsPressed = false; //so players can't hold both buttons down
private final int holdMovementPeriod = 9;
//keep track of song
public static Intent themeSong;
//keep track of how far we are in the song, serviceStop() deletes everything in service ThemeSong so variable must be saved elsewhere
public static int lengthOfSong = 0;
public static boolean backButtonPressed = false; //check if backButton was pressed in service ThemeSong oonDestroy() since that's the last thing that is run
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
themeSong=new Intent(this, ThemeSong.class);
startService(themeSong); //OR stopService(svc);
leftButton = findViewById(R.id.leftArrow);
rightButton = findViewById(R.id.rightArrow);
screen = findViewById(R.id.gameScreen);
gameView = new FishView(this);
screen.addView(gameView);
pauseButton = findViewById(R.id.pauseButton);
mainTimer = new Timer();
createNewAnimationTask();
createNewLevelTask();
//create listeners fo holding left or right button
findViewById(R.id.leftArrow).setOnTouchListener(new View.OnTouchListener() {
#SuppressLint("ClickableViewAccessibility")
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
holdLeft();
rightButton.setEnabled(false);}
if (event.getAction() == MotionEvent.ACTION_UP) {
rightButton.setEnabled(true);
if (movingLeft!=null){
movingLeft.cancel();
}}
return false;}
});
findViewById(R.id.rightArrow).setOnTouchListener(new View.OnTouchListener() {
#SuppressLint("ClickableViewAccessibility")
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
holdRight();
leftButton.setEnabled(false);}
if (event.getAction() == MotionEvent.ACTION_UP) {
leftButton.setEnabled(true);
if (movingRight!=null){
movingRight.cancel();}}
return false;}
});
}
public void moveLeft(#SuppressWarnings("unused") View v){
if (buttonIsPressed){return;}
gameView.setLeftPressed(true);
gameView.leftFishAnimation();//before running the animations we first set which fish animations to run (left or right)
gameView.invalidate();
}
public void moveRight(#SuppressWarnings("unused") View view) {
if (buttonIsPressed){return;}
gameView.setRightPressed(true);
gameView.rightFishAnimation();
gameView.invalidate();
}
public void pauseGame(View v){
String resume = "Resume";
String pause = "Pause";
if (!pauseFlag){
stopService(themeSong); //turn of music
pauseFlag = true;
pauseButton.setText(resume);
pauseButton.setBackgroundResource(R.drawable.roundbuttonred);
//disable animation and level tasks
mainTimer.cancel();
//disable all falling garbage on screen
for (SmallGarbage smallGarbage : smallGarbages) {smallGarbage.disableGarbageTimer();}
for (BigGarbage bigGarbage : bigGarbages) {bigGarbage.disableGarbageTimer();}
for (LifePoint lifePoint : lifePoints) {lifePoint.disableGarbageTimer();}
//disable buttons
leftButton.setEnabled(false);
rightButton.setEnabled(false);
}
else{
startService(themeSong); //start music
pauseFlag=false;
pauseButton.setText(pause);
leftButton.setEnabled(true);
rightButton.setEnabled(true);
pauseButton.setBackgroundResource(R.drawable.roundbuttonblue);
//resume falling garbage
for (SmallGarbage smallGarbage : smallGarbages) {smallGarbage.startFallingGarbage();}
for (BigGarbage bigGarbage : bigGarbages) {bigGarbage.startFallingGarbage();}
for (LifePoint lifePoint : lifePoints) {lifePoint.startFallingGarbage();}
//resume animation and level increase
mainTimer = new Timer();
createNewAnimationTask();
createNewLevelTask();
}
}
private void createNewAnimationTask(){
TimerTask newAnimationTask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
#Override
public void run() {
//here we set the animation
int selectedFish = gameView.getSelectedFish();
selectedFish ++;
if (selectedFish==2){
selectedFish = 0;}
gameView.setSelectedFish(selectedFish);
//update screen
gameView.invalidate();
}
});
}
};
long animationPeriod = 600;
mainTimer.scheduleAtFixedRate(newAnimationTask, 0, animationPeriod);
}
private void createNewLevelTask(){
TimerTask levelCountDown = new TimerTask(){
#Override
public void run() {
levelChangeTime--;
spawnBossGarbage--;
spawnHeart--;
if (levelChangeTime==0 || spawnBossGarbage == 0 || spawnHeart == 0){
//move task that updates the UI onto the main thread
runOnUiThread(new Runnable() { //this tells the program to run this on the UI(aka main) thread, we could also call on new Thread if wanted to start new thread
#Override
public void run() {
if (levelChangeTime==0){generateNewGarbage("smallGarbage");}
if (spawnBossGarbage==0){generateNewGarbage("bigGarbage");}
if (spawnHeart==0){generateNewGarbage("lifePoint");}// when this is added we can't lose life?
}
});
}
}
};
mainTimer.scheduleAtFixedRate(levelCountDown,0,1000);
}
private void holdLeft(){
movingLeft = new Timer();
final View v = new View(this); //create view so moveLeft() can called
TimerTask holdLeftTask = new TimerTask(){
#Override
public void run() {
handler.post(new Runnable() {
#Override
public void run() {
moveLeft(v);
}
});
}};
movingLeft.scheduleAtFixedRate(holdLeftTask,0,holdMovementPeriod);
}
private void holdRight(){
movingRight = new Timer();
final View v = new View(this);
TimerTask holdRightTask = new TimerTask(){
#Override
public void run() {
handler.post(new Runnable() {
#Override
public void run() {
moveRight(v);
}
});
}};
movingRight.scheduleAtFixedRate(holdRightTask,0,holdMovementPeriod);
}
private void generateNewGarbage(String garbage){
switch (garbage){
case "bigGarbage":
spawnBossGarbage = 40; //time to next spawn
BigGarbage newBigGarbage = new BigGarbage(MainActivity.this);
newBigGarbage.setListener(MainActivity.this);
bigGarbages.add(newBigGarbage);
screen.addView(newBigGarbage);
break;
case "smallGarbage":
levelChangeTime = new Random().nextInt(20)+3; //set seconds between 3 and 20 at random
//this create SmallGarbage and initialize its task
SmallGarbage newGarbage = new SmallGarbage(MainActivity.this);
newGarbage.setListener(MainActivity.this); // set listener for garbage
smallGarbages.add(newGarbage);
screen.addView(newGarbage);
break;
case "lifePoint":
spawnHeart=30; //time to next spawn
//this create SmallGarbage and initialize its task
LifePoint newLifePoint = new LifePoint(MainActivity.this);
newLifePoint.setListener(MainActivity.this); // set listener for garbage
lifePoints.add(newLifePoint);
screen.addView(newLifePoint);
break;
}
}
//here starts the GarbageListener
#Override
public void handleAvoidedGarbage(String avoidedGarbage) {
gameView.avoidedGarbage(avoidedGarbage);
}
#Override
public boolean handleHitPlayer(int x, int y, String garbageType) {
return gameView.hitWasteChecker(x,y, garbageType);
}
#Override
public void handleLoseLife() {
gameView.loseLife();
}
//empty lives on screen, once they have landed or hit player
#Override
public void emptyLifePointList(){
lifePoints.clear();
lifePoints = new ArrayList<>();
}
//empty big garbage on screen, once they have landed or hit player
#Override
public void emptyBigGarbageList(){
bigGarbages.clear();
bigGarbages = new ArrayList<>();
}
//saving and setting length of played song
public static int getLengthOfSong() {
return lengthOfSong;
}
public static void setLengthOfSong(int lengthOfSong) {
MainActivity.lengthOfSong = lengthOfSong;
}
//onStop runs AFTER onBackPressed(), so lengthOfSong must be reset there
#Override
public void onBackPressed() {
super.onBackPressed();
backButtonPressed = true;
}
public static boolean isBackButtonPressed() {
return backButtonPressed;
}
public static void setBackButtonPressed(boolean backButtonPressed) {
MainActivity.backButtonPressed = backButtonPressed;
}
//this runs whenever the app is closed
#Override
protected void onStop(){
super.onStop();
//stop music
stopService(themeSong);
setLengthOfSong(0);
//pause game, this will also reset sound upon start
final View v = new View(this);
pauseFlag = false;
pauseGame(v);
}
}
FishView (deals with creating the player, rules and HANDELING the starting the game over screen)
public class FishView extends View {
private final Bitmap[] fish = new Bitmap[3];
private final Bitmap gameBackground;
private final Bitmap[] lifePoints = new Bitmap[2];
private int selectedFish;
private final Paint scorePaint = new Paint();
private int score, fishLives;
private static final int fishY = 1200;
private int fishX = 400;
private int speedX = 0;
private boolean leftPressed = false;
private boolean rightPressed = false;
public FishView(Context context) {
super(context);
//set background
gameBackground = BitmapFactory.decodeResource(getResources(),R.drawable.underwater);
//set default/start fish animations
leftFishAnimation();
//set selected fish animation to default start on 0
selectedFish = 0;
//set life points
lifePoints[1] = BitmapFactory.decodeResource(getResources(),R.drawable.lifepoint);
lifePoints[0] = BitmapFactory.decodeResource(getResources(),R.drawable.deadlife);
//set score
scorePaint.setColor(Color.WHITE);
scorePaint.setTextSize(80);
// scorePaint.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD)); //??
scorePaint.setAntiAlias(true); //(graphic improvement) this removes the staircase effect aka make smoother
scorePaint.setTypeface(Typeface.SERIF);
score = 0;
//set fish lives
fishLives = 3;
}
//in a View, the onDraw method is called whenever:
//the view is initially drawn or whenever invalidate() is called on the view
//in our case we call on the constructor which initially the View
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//should maybe be canvas.getWidth() here
int canvasWidth=getWidth();
//set game boundaries
int minFishX = 0; //should not be able to go of screen (to the left)
int maxFishX = canvasWidth-fish[0].getWidth(); //furthers you can go to the right (to the right)
//check boundaries
if (fishX < minFishX) {
fishX = minFishX;
}
if (fishX > maxFishX) {
fishX = maxFishX;
}
//set position dependent on speed
fishX += speedX;
//draw background
canvas.drawBitmap(gameBackground, 0, 0, null);
//this draws the bitmap we decoded from the image
if (leftPressed){
speedX -= 15;
}
else if (rightPressed){
speedX += 15;
}
if (speedX != 0){
while (speedX != 0){
if (leftPressed){
fishX -= 1;
speedX += 1;
canvas.drawBitmap(fish[selectedFish],fishX,fishY,null);
invalidate();
}
else if (rightPressed){
fishX += 1;
speedX -= 1;
canvas.drawBitmap(fish[selectedFish],fishX,fishY,null);
invalidate();
}
}}
else{ //if nothing happens when we stay here
canvas.drawBitmap(fish[selectedFish],fishX,fishY, null);
}
leftPressed=false;
rightPressed=false;
//draw score
canvas.drawText("Score: " + score, 20 , 90, scorePaint);
//draw life points and life point we have lost
for (int lives = 0; lives < 3 ; lives++) {
int lifeX = 650 + 140*lives;
int lifeY = 10;
if (lives < fishLives){
canvas.drawBitmap(lifePoints[1],lifeX,lifeY,null);
}
else{
canvas.drawBitmap(lifePoints[0],lifeX,lifeY,null);
}
}
}
public boolean hitWasteChecker(int x, int y, String garbageType){
switch (garbageType){
//define hit boxes
//first check is how far above, second how much underneath, third how much to the left, and fourth how much to the right
case "smallGarbage":
return fishY <= y + 80 && fishY + fish[selectedFish].getHeight() >= y + 75 && fishX <= x + 75 && x + 20 <= (fishX + fish[selectedFish].getWidth());
case "bigGarbage":
return fishY <= y + 170 && fishY + fish[selectedFish].getHeight() >= y + 75 && fishX <= x + 180 && x + 20 <= (fishX + fish[selectedFish].getWidth());
case "lifePoint":
if (fishY <= y + 25 && fishY + fish[selectedFish].getHeight() >= y + 60 && fishX <= x + 110 && x + 35 <= (fishX + fish[selectedFish].getWidth())){
if (fishLives<3){fishLives++;
return true;} //if not full life gain a life
if (fishLives==3){score+=40; //if already full life then gain 40 points
return true;}}
return false;
default:
return false;
}}
public void loseLife(){
fishLives--;
if (fishLives<=0){
//stop theme song from playing
getContext().stopService(MainActivity.themeSong);
//through these lines a new Activity can be created from a View
Intent gameOverIntent = new Intent(getContext(), GameOverActivity.class);
gameOverIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); //not possible to go back from game over screen
gameOverIntent.putExtra("final score", score); // send data to game over activity
getContext().startActivity(gameOverIntent);
((MainActivity) getContext()).overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
((MainActivity) getContext()).finish(); //TIMERS is till running
}
}
public void leftFishAnimation(){
fish[0] = BitmapFactory.decodeResource(getResources(),R.drawable.leftfish1);
fish[1] = BitmapFactory.decodeResource(getResources(),R.drawable.leftfish2);
}
public void rightFishAnimation(){
fish[0] = BitmapFactory.decodeResource(getResources(),R.drawable.rightfish1);
fish[1] = BitmapFactory.decodeResource(getResources(),R.drawable.rightfish2);
}
public void setLeftPressed(boolean leftPressed) {
this.leftPressed = leftPressed;
}
public void setRightPressed(boolean rightPressed) {
this.rightPressed = rightPressed;
}
public int getSelectedFish() {
return selectedFish;
}
public void setSelectedFish(int selectedFish) {
this.selectedFish = selectedFish;
}
public void avoidedGarbage(String avoidedGarbage){
switch (avoidedGarbage){
case "smallGarbage":
score += 10;
break;
case "bigGarbage":
score += 25;
break;
}
}
}
GameOver: (display the game over screen)
public class GameOverActivity extends AppCompatActivity {
//create instance of database
private DatabaseHelper db;
private EditText usernameInput;
private int score;
private MediaPlayer gameOverSound;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game_over);
score = Objects.requireNonNull(getIntent().getExtras()).getInt("final score");
usernameInput = findViewById(R.id.addUsername);
db = new DatabaseHelper(this);
//easier way of doing it
gameOverSound = MediaPlayer.create(this, R.raw.gameoversound);
gameOverSound.setVolume(0.2f,0.2f);
gameOverSound.start();
String yourFinalScore = "Your final score: " + score;
TextView finalScore = findViewById(R.id.finalScore);
finalScore.setText(yourFinalScore);
}
public void restartGame(View v){
Intent restartIntent = new Intent(this, MainActivity.class);
restartIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); //so we can't go back to game over
startActivity(restartIntent);
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out); //transition between activities
finish(); //end this activity, MainActivity is already ended so can't only call on finish here to go back
}
public void backToStartMenu(View view) {
Intent startMenuIntent = new Intent(this, MenuActivity.class);
startActivity(startMenuIntent);
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
finish(); //end this activity
}
public void addHighscore(View view) {
String writtenUsername = usernameInput.getText().toString();
if (!writtenUsername.equals("") && score != 0){
//insert writtenUsername and score into database
boolean insertedData = db.insertData(writtenUsername, score);
if (insertedData){
Toast.makeText(this, "Highscore was added", Toast.LENGTH_SHORT).show();
Intent startMenuIntent = new Intent(this, MenuActivity.class);
startActivity(startMenuIntent);
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
finish();}
else{
Toast.makeText(this, "Highscore couldn't be added", Toast.LENGTH_SHORT).show();
}
}
}
//this runs whenever the app is closed, mobile arrow is pressed or we switch activity
#Override
protected void onStop(){
super.onStop();
gameOverSound.stop();
gameOverSound.release(); //solve error: if run twice the app will close because we cant release it twice
}
//if pressed mobile back button go back to start menu
#Override
public void onBackPressed() {
super.onBackPressed();
View v = new View(this);
backToStartMenu(v);
}
}
What I find weird about this problem is that the MainActivity, with the player animation and all the falling view objects, runs fine. However, something as small as the game over screen is lagging. This leaves me to believe that I somehow don't quit my Activities as I should which leads to the main thread not being able to handel it. Anyways thank you for your time! :)
Update:
I checked it and it seems to be some real problem with the transition from MainActivity to GameOver. Using Android help -> find-action -> profiler,
I was able to see that the memory useage was about 110 MB while in MainActivity and as soon as I got to the game over screen it went all the way up to 400 MB. But still I'm not able to locate why it occurs.
I figured it out. The problem was the sharp background image that I was using in my GameOver screen, apparently it was too much for the game too handle. So if you have any similar problem try changing the images and backgrounds on the screen.

How to Stop a Thread when Using Handler in Android?

I'm going to make several images that are to be changing by Handler when they are clicked.
But now there are only two images for a test.
I want to change the images in two processes of clicking on them.
The first process should be stopped when the imaged was clicked again.
In my code, however, the first process doesn't stop.
I can see that both processes are simultaneously acting along.
How can I stop the first thread, and how can I manage one by one when there are many threads are going on?
Here is my code below.
public class MainActivity extends AppCompatActivity {
ImageView img;
ImageView img2;
ImageView img3;
Button btn;
Handler myHandler;
Runnable myRun;
int flag_number;
int img1_phase = 0;
//click method for image 1
public void img1_click (View view) {
flag_number = 1;
click_change_Image(img, img1_phase);
myRun = new Runnable() {
#Override
public void run() {
time_change_image(img, img1_phase);
}
};
new Thread(myRun).start();
}
}
//Click method for 2nd process
public void click_change_Image(final ImageView imageView, int phase) {
if (phase == 4 || phase == 5) {
imageView.setImageResource(R.drawable.second_1);
myHandler.removeCallbacksAndMessages(null); //this code doesn't work
Thread.interrupted();// not work either
phase = 7;
}
image_checker(phase);
return;
}
//Change Image Process by Thread after Clicked
public void time_change_image(final ImageView imageView, int phase) {
if (phase == 0) {
change_Image(imageView, R.drawable.new_one_1, 300);
phase = 1;
image_checker(phase);
change_Image(imageView, R.drawable.new_one_2, 300);
phase = 2;
image_checker(phase);
change_Image(imageView, R.drawable.first_1, 300);
phase = 3;
image_checker(phase);
change_Image(imageView, R.drawable.first_2, 3000);
phase = 4;
image_checker(phase);
change_Image(imageView, R.drawable.first_3, 3000);
phase = 5;
image_checker(phase);
change_Image(imageView, R.drawable.first_4, 3000);
phase = 6;
image_checker(phase);
change_Image(imageView, R.drawable.empty, 3000);
phase = 0;
image_checker(phase);
}else if(phase == 7) {
change_Image(imageView, R.drawable.second_2, 3000);
phase = 8;
image_checker(phase);
change_Image(imageView, R.drawable.second_3, 3000);
phase = 9;
image_checker(phase);
change_Image(imageView, R.drawable.second_4, 3000);
phase = 10;
image_checker(phase);
change_Image(imageView, R.drawable.empty, 3000);
phase = 0;
image_checker(phase);
}
flag_number = 0;
}
//Change Image Resource method
public void change_Image(final ImageView iv, final int image, int wait_time) {
sleep_Thread(wait_time);
myHandler.post(new Runnable() {
#Override
public void run() {
iv.setImageResource(image);
}
});
}
}
Using a flag to manage your thread. For instance:
boolean isRun = true (global variable)
myRun = new Runnable() {
#Override
public void run() {
if(isRun) {
time_change_image(img, img1_phase);
}
}
};
Use Handler to avoid delay in main thread.
Handler mHandler = new Handler();
to start a thread:
mHandler.post(Runnable);
or
mHandler.postDelayed(Runnable, some delayTime)
to stop
mHandler.removeCallback(Runnable);

Horizontal ScrollView Gallery. Scroll both directions or from begining

I am making horizontal scrollview gallery, and I want to autoscroll it. Now it's scrolling from left to right but when I reach end of list I just simply jump to first one, but it looks really bad, so I want to go scroll around from beginning avoiding just skipping to first one, or if it is not possible just start scrolling to the other side when I reach last view on right (maybe better option). Could someone help me how to do this?
private LinearLayout horizontalOuterLayout;
private HorizontalScrollView horizontalScrollview;
private int scrollMax;
private int scrollPos = 0;
private TimerTask clickSchedule;
private TimerTask scrollerSchedule;
private TimerTask faceAnimationSchedule;
private Timer scrollTimer = null;
private Timer faceTimer = null;
private String[] imageNameArray ={ "sponsors_czarnykot", "sponsors_estradarzeszow","sponsors_klubp","sponsors_kula","sponsors_czarnykot", "sponsors_estradarzeszow","sponsors_klubp","sponsors_kula" };
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.horizontal_layout);
horizontalScrollview = (HorizontalScrollView) findViewById(R.id.horiztonal_scrollview_id);
horizontalOuterLayout = (LinearLayout) findViewById(R.id.horiztonal_outer_layout_id);
horizontalScrollview.setHorizontalScrollBarEnabled(false);
addImagesToView();
ViewTreeObserver vto = horizontalOuterLayout.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener()
{
#Override
public void onGlobalLayout()
{
horizontalOuterLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
getScrollMaxAmount();
startAutoScrolling();
}
});
}
public void getScrollMaxAmount()
{
int actualWidth = (horizontalOuterLayout.getMeasuredWidth() - 512);
scrollMax = actualWidth;
}
public void startAutoScrolling()
{
if (scrollTimer == null)
{
scrollTimer = new Timer();
final Runnable Timer_Tick = new Runnable()
{
public void run()
{
moveScrollViewRight();
}
};
if (scrollerSchedule != null)
{
scrollerSchedule.cancel();
scrollerSchedule = null;
}
scrollerSchedule = new TimerTask()
{
#Override
public void run()
{
runOnUiThread(Timer_Tick);
}
};
scrollTimer.schedule(scrollerSchedule, 30, 30);
}
}
public void moveScrollViewRight()
{
scrollPos = (int) (horizontalScrollview.getScrollX() + 1.0);
if (scrollPos >= scrollMax)
{
scrollPos = 0;
}
horizontalScrollview.scrollTo(scrollPos, 0);
}
/** Adds the images to view. */
public void addImagesToView()
{
for (int i = 0; i < imageNameArray.length; i++)
{
final ImageView imageView = new ImageView(this);
int imageResourceId = getResources().getIdentifier(imageNameArray[i], "drawable", getPackageName());
Drawable image = this.getResources().getDrawable(imageResourceId);
imageView.setBackgroundDrawable(image);
imageView.setTag(i);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(180, 123);
params.setMargins(0, 25, 0, 25);
imageView.setLayoutParams(params);
horizontalOuterLayout.addView(imageView);
}
}
public void stopAutoScrolling()
{
if (scrollTimer != null)
{
scrollTimer.cancel();
scrollTimer = null;
}
}
public void onBackPressed()
{
super.onBackPressed();
finish();
}
public void onPause()
{
super.onPause();
finish();
}
public void onDestroy()
{
clearTimerTaks(clickSchedule);
clearTimerTaks(scrollerSchedule);
clearTimerTaks(faceAnimationSchedule);
clearTimers(scrollTimer);
clearTimers(faceTimer);
clickSchedule = null;
scrollerSchedule = null;
faceAnimationSchedule = null;
scrollTimer = null;
faceTimer = null;
super.onDestroy();
}
private void clearTimers(Timer timer)
{
if (timer != null)
{
timer.cancel();
timer = null;
}
}
private void clearTimerTaks(TimerTask timerTask)
{
if (timerTask != null)
{
timerTask.cancel();
timerTask = null;
}
}
scrolling back the other way would be easiest.
add in a instance variable that is set to 1.0 (called say scrollDist)
then change this line
scrollPos = (int) (horizontalScrollview.getScrollX() + 1.0);
to
scrollPos = (int) (horizontalScrollview.getScrollX() + scrollDist);
and this line
scrollPos = 0;
to
scrollDist *= -1.0;
this way it will reverse each time it hits the end of the scrollview.
For endless scrolling use the following snnipet
public void getScrollMaxAmount() {
int actualWidth = (horizontalOuterLayout.getMeasuredWidth() - getWindowManager().getDefaultDisplay().getWidth());
scrollMax = actualWidth;
}
public void moveScrollView() {
// ********************* Scrollable Speed ***********************
scrollPos = (int) (horizontalScrollview.getScrollX() + 1.0);
if (scrollPos >= scrollMax) {
Log.v("childCount", ""+scrollMax);
addImagesToView();
getScrollMaxAmount();
}
horizontalScrollview.scrollTo(scrollPos, 0);
}

How to animate multiple objects one by one after some intervals android

How to animate multiple objects one by one after some intervals android
i am using this code for animation
for (int y = 0; y < 10; y++) {
runOnUiThread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
Toast.makeText(ProjectFirstActivity.this, y + "",
Toast.LENGTH_SHORT).show();
ObjectAnimator oa = ObjectAnimator.ofFloat(myimageview[y],
"translationY", 0, -200);
oa.setDuration(1000);
oa.start();
}
});
}
but it is animating all in one go but i want one by one animation of my imageview please help
No need to use Threads and Handlers. Instead of that use,
objectAnimator.setStartDelay(delay);
Using that you can stop that animation for the respective 'delay'
Try this code..
int delay = 1000;
for (int y = 0; y < 10; y++) {
Toast.makeText(ProjectFirstActivity.this, y + "",
Toast.LENGTH_SHORT).show();
ObjectAnimator oa = ObjectAnimator.ofFloat(myimageview[y],
"translationY", 0, -200);
oa.setDuration(1000);
oa.setStartDelay(delay);
oa.start();
delay = delay+1000;
}
You can use for loop to generate AnimatorSet and then play them sequentially using set.playSequentially(yourAnimatorSetListHere);
I haven't used list in below mentioned snippet.
AnimatorSet decSet = new AnimatorSet();
decSet.playTogether(
ObjectAnimator.ofArgb(mTextSlidetoCancel, "visibility", View.GONE, View.VISIBLE),
ObjectAnimator.ofArgb(mBtnMicActive, "visibility", View.GONE, View.VISIBLE),
ObjectAnimator.ofArgb(mChronometer, "visibility", View.GONE, View.VISIBLE));
decSet.setDuration(125);
AnimatorSet decSet2 = new AnimatorSet();
decSet2.playTogether(
ObjectAnimator.ofArgb(mBtnAttach, "visibility", View.VISIBLE, View.GONE),
ObjectAnimator.ofArgb(mBtnEmoji, "visibility", View.VISIBLE, View.GONE),
ObjectAnimator.ofArgb(mEditTExt, "visibility", View.VISIBLE, View.GONE)
);
decSet2.setDuration(125);
AnimatorSet set = new AnimatorSet();
set.playSequentially(decSet2,decSet);
set.start();
Try out this way!
public Integer[] Imgid = {R.drawable.anim2, R.drawable.anim3,
R.drawable.anim4, R.drawable.anim5}; // your image array.
Animation anim;
Handler handler;
ImageView iv;
int count;
Runnable galleryAnimRunnable;
Inside onCreate
iv= (ImageView)findViewById(R.id.imagetype);
handler = new Handler();
galleryAnimRunnable = new Runnable() {
public void run() {
if(count==Imgid.length){
//do any action
}
else{
anim = AnimationUtils.loadAnimation(AnimationScreen.this, R.anim.fade_out); // load your desire animation.
iv.setBackgroundResource(Imgid[count]);
iv.setAnimation(anim);
count++;
handler.postDelayed(galleryAnimRunnable, 300); //set your desire delay time.
}
}
};
Your sleep call isn't helping because when one posted UI job goes to sleep, then next one starts and goes to sleep immediately following that, and so on. Then the first job wakes up and runs, followed closely by the second job awakening and running, etc.
If you want the sleep to help you need to wait before posting each job, which could be as simple as something like the following:
for (int y = 0; y < 10; y++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(ProjectFirstActivity.this, y + "",
Toast.LENGTH_SHORT).show();
ObjectAnimator oa = ObjectAnimator.ofFloat(myimageview[y],
"translationY", 0, -200);
oa.setDuration(1000);
oa.start();
}
});
}
EDIT: Although the above explains why you were having problems, I would recommend going with something like the answer posted by Jgdsh Seerm using setStartDelay().
Try this way!
ImageView image1;
public int currentimageindex1=0;
Timer timer;
TimerTask task;
private Animation animation1;
private Animation animation2;
int img[] = {R.drawable.aa, R.drawable.bb,
R.drawable.cc,R.drawable.dd,R.drawable.ee,R.drawable.ff,R.drawable.gg,
R.drawable.hh};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Handler mHandler = new Handler();
// Create runnable for posting
final Runnable mUpdateResults = new Runnable() {
public void run() {
AnimateandSlideShow();
}
};
int delay = 1000; // delay for 1 sec.
int period = 4000; // repeat every 4 sec.
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
mHandler.post(mUpdateResults);
}
}, delay, period);
}
public void onClick(View v) {
finish();
android.os.Process.killProcess(android.os.Process.myPid());
}
/**
* Helper method to start the animation on the splash screen
*/
private void AnimateandSlideShow() {
image1 = (ImageView)findViewById(R.id.imageView1);
image1.setImageResource(img[currentimageindex1%img.length]);
currentimageindex1++;
}

How to wait for Runnable finish?

I have a method named loadBalls(). In this method, I called another method named removeOldBalls().
In removeOldBalls(), I have a runnable to detach children on the scene.
Below are 2 methods :
public static void loadBalls() {
removeOldBalls();
for (int i = 0; i < MAX_BALL; i++) {
int x = MathUtils.random(0, CAMERA_WIDTH - BALL_SIZE);
int y = BALL_SIZE;
final Ball ball = new Ball(x, y, BALL_SIZE, BALL_SIZE, GraphicsManager.trBalloons[i]);
scene.registerTouchArea(ball);
balls.add(ball);
if (!balls.get(i).hasParent()) {
scene.attachChild(balls.get(i));
}
Log.e("test", "load");
}
}
public static void removeOldBalls() {
((BaseLiveWallpaperService) LWP.context).runOnUpdateThread(new Runnable() {
public void run() {
Log.e("test", "remove");
scene.detachChildren();
}
});
if (balls != null) {
int length = balls.size();
for (int i = 0; i < length; i++) {
fsw.destroyBody(balls.get(i).body);
}
balls.clear();
Log.e("test", "clear");
}
}
What I need is all children are removed before adding new ones. But when running above source code, the children are added first, then removed.
Please tell me how to wait for removing finish before adding.
I think look for the class android.os.Handler. Then you can create two threads: one to remove all the children and another to add the children. Then add those threads to the Handler like this:
handler.post(new Runnable(){
#Override
public void run() {
// Thread to remove children
}
});
handler.post(new Runnable(){
#Override
public void run() {
// Thread to add children
}
});
Once you add them one after another the Android SDK will execute them in the order they were added. So that will take care of your ordering issue.
Move the code which adds the children to another method, for example addBalls:
private void addBalls() {
for (int i = 0; i < MAX_BALL; i++) {
int x = MathUtils.random(0, CAMERA_WIDTH - BALL_SIZE);
int y = BALL_SIZE;
final Ball ball = new Ball(x, y, BALL_SIZE, BALL_SIZE, GraphicsManager.trBalloons[i]);
scene.registerTouchArea(ball);
balls.add(ball);
if (!balls.get(i).hasParent()) {
scene.attachChild(balls.get(i));
}
Log.e("test", "load");
}
}
And call this method fron the run method of the Runnable after you call scene.detachChildren:
public void run() {
Log.e("test", "remove");
scene.detachChildren();
addBalls();
}

Categories

Resources