简体   繁体   中英

ImageViews custom checkboxes repeats itself randomly

I have a gridview with an adapter, which also has a checkbox look to be shown when an imageview has been clicked. But something goes wrong. If an image is checked and you scroll to the bottom, one of the images are also checked. If you scroll up again, another image than the one you clicked to begin with, is checked (in most cases).

So here is the code for my adapter. The code in concern is the getView method:

public class ImageAdapter extends BaseAdapter {

    private Context context;
    private ArrayList<String> files;
    private Bitmap mPlaceHolderBitmap;
    private File directory;
    private int thumbSize;
    private GridImageListener gridImageListener;
    private LayoutInflater inflater;
    private View rootView;
    private final int MAX_PICTURE_LIMIT = 5;
    private int picturesChosenCount = 0;

    public ImageAdapter(Context context, ArrayList<String> files, File directory, int thumbSize, GridImageListener gridImageListener, LayoutInflater inflater, View rootView) {
        super();
        this.context    = context;
        this.files      = files;
        this.directory  = directory;
        this.thumbSize = thumbSize;
        this.gridImageListener = gridImageListener;
        this.inflater = inflater;
        this.rootView = rootView;

        mPlaceHolderBitmap = drawableToBitmap(context.getResources().getDrawable(R.drawable.logo));
    }

    public Bitmap drawableToBitmap (Drawable drawable) {

        if (drawable instanceof BitmapDrawable) {
            return ((BitmapDrawable)drawable).getBitmap();
        }

        Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
        drawable.draw(canvas);

        return bitmap;
    }

    @Override
    public int getCount() {
        return files.size();
    }

    @Override
    public Object getItem(int position) {
        return files.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup container) {

        final ViewHolder holder;

        if (convertView == null) { // if it's not recycled, initialize some attributes
            holder = new ViewHolder();

            convertView = inflater.inflate(R.layout.component_imageview_checkable, null);
            holder.imageview = (ImageView) convertView.findViewById(R.id.checkableImageView);
            holder.imageview.getLayoutParams().height  = thumbSize;
            holder.imageview.getLayoutParams().width   = thumbSize;
            holder.imageCheckBox = (RelativeLayout) convertView.findViewById(R.id.image_check_view);

            loadBitmap(files.get(position), holder.imageview);

            convertView.setTag(holder);

        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        holder.imageCheckBox.setId(position);
        holder.imageview.setId(position);


        holder.imageview.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                    if (holder.imageCheckBox.getVisibility() == View.VISIBLE) {
                        holder.imageCheckBox.setVisibility(View.INVISIBLE);
                        picturesChosenCount--;
                    } else {
                        if (picturesChosenCount < 5) {
                            holder.imageCheckBox.setVisibility(View.VISIBLE);
                            picturesChosenCount++;
                        } else {
                            Toast.makeText(context, "Max number of pictures has been reached", Toast.LENGTH_SHORT).show();
                        }
                    }

                gridImageListener.onClickImage(files.get(position));
            }
        });

        holder.id = position;

        return convertView;
    }

    public void loadBitmap(String path, ImageView imageView) {

        if (cancelPotentialWork(path, imageView)) {
            final BitmapWorkerTask task = new BitmapWorkerTask(imageView, context, path, directory, thumbSize);
            final AsyncDrawable asyncDrawable =
                    new AsyncDrawable(context.getResources(), mPlaceHolderBitmap, task);
            imageView.setImageDrawable(asyncDrawable);
            task.execute(path);
        }
    }

    public static boolean cancelPotentialWork(String path, ImageView imageView) {
        final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);

        if (bitmapWorkerTask != null) {
            final String bitmapData = bitmapWorkerTask.path;
            // If bitmapData is not yet set or it differs from the new data
            if (bitmapData.equals("0") || !bitmapData.equals(path)) {
                // Cancel previous task
                bitmapWorkerTask.cancel(true);
            } else {
                // The same work is already in progress
                return false;
            }
        }
        // No task associated with the ImageView, or an existing task was cancelled
        return true;
    }

    private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) {
        if (imageView != null) {
            final Drawable drawable = imageView.getDrawable();
            if (drawable instanceof AsyncDrawable) {
                final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
                return asyncDrawable.getBitmapWorkerTask();
            }
        }
        return null;
    }


    static class AsyncDrawable extends BitmapDrawable {
        private final WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference;

        public AsyncDrawable(Resources res, Bitmap bitmap,
                             BitmapWorkerTask bitmapWorkerTask) {
            super(res, bitmap);
            bitmapWorkerTaskReference =
                    new WeakReference<BitmapWorkerTask>(bitmapWorkerTask);
        }

        public BitmapWorkerTask getBitmapWorkerTask() {
            return bitmapWorkerTaskReference.get();
        }
    }
}

