【问题标题】:ImageView.setImageBitmap doesn't change view when called using Handler.postDelayed methodImageView.setImageBitmap 在使用 Handler.postDelayed 方法调用时不会改变视图
【发布时间】:2016-03-09 10:40:13
【问题描述】:

我正在尝试做简单的幻灯片,有我正在使用的代码:

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 张图片。另外,如果我在可运行文件中替换该行

handler.postDelayed(this, 1000);

handler.post(this);

它工作得很好,我的 ImageView 正在更新,但过程是恒定的,我想设置一些延迟,这就是我使用“postDelayed”的原因。 我也尝试过这样声明 Handler:

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

并得到相同的结果。 此外,当我将带有 Pictures.this 上下文的 Toast 添加到可运行时 - 它会显示出来,所以我也尝试过像这样声明可运行:

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

但它会导致相同的结果。 我在这里错过了什么?

【问题讨论】:

  • 不,一切正常,日志显示没有错误,只是 ImageView 在我使用“postDelayed”时没有更新。

标签: android imageview runnable android-handler


【解决方案1】:

您正在删除 slideShowStart 的 onClick 中的处理程序回调,

handler.removeCallbacks(runnable);

所以没有办法接收到消息。删除该行,它应该可以工作。

【讨论】:

  • 试过了,图片没有更新。另外,你提到的那条线一开始并不存在,在寻找治疗方法时偶然发现了这种结构......
【解决方案2】:

仍然没有弄清楚导致问题的原因,但找到了解决方法,我已经像这样更改了我的Runnable(添加了picture.invalidate()):

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

现在ImageView 中的图像在每次执行Runnable 时都会正确更新,即使我使用的是postDelayed

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-29
    • 2014-05-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多