Reputation: 51
I'm trying to do simple slideshow, there is the code I'm using:
public class Pictures extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
private ImageView picture;
private Integer resourceImage;
private Handler handler = new Handler();
private Runnable runnable = new Runnable() {
public void run() {
showNewPicture(true);
handler.postDelayed(this, 1000);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
// initialization here
final Button slideshowStart = (Button) findViewById(R.id.slideshow_start);
// I'm starting slideshow using this:
slideshowStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
handler.removeCallbacks(runnable);
handler.post(runnable);
}
});
final Button slideshowStop = (Button) findViewById(R.id.slideshow_stop);
// I'm stopping slideshow using this:
slideshowStop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
handler.removeCallbacks(runnable);
}
});
}
private void showNewPicture(Boolean next){
// defining resource ID for the new picture, i. e.:
resourceImage = R.drawable.some_picture;
setScaledImage(picture, resourceImage);
picture.setTag(newTag);
}
// all the code below is to scale images to the actual size of the view
private void setScaledImage(ImageView imageView, final int resId) {
final ImageView iv = imageView;
ViewTreeObserver viewTreeObserver = iv.getViewTreeObserver();
viewTreeObserver.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
public boolean onPreDraw() {
iv.getViewTreeObserver().removeOnPreDrawListener(this);
int imageViewHeight = iv.getMeasuredHeight();
int imageViewWidth = iv.getMeasuredWidth();
iv.setImageBitmap(
decodeSampledBitmapFromResource(getResources(),
resId, imageViewWidth, imageViewHeight));
return true;
}
});
}
private static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds = true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}
private static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
if(height > width){
while ((halfHeight / inSampleSize) >= reqHeight) {
inSampleSize *= 2;
}
}else{
while ((halfWidth / inSampleSize) >= reqWidth) {
inSampleSize *= 2;
}
}
}
return inSampleSize;
}
}
When I'm calling showNewPicture(true) with some button click, it works fine and updates source of ImageView. But when I'm running the slideshow with the code provided, it only changes when I click "start" and "stop" button. The code inside the runnable executes, so if I'll have 10 images, start the slideshow, wait for about 5 seconds and click "stop", the ImageView will display the 6th image. Also if I replace the line insite the runnable
handler.postDelayed(this, 1000);
with
handler.post(this);
it works just fine, my ImageView is updating, but the process is constant, and I want to set some delay, that's why I'm using "postDelayed". I've also tried to declare Handler like this:
private Handler handler = new Handler(Looper.getMainLooper());
and got the same result. Also, when I'm adding Toast with Pictures.this context to runnable - it shows up, so I've also tried Declaring Runnable like this:
private Runnable runnable = new Runnable() {
public void run() {
Pictures.this.showNewPicture(true);
Pictures.this.handler.postDelayed(this, 1000);
}
};
but it leads to the same result. What am I missing here?
Upvotes: 0
Views: 566
Reputation: 51
Still hasn't figured out what causes the problem, but found a workaround, I've chaned my Runnable
like this (added picture.invalidate()
):
private Runnable runnable = new Runnable() {
public void run() {
showNewPicture(true);
picture.invalidate();
handler.postDelayed(this, 5000);
}
};
Now the image within the ImageView
is updating correctly on each Runnable
execution, even if I'm using postDelayed
.
Upvotes: 0
Reputation: 3711
You are removing the handler callbacks in the onClick
of the slideShowStart,
handler.removeCallbacks(runnable);
so there is no way the message will be received. Remove that line and it should work.
Upvotes: 0