class ViewHolder {
    int id;
    ImageView imageview;
    RelativeLayout imageCheckBox;
}

I know it has something to do with the recycling of views in the gridview, but I don't know how to avoid/fix it. Each imageview is loaded separately in an asynctask and is reloaded when you scroll to it. If you need to take a look at it, the code is here: http://pastebin.com/2BcBW7PN

And finally, here is my XML for the item of each image:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/checkableImageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:scaleType="centerCrop"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" />

    <RelativeLayout
        android:id="@+id/image_check_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/checkableImageView"
        android:layout_alignTop="@+id/checkableImageView"
        android:layout_alignRight="@+id/checkableImageView"
        android:layout_alignBottom="@+id/checkableImageView"
        android:visibility="invisible">

        <com.ivankocijan.magicviews.views.MagicTextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:textColor="@color/white"
            android:background="@drawable/blue_border"
            android:layout_alignParentTop="true"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true" />

        <com.ivankocijan.magicviews.views.MagicTextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/icon_check"
            android:textColor="@color/white"
            android:textSize="@dimen/txtsize_standard_smaller_icon"
            android:padding="4dp"
            app:typeFace="@string/icon_font"
            android:background="@color/standard_blue"
            android:layout_alignParentTop="true"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true" />

    </RelativeLayout>
  </RelativeLayout>

What might be wrong? I have read all the tutorials I could find, but none of them seemed to do any difference.

You can use : Eg: Android – Select multiple photos from Gallery

Or :

Entity -CustomGallery.class

public class CustomGallery {

public String sdcardPath;
public boolean isSeleted = false;

}

Adapter -GalleryAdapterCustom.class

private Context mContext;
private LayoutInflater infalter;
private ArrayList<CustomGallery> data = new ArrayList<CustomGallery>();
ImageLoader imageLoader;

private boolean isActionMultiplePick;

public GalleryAdapterCustom(Context c, ImageLoader imageLoader) {
    infalter = (LayoutInflater) c
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    mContext = c;
    this.imageLoader = imageLoader;
    // clearCache();
}

@Override
public int getCount() {
    return data.size();
}

@Override
public CustomGallery getItem(int position) {
    return data.get(position);
}

@Override
public long getItemId(int position) {
    return position;
}

public void setMultiplePick(boolean isMultiplePick) {
    this.isActionMultiplePick = isMultiplePick;
}

public void selectAll(boolean selection) {
    for (int i = 0; i < data.size(); i++) {
        data.get(i).isSeleted = selection;

    }
    notifyDataSetChanged();
}

public boolean isAllSelected() {
    boolean isAllSelected = true;

    for (int i = 0; i < data.size(); i++) {
        if (!data.get(i).isSeleted) {
            isAllSelected = false;
            break;
        }
    }

    return isAllSelected;
}

public boolean isAnySelected() {
    boolean isAnySelected = false;

    for (int i = 0; i < data.size(); i++) {
        if (data.get(i).isSeleted) {
            isAnySelected = true;
            break;
        }
    }

    return isAnySelected;
}

public ArrayList<CustomGallery> getSelected() {
    ArrayList<CustomGallery> dataT = new ArrayList<CustomGallery>();

    for (int i = 0; i < data.size(); i++) {
        if (data.get(i).isSeleted) {
            dataT.add(data.get(i));
        }
    }

    return dataT;
}

public void addAll(ArrayList<CustomGallery> files) {

    try {
        this.data.clear();
        this.data.addAll(files);

    } catch (Exception e) {
        e.printStackTrace();
    }

    notifyDataSetChanged();
}

