2016-03-09 3 views
0

Я пытаюсь сделать простой слайд-шоу, есть код, я использую:ImageView.setImageBitmap не меняет вид, когда вызывается с помощью метода Handler.postDelayed

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; 
} 
} 

Когда я звоню showNewPicture (true) с некоторым нажатием кнопки, он отлично работает и обновляет источник ImageView. Но когда я запускаю слайд-шоу с предоставленным кодом, он меняется только при нажатии кнопки «начать» и «остановить». Код внутри runnable выполняется, поэтому, если у меня будет 10 изображений, запустите слайд-шоу, подождите около 5 секунд и нажмите «Остановить», ImageView отобразит 6-е изображение. Кроме того, если я заменить строку INSITE на работоспособный

handler.postDelayed(this, 1000); 

с

handler.post(this); 

это работает просто отлично, моя ImageView обновляется, но этот процесс является постоянным, и я хочу, чтобы установить некоторую задержку, поэтому Я использую «postDelayed». Я также попытался объявить Handler, как это:

private Handler handler = new Handler(Looper.getMainLooper()); 

и получил тот же результат. Кроме того, когда я добавляю Тост с pictures.This контексте работоспособным - это показывает, так что я также пытался Декларирование Runnable так:

private Runnable runnable = new Runnable() { 
    public void run() { 
     Pictures.this.showNewPicture(true); 
     Pictures.this.handler.postDelayed(this, 1000); 
    } 
}; 

, но это приводит к тому же результату. Что мне здесь не хватает?

+0

получил какую-либо ошибку.? – Amy

+0

Нет, все работает нормально, журнал не показывает ошибок, просто ImageView не обновляется, когда я использую «postDelayed». – oort

ответ

0

до сих пор не понял, что вызывает проблему, но нашел обходной путь, я chaned мой Runnable как это (добавлено picture.invalidate()):

private Runnable runnable = new Runnable() { 
    public void run() { 
     showNewPicture(true); 
     picture.invalidate(); 
     handler.postDelayed(this, 5000); 
    } 
}; 

Теперь изображение в ImageView обновляется правильно на каждый Runnable исполнение, даже если я использую postDelayed.

0

Вы удаляете обратные вызовы обработчиков в onClick в slideShowStart,

handler.removeCallbacks(runnable); 

так что нет никакого способа, сообщение будет получено. Удалите эту строку, и она должна работать.

+0

Пробовал, изображение не обновляется. Кроме того, линия, о которой вы упоминаете, сначала не была там, наткнулась на такую ​​конструкцию, а была поиском для лечения ... – oort