如何禁止在 GridView 中点击特定图像 - Android

How to disable the click of a specific image in GridView - Android

整晚都在复习逻辑,就是得不到答案。我需要我的可绘制占位符图像不可点击,并且我的真实图像(来自 SD 卡的照片)对于常规点击和长按都可以点击。我已经记录了关于如何编写 if 条件的一百万个版本,它会说这样的话:if the image Bitmap is the drawable and equal to the position clicked on,然后处理点击监听器。但这永远不可能发生!他们永远不平等。当我将可绘制位图与单击位置的位图进行比较时,Bitmap 数字总是不同(这对我来说毫无意义)。

所以我尝试了另一种方法。我想尝试使用我发现的方法 here 直接在其位置禁用可绘制对象。这些方法,我放在我的adapter中class.

@Override
    public boolean areAllItemsEnabled() {

        return false;
    }

    @Override
    public boolean isEnabled(int position) {
        return true;
    }

但是这些方法对我来说毫无意义。 Where/how 我会根据我的情况给他们打电话吗?我不明白这些应该如何禁用我的自定义 GridView 中的 select 项。如果您有任何想法,谢谢。

这是我来自 logcat. 的日志语句值 我通过单击 GridView 中的可绘制图像获得了这些值,但如您所见, 图片 Bitmap 和适配器位置项不一样。那么我如何识别我的可绘制对象以便我知道禁用那里的点击?

Value of adapter position item: android.graphics.Bitmap@430706e0
Value of drawableObject: android.graphics.Bitmap@4301fff0
Value of photoGridItem: android.graphics.Bitmap@4301a768

PhotoTab.java

package org.azurespot.cutecollection.phototab;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Environment;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ArrayAdapter;
import android.widget.GridView;

import org.azurespot.R;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.ArrayList;

/**
 * Created by mizu on 2/8/15.
 */
public class PhotoTab extends Fragment {

    private GridView gridView;
    File[] files;
    ArrayList<PhotoGridItem> photoList = new ArrayList<>();
    ArrayAdapter<PhotoGridItem> adapter;
    Bitmap bitmap;
    private String[] numberSDCardFiles = null;
    PhotoGridItem drawableObject;
    PhotoGridItem photoGridItem;

    public PhotoTab() {
        super();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        // Inflate the layout for this fragment
        View v = inflater.inflate(R.layout.photo_tab, container, false);

        adapter = new GridViewPhotoAdapter(getActivity(), photoList);
        // with fragments, make sure you include the rootView when finding id
        gridView = (GridView) v.findViewById(R.id.photo_grid);
        gridView.setAdapter(adapter);

        if(adapter.getCount() == 0) {
            // load contents of SD card
            loadSDCard();

            // add the default icons remaining, to GridView, if less than 24 files on SD card
            for (int i = 0; i < (24 - numberSDCardFiles.length); i++) {
                drawableObject = new PhotoGridItem(BitmapFactory.decodeResource(getResources(),
                        R.drawable.ic_photo_placeholder));

                adapter.add(drawableObject);
                adapter.notifyDataSetChanged();

            }

        }

        setupGridViewListener();

        return v;
    }


    public void loadSDCard() {

        try {
            // gets directory CutePhotos from sd card
            File cutePhotosDir = new File(Environment.getExternalStoragePublicDirectory
                    (Environment.DIRECTORY_PICTURES), "Cute Photos");
            // lists all files in CutePhotos, loads in Files[] array
            files = cutePhotosDir.listFiles();

            for (File singleFile : files) {

                String filePath = singleFile.getAbsolutePath();
                // this method makes size small for the view (to save memory)
                bitmap = decodeImageBitmap(filePath, 270, 270);
                photoGridItem = new PhotoGridItem(bitmap);
                // Check if this is a new bitmap file
                adapter.add(photoGridItem);
                adapter.notifyDataSetChanged();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        // get number of files in Cute Photos directory
        numberSDCardFiles =  new String[files.length];

    }


    private void setupGridViewListener(){
        gridView.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView,
                                    View item, int pos, long id) {



                //Convert the bitmap to byte array, so can pass through intent
                ByteArrayOutputStream stream = new ByteArrayOutputStream();
                Bitmap bm = adapter.getItem(pos).getImage();
                bm.compress(Bitmap.CompressFormat.PNG, 100, stream);
                final byte[] byteArray = stream.toByteArray();

                Intent i = new Intent(getActivity(), PhotoViewerActivity.class);
                i.putExtra("photo", byteArray);
                startActivity(i);

                Log.d("TAG", "Value of bm: " + bm);
                Log.d("TAG", "Value of adapter position item: " + adapter.getItem(pos));
                Log.d("TAG", "Value of drawableObject: " + drawableObject);


            }

        });