public void changeSelection(View v, int position) {

    if (data.get(position).isSeleted) {
        data.get(position).isSeleted = false;
    } else {
        data.get(position).isSeleted = true;

    }

    ArrayList<CustomGallery> dataT = new ArrayList<CustomGallery>();

    for (int i = 0; i < data.size(); i++) {
        if (data.get(i).isSeleted) {
            dataT.add(data.get(i));
        }
    }

    if (dataT.size() > NewPostActivity.max_image) {

        Toast.makeText(mContext, "Bạn chỉ được đăng tối đa 20 ảnh / 1 tin",
                Toast.LENGTH_SHORT).show();
        data.get(position).isSeleted = false;
    }

    ((ViewHolder) v.getTag()).imgQueueMultiSelected.setSelected(data
            .get(position).isSeleted);
    // }

}

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    final ViewHolder holder;
    if (convertView == null) {

        convertView = infalter.inflate(R.layout.gallery_item, null);
        holder = new ViewHolder();
        holder.imgQueue = (ImageView) convertView
                .findViewById(R.id.imgQueue);

        holder.imgQueueMultiSelected = (ImageView) convertView
                .findViewById(R.id.imgQueueMultiSelected);

        if (isActionMultiplePick) {
            holder.imgQueueMultiSelected.setVisibility(View.VISIBLE);
        } else {
            holder.imgQueueMultiSelected.setVisibility(View.GONE);
        }

        convertView.setTag(holder);

    } else {
        holder = (ViewHolder) convertView.getTag();
    }
    holder.imgQueue.setTag(position);

    try {

        imageLoader.displayImage("file://" + data.get(position).sdcardPath,
                holder.imgQueue, new SimpleImageLoadingListener() {
                    @Override
                    public void onLoadingStarted(String imageUri, View view) {
                        holder.imgQueue
                                .setImageResource(R.drawable.default_icon2);
                        super.onLoadingStarted(imageUri, view);
                    }
                });

        if (isActionMultiplePick) {

            holder.imgQueueMultiSelected
                    .setSelected(data.get(position).isSeleted);

        }

    } catch (Exception e) {
        e.printStackTrace();
    }

    return convertView;
}

public class ViewHolder {
    ImageView imgQueue;
    ImageView imgQueueMultiSelected;
}

public void clearCache() {
    imageLoader.clearDiscCache();
    imageLoader.clearMemoryCache();
}

public void clear() {
    data.clear();
    notifyDataSetChanged();
}

}

Activity- CustomGalleryActivity.class

public class CustomGalleryActivity extends Activity {
GridView gridGallery;
Handler handler;
GalleryAdapterCustom adapter;
String count_image;
RelativeLayout layout_select, layout_cancel;
ImageView imgNoMedia;
Button btnGalleryOk;
public static final int REQUEST_CODE_Gallery = 1111;
public static final int REQUEST_CODE_Gallery_OK = 2222;
String action;
private ImageLoader imageLoader;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    setContentView(R.layout.gallery);

    action = getIntent().getStringExtra("action");
    if (action == null) {
        finish();
    }
    initImageLoader();
    init();
}

private void initImageLoader() {
    try {
        String CACHE_DIR = Environment.getExternalStorageDirectory()
                .getAbsolutePath() + "/.temp_tmp";
        new File(CACHE_DIR).mkdirs();

        File cacheDir = StorageUtils.getOwnCacheDirectory(getBaseContext(),
                CACHE_DIR);

        DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder()
                .cacheOnDisc(true).imageScaleType(ImageScaleType.EXACTLY)
                .bitmapConfig(Bitmap.Config.RGB_565).build();
        ImageLoaderConfiguration.Builder builder = new ImageLoaderConfiguration.Builder(
                getBaseContext())
                .defaultDisplayImageOptions(defaultOptions)
                .discCache(new UnlimitedDiscCache(cacheDir))
                .memoryCache(new WeakMemoryCache());

        ImageLoaderConfiguration config = builder.build();
        imageLoader = ImageLoader.getInstance();
        imageLoader.init(config);

    } catch (Exception e) {

    }
}

