当我点击其他屏幕元素时,如何防止此Android列表视图中的图像移动?

时间:2022-04-29 21:13:34

I made another post earlier about this subject but I've since changed my code around a bit based on suggestions but the same problem exists. My images keep shifting around if I click other elements on screen.

我之前发过另一篇关于这个主题的帖子,但我已经基于建议改变了我的代码,但存在同样的问题。如果我点击屏幕上的其他元素,我的图像会继续移动。

Here is my code which I call by this:

这是我的代码,我称之为:

new Thumbnailer(image_main, image_table).execute(image);

new Thumbnailer(image_main,image_table).execute(image);

image_main is my imageView and image_table is the table that holds it.

image_main是我的imageView,image_table是保存它的表。

 private class Thumbnailer extends AsyncTask<String, Void, Bitmap> {
      private ImageView imageView;
      private TableLayout imageTable;

        public Thumbnailer(ImageView imageView, TableLayout imageTable) {
            this.imageView = imageView;
            this.imageTable = imageTable;
        }

  @Override
  protected void onPostExecute(Bitmap result) {
      imageView.setImageBitmap(result);
               imageView.setVisibility(View.VISIBLE);
               imageTable.setVisibility(View.VISIBLE);
  }
  @Override
      protected void onProgressUpdate(Void... progress) {
      }

  @Override
  protected Bitmap doInBackground(String... params) {
         BitmapFactory.Options o = new BitmapFactory.Options();
          o.inJustDecodeBounds = true;
          BitmapFactory.decodeFile(params[0], o);
          final int REQUIRED_SIZE=70;

          //Find the correct scale value. It should be the power of 2.
          int width_tmp=o.outWidth, height_tmp=o.outHeight;
          int scale=1;
          while(true){
              if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
                  break;
              width_tmp/=2;
              height_tmp/=2;
              scale++;
          }
          //Decode with inSampleSize
          BitmapFactory.Options o2 = new BitmapFactory.Options();
          o2.inSampleSize=scale;       
          return BitmapFactory.decodeFile(params[0], o2);
  }
 }

3 个解决方案

#1


4  

Sounds like you're getting bitten by view recycling. That is, when you scroll a List in Android, it doesn't create a new row and instead reuses a row taken offscreen. In this case, that can result in multiple tasks trying to load an image into a single imageview. You effectively need to somehow be able to tell which load request is the most recent for a row and cancel the earlier ones/ignore their results, or just use a library that handles this for you (like droid-fu).

听起来像你被视图回收所咬。也就是说,当您在Android中滚动列表时,它不会创建新行,而是重新使用屏幕外的行。在这种情况下,这可能导致多个任务尝试将图像加载到单个图像视图中。你有效地需要能够以某种方式告诉哪一个加载请求是最新的行并取消之前的那些/忽略它们的结果,或者只是使用一个为你处理这个的库(如droid-fu)。

You could also just turn off view recycling in your Adapter (that's the part that uses the convertView argument in the getView method), but be aware this will make list scrolling slow and jittery, especially on older devices.

您也可以在适配器中关闭视图回收(这是在getView方法中使用convertView参数的部分),但请注意,这会使列表滚动缓慢且抖动,尤其是在旧设备上。

#2


5  

I had a similar problem. I would load images into a ListView via an AsyncTask (which might fetch the image via HTTP), and it seemed to load the wrong image for a split second before loading the correct one. It was as if Android was reusing the row before the HTTP request finished, and the AsyncTasks were kind of colliding.

我有类似的问题。我会通过AsyncTask(可能通过HTTP获取图像)将图像加载到ListView中,并且在加载正确的图像之前,它似乎加载错误的图像一瞬间。就好像Android在HTTP请求完成之前重用行一样,并且AsyncTasks有点碰撞。

The comments above confirmed that is what was happening.

上面的评论证实了正在发生的事情。

I fixed it by placing the image path in the tag of the ImageView before the AsyncTask starts, and then checking that tag after the AsyncTask finishes but just before it calls setImageBitmap.

我通过在AsyncTask启动之前将图像路径放在ImageView的标记中来修复它,然后在AsyncTask完成之后但在它调用setImageBitmap之前检查该标记。

Add these lines:

添加以下行:

final String somethingUnique = "put the image path or some other identifier here";
image_main.setTag(somethingUnique);

Before this line:

在此之前:

new Thumbnailer(image_main, image_table).execute(image);

Now, in onPostExecute, check the tag:

现在,在onPostExecute中,检查标记:

// if this does not match, then the view has probably been reused
if (((String)imageView.getTag()).equals(somethingUnique)) {
  imageView.setImageBitmap(result);
}

#3


0  

This Android Developer's blog post provides a reference project for this. Just change the http image download code in the project to your doInBackground code.

这个Android Developer的博客文章提供了一个参考项目。只需将项目中的http映像下载代码更改为doInBackground代码即可。

#1


4  

Sounds like you're getting bitten by view recycling. That is, when you scroll a List in Android, it doesn't create a new row and instead reuses a row taken offscreen. In this case, that can result in multiple tasks trying to load an image into a single imageview. You effectively need to somehow be able to tell which load request is the most recent for a row and cancel the earlier ones/ignore their results, or just use a library that handles this for you (like droid-fu).

听起来像你被视图回收所咬。也就是说,当您在Android中滚动列表时,它不会创建新行,而是重新使用屏幕外的行。在这种情况下,这可能导致多个任务尝试将图像加载到单个图像视图中。你有效地需要能够以某种方式告诉哪一个加载请求是最新的行并取消之前的那些/忽略它们的结果,或者只是使用一个为你处理这个的库(如droid-fu)。

You could also just turn off view recycling in your Adapter (that's the part that uses the convertView argument in the getView method), but be aware this will make list scrolling slow and jittery, especially on older devices.

您也可以在适配器中关闭视图回收(这是在getView方法中使用convertView参数的部分),但请注意,这会使列表滚动缓慢且抖动,尤其是在旧设备上。

#2


5  

I had a similar problem. I would load images into a ListView via an AsyncTask (which might fetch the image via HTTP), and it seemed to load the wrong image for a split second before loading the correct one. It was as if Android was reusing the row before the HTTP request finished, and the AsyncTasks were kind of colliding.

我有类似的问题。我会通过AsyncTask(可能通过HTTP获取图像)将图像加载到ListView中,并且在加载正确的图像之前,它似乎加载错误的图像一瞬间。就好像Android在HTTP请求完成之前重用行一样,并且AsyncTasks有点碰撞。

The comments above confirmed that is what was happening.

上面的评论证实了正在发生的事情。

I fixed it by placing the image path in the tag of the ImageView before the AsyncTask starts, and then checking that tag after the AsyncTask finishes but just before it calls setImageBitmap.

我通过在AsyncTask启动之前将图像路径放在ImageView的标记中来修复它,然后在AsyncTask完成之后但在它调用setImageBitmap之前检查该标记。

Add these lines:

添加以下行:

final String somethingUnique = "put the image path or some other identifier here";
image_main.setTag(somethingUnique);

Before this line:

在此之前:

new Thumbnailer(image_main, image_table).execute(image);

Now, in onPostExecute, check the tag:

现在,在onPostExecute中,检查标记:

// if this does not match, then the view has probably been reused
if (((String)imageView.getTag()).equals(somethingUnique)) {
  imageView.setImageBitmap(result);
}

#3


0  

This Android Developer's blog post provides a reference project for this. Just change the http image download code in the project to your doInBackground code.

这个Android Developer的博客文章提供了一个参考项目。只需将项目中的http映像下载代码更改为doInBackground代码即可。