        // to delete a photo item
        gridView.setOnItemLongClickListener(new OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> aView, View item,
                                           final int pos, long id) {

                new AlertDialog.Builder(getActivity())
                        .setTitle("Delete")
                        .setMessage("Delete this cute photo?")
                        .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) {
                                // delete from ArrayList first
                                photoList.remove(pos);

                                // get file name then delete it from SD card
                                String name = files[pos].getName();
                                File file = new File(Environment.getExternalStoragePublicDirectory
                                  (Environment.DIRECTORY_PICTURES), "Cute Photos" + "/" + name);
                                file.delete();

                                // after each item delete, replace with default icon
                                adapter.add(new PhotoGridItem(BitmapFactory.decodeResource(getResources(),
                                R.drawable.ic_photo_placeholder)));
                                adapter.notifyDataSetChanged();
                            }
                        })
                        .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) {

                                // do nothing
                                dialog.cancel();
                            }
                        })
                        .setIcon(android.R.drawable.ic_dialog_alert)
                        .show();

                return true;
            }
        });
    }

    // next 2 methods scale the bitmap image to a better size (so not huge)
    public 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) {

            if (width > height) {
                inSampleSize = Math.round((float)height / (float)reqHeight);
            } else {
                inSampleSize = Math.round((float)width / (float)reqWidth);
            }
        }
        return inSampleSize;
    }

    public static Bitmap decodeImageBitmap(String path, int reqWidth, int reqHeight) {
        // First decode with inJustDecodeBounds=true to check dimensions
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(path, options);

        // Calculate inSampleSize
        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
        Bitmap bm = BitmapFactory.decodeFile(path, options);

        return bm;
    }


}

GridViewPhotoAdapter.java

package org.azurespot.cutecollection.phototab;

/**
* Created by mizu on 2/5/15.
*/
// package org.azurespot.cutecollection;

import android.content.Context;
import android.graphics.Bitmap;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;

import org.azurespot.R;

import java.util.ArrayList;

/**
 * Created by mizu on 2/5/15.
 */
public class GridViewPhotoAdapter extends ArrayAdapter<PhotoGridItem> {

    ViewHolder holder = null;
    int position;

    public GridViewPhotoAdapter(Context context, ArrayList<PhotoGridItem> photos) {
        super(context, 0, photos);

    }

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

        View v = convertView;
        this.position = position;

        if (v == null) {

            v = LayoutInflater.from(getContext())
                            .inflate(R.layout.photo_grid_item, parent, false);

            holder = new ViewHolder();
            holder.imageView = (ImageView) v.findViewById(R.id.photo_grid_view);
            // stores holder with view
            v.setTag(holder);

        } else {

            holder = (ViewHolder)v.getTag();
        }

        // gets position of whichever photo you click on in the GridView
        final PhotoGridItem photoGridItem = getItem(position);

        if (photoGridItem != null) {
            Bitmap bm = photoGridItem.getImage();
            holder.imageView.setImageBitmap(bm);

            // positioning the image in the GridView slot
            holder.imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
            holder.imageView.setLayoutParams(new LinearLayout.LayoutParams(270, 270));
        }


        return v;

    }

    public class ViewHolder{
        ImageView imageView;
    }

    @Override
    public boolean areAllItemsEnabled() {

        return false;
    }

    @Override
    public boolean isEnabled(int position) {
        return true;
    }

}

在 IsEnabled 方法中添加您的逻辑,如下所示

@Override
public boolean isEnabled(int position) {
    if(position == POSITION_U_WANT_TO_DISABLE) {
      return false;
    }
    return true;
}

根据您的代码,您总是在该方法中返回 true(已启用)。

难以置信,但我终于找到了正确的逻辑。我不需要上面提到的 2 个 List 方法,因为这些方法依赖于我在 GridView 定位中识别可绘制对象与照片。因此,在将我的占位符可绘制对象添加到我的网格时,我还将它们全部放入 ArrayList<Bitmap> 中,以便我可以搜索列表并在需要时提取可绘制对象的值。

然后我在点击侦听器的代码中添加了一个条件,如果我的 ArrayListBitmaps 包含在被点击的视图位置找到的位图,则不要继续执行点击侦听器的代码。如果它不包含 ArrayList 中的 Bitmap,则继续处理它。

我检查了我是否仍然可以在 GridView 中添加和删除项目并且仍然可以进行有条件的工作,我确实可以。以下是上下文中的新增内容。

ArrayList<Bitmap> bmList = new ArrayList<>();

...

    // add the default icons remaining, to GridView, if less than 24 files on SD card
    for (int i = 0; i < (24 - numberSDCardFiles.length); i++) {
        drawableObject = new PhotoGridItem(BitmapFactory.decodeResource(getResources(),
                    R.drawable.ic_photo_placeholder));

        // adds each drawable Bitmap to an ArrayList
        bmList.add(drawableObject.getImage());
        // adds to adapter
        adapter.add(drawableObject);
        adapter.notifyDataSetChanged();
     }

...

private void setupGridViewListener(){
        gridView.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView,
                                    View item, int pos, long id) {

                if(!bmList.contains(adapter.getItem(pos).getImage())) {
                    //Convert the bitmap to byte array, so can pass through intent
                    ByteArrayOutputStream stream = new ByteArrayOutputStream();
                    Bitmap bm = adapter.getItem(pos).getImage();
                    bm.compress(Bitmap.CompressFormat.PNG, 100, stream);
                    final byte[] byteArray = stream.toByteArray();

                    Intent i = new Intent(getActivity(), PhotoViewerActivity.class);
                    i.putExtra("photo", byteArray);
                    startActivity(i);
                }
            }

        });