private void init() {

    handler = new Handler();
    gridGallery = (GridView) findViewById(R.id.gridGallery);
    gridGallery.setFastScrollEnabled(true);
    adapter = new GalleryAdapterCustom(getApplicationContext(), imageLoader);
    PauseOnScrollListener listener = new PauseOnScrollListener(imageLoader,
            true, true);
    gridGallery.setOnScrollListener(listener);

    if (action.equalsIgnoreCase(Action.ACTION_MULTIPLE_PICK)) {

        findViewById(R.id.layout_select).setVisibility(View.VISIBLE);
        gridGallery.setOnItemClickListener(mItemMulClickListener);
        adapter.setMultiplePick(true);

    } else if (action.equalsIgnoreCase(Action.ACTION_PICK)) {

        findViewById(R.id.layout_select).setVisibility(View.GONE);
        gridGallery.setOnItemClickListener(mItemSingleClickListener);
        adapter.setMultiplePick(false);

    }

    gridGallery.setAdapter(adapter);
    imgNoMedia = (ImageView) findViewById(R.id.imgNoMedia);
    layout_cancel = (RelativeLayout) findViewById(R.id.layout_cancel);

    layout_cancel.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            finish();
        }
    });

    layout_select = (RelativeLayout) findViewById(R.id.layout_select);

    layout_select.setOnClickListener(mOkClickListener);

    new Thread() {

        @Override
        public void run() {
            Looper.prepare();
            handler.post(new Runnable() {

                @Override
                public void run() {
                    adapter.addAll(getGalleryPhotos());
                    checkImageStatus();
                }
            });
            Looper.loop();
        };

    }.start();

}

private void checkImageStatus() {
    if (adapter.isEmpty()) {
        imgNoMedia.setVisibility(View.VISIBLE);
    } else {
        imgNoMedia.setVisibility(View.GONE);
    }
}

View.OnClickListener mOkClickListener = new View.OnClickListener() {

    @Override
    public void onClick(View v) {
        ArrayList<CustomGallery> selected = adapter.getSelected();

        String[] allPath = new String[selected.size()];
        for (int i = 0; i < allPath.length; i++) {
            allPath[i] = selected.get(i).sdcardPath;
        }
        if (allPath.length == 0) {
            Toast.makeText(CustomGalleryActivity.this, "Vui lòng chọn ảnh",
                    Toast.LENGTH_SHORT).show();
        } else {
            Intent data = new Intent().putExtra("all_path", allPath);
            setResult(REQUEST_CODE_Gallery_OK, data);
            finish();
        }
    }
};
AdapterView.OnItemClickListener mItemMulClickListener = new AdapterView.OnItemClickListener() {

    @Override
    public void onItemClick(AdapterView<?> l, View v, int position, long id) {
        adapter.changeSelection(v, position);

    }
};

AdapterView.OnItemClickListener mItemSingleClickListener = new AdapterView.OnItemClickListener() {

    @Override
    public void onItemClick(AdapterView<?> l, View v, int position, long id) {
        CustomGallery item = adapter.getItem(position);
        Intent data = new Intent().putExtra("single_path", item.sdcardPath);
        setResult(REQUEST_CODE_Gallery_OK, data);
        finish();
    }
};

private ArrayList<CustomGallery> getGalleryPhotos() {
    ArrayList<CustomGallery> galleryList = new ArrayList<CustomGallery>();

    try {
        final String[] columns = { MediaStore.Images.Media.DATA,
                MediaStore.Images.Media._ID };
        final String orderBy = MediaStore.Images.Media._ID;

        Cursor imagecursor = managedQuery(
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns,
                null, null, orderBy);

        if (imagecursor != null && imagecursor.getCount() > 0) {

            while (imagecursor.moveToNext()) {
                CustomGallery item = new CustomGallery();

                int dataColumnIndex = imagecursor
                        .getColumnIndex(MediaStore.Images.Media.DATA);

                item.sdcardPath = imagecursor.getString(dataColumnIndex);

                galleryList.add(item);
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

    // show newest photo at beginning of the list
    Collections.reverse(galleryList);
    return galleryList;
}

Use .

Intent i = new Intent(NewPostActivity.this,
                        CustomGalleryActivity.class);
                i.putExtra("action", Action.ACTION_MULTIPLE_PICK);
                startActivityForResult(i, REQUEST_CODE_Gallery);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM