【问题标题】:The setOnItemLongClickListener in GridView is not clickableGridView 中的 setOnItemLongClickListener 不可点击
【发布时间】:2015-03-25 06:15:50
【问题描述】:

我已经尝试了所有可以在 SO 上找到的建议,并且我能够在我的 ListView 上成功使用这个确切的代码,但由于某种原因,我无法在我的 @987654322 上设置长点击监听器@。我在方法setupGridViewListener(); 中登录,它甚至没有运行,但我在onCreateView() 中有我的方法。不知道为什么它不起作用。长按后应该会弹出警告对话框,但不会。方法在我的班级底部。

更新:

我没有提到我的onClickListener 工作正常。所以我至少可以单击一下,这会显示我的活动。但是,该代码在我的适配器中,所以也许它们应该在同一个类中?我包括我的适配器和下面的 2 个xmls。

更新 2 我发现了几件值得一提的事情,即使在我的代码再次运行之后也是如此。首先,将我的点击监听器放入我的适配器是一个错误。它大大减慢了速度……如此之多,我很想找到一种方法将事情放在另一个线程上。但最后,我不需要。我意识到我实际上可以让我的两个点击监听器进入我的PhotoTab.java 类。这立即使它更快(恢复正常)。但另一个奇怪的事情是,IDE 不让我使用OnClickListener,而是坚持让我回到OnItemClickListener。所以一旦我把它们改回来,一切都恢复了。所以听众最终在我的GridView变量上,例如gridView.setOnItemClickListener(new OnItemClickListener() {} 不是我的 ImageView 项目变量。也许这就是让事情变得更快的原因?有一个GridView,但有24 个ImageViews(GridView 单元格)。但这只是一个猜测。我已将我的代码更新为当前的工作代码。除了我还在处理长点击代码,所以这还不正确。不过,对话框警报有效,GridView 中的每个项目都是可点击的。

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.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;
    byte[] byteArray = null;
    private String[] allSDCardFiles = null;

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

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

        // this null check won't instantiate again if it was already
//        if(adapter == null)
        adapter = new GridViewPhotoAdapter(getActivity(), R.layout.photo_grid_item);

        // Set the Adapter to GridView
        gridView.setAdapter(adapter);

        // 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 - allSDCardFiles.length); i++) {
            adapter.add(new PhotoGridItem(BitmapFactory.decodeResource(getResources(),
                    R.drawable.ic_photo_placeholder)));
            adapter.notifyDataSetChanged();
            i++;
        }

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

        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
        allSDCardFiles =  new String[files.length];

    }



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

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

        });

        // 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
//                                PhotoTab.photoList.remove(position);

                                // get file name then delete it from SD card
                                File cutePhotosDir = new File(Environment.getExternalStoragePublicDirectory
                                        (Environment.DIRECTORY_PICTURES), "CutePhotos/" + photoGridItem);
                                cutePhotosDir.delete();


                                // after each item delete, must refresh load so can delete again
//                                photoTab.loadSDCard();
                            }
                        })
                        .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

    package org.azurespot.cutecollection.phototab;

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

import android.app.Activity;
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;

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

    public Context context;
    private int resourceId;
    ViewHolder holder = null;
    int position;

    public GridViewPhotoAdapter(Context context, int layoutResourceId) {
        super(context, layoutResourceId);
        this.context = context;
        this.resourceId = layoutResourceId;
    }

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

        View row = convertView;
        this.position = position;

        if (row == null) {

            LayoutInflater inflater = ((Activity) context).getLayoutInflater();
            row = inflater.inflate(resourceId, parent, false);

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

        } else {

            holder = (ViewHolder)row.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 row;

    }

    public class ViewHolder{
        ImageView imageView;
    }

}

photo_tab.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/root_view"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#2198bb">

    <GridView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/photo_grid"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true"
        android:verticalSpacing="5dp"
        android:horizontalSpacing="2dp"
        android:layout_marginLeft="5dp"
        android:layout_marginRight="5dp"
        android:layout_marginTop="25dp"
        android:columnWidth="100dp"
        android:gravity="center"
        android:numColumns="auto_fit"
        android:stretchMode="columnWidth"
        android:scrollbarStyle="outsideOverlay"
        android:verticalScrollbarPosition="right" />

</RelativeLayout>

photo_grid_item.xml

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

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/photo_grid_view"
        android:focusable="false"
        android:focusableInTouchMode="false"/>
</LinearLayout>

【问题讨论】:

  • 您好,我查看了您的代码,您想在长按网格视图项目时删除照片。您只需单击即可正常工作,因为您在图像单击中实现了。我建议不要尝试捕捉网格视图长按你可以使用图像视图长按监听器。 :)
  • 感谢 Bhavdip,另一位发帖人建议这样做,它奏效了! :)
  • @Noni,我喜欢你的 cmets 关于在适配器中设置侦听器的错误。这似乎很正常(您之前所做的),我已经为 ListView 这样做了,而不是 GridView。 Google 已在 ListView 的适配器中推荐了侦听器。我不知道使用 GridView 会如此不同。现在您在适配器之外设置了侦听器,我怀疑您当前的技术会占用更多内存,但可能不会太多。
  • 是的,这是一个令人惊讶的发现。可能我仍然应该将图像加载过程放入AsyncTask 或其他类型的Thread,但是当我将所有内容放入PhotoTab.java 类而不是适配器类时,它显示出显着的变化。不过,感谢您的额外见解!

标签: android android-gridview onitemclicklistener onitemlongclicklistener


【解决方案1】:
package com.example.slideanim;

import java.util.ArrayList;

import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.Toast;

public class MyGridAdapter extends BaseAdapter {
    private ArrayList<String> list = new ArrayList<String>();
    private Activity activity;
    private LayoutInflater layoutInflater;

    public MyGridAdapter(Activity activity, ArrayList<String> list) {
        // TODO Auto-generated constructor stub
        this.activity = activity;
        this.list = list;
        layoutInflater = activity.getLayoutInflater();
    }

    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return list.size();
    }

    @Override
    public Object getItem(int arg0) {
        // TODO Auto-generated method stub
        return list.get(arg0);
    }

    @Override
    public long getItemId(int arg0) {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public View getView(int pos, View convertView, ViewGroup arg2) {
        // TODO Auto-generated method stub
        ViewHolder holder = null;
        if (convertView == null) {
            holder = new ViewHolder();
            convertView = layoutInflater.inflate(R.layout.row, null);
            holder.imageView = (ImageView) convertView
                    .findViewById(R.id.photo_grid_view);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        holder.imageView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
            }
        });

        holder.imageView.setOnLongClickListener(new OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                // TODO Auto-generated method stub
                Toast.makeText(activity, "got", Toast.LENGTH_SHORT).show();
                return true;
            }
        });

        return convertView;
    }

    private static class ViewHolder {
        public ImageView imageView;
    }

}

【讨论】:

  • 请发布您的行项目 xml 以获得更好的答案。
  • 谢谢,我已经更新了我的代码。顺便说一句,您的代码中发生了什么?我不明白你的建议,谢谢。
  • 好的,谢谢,我现在正在尝试这样做。得到很多错误。 :( 但很高兴知道你认为这是问题所在。我会告诉你情况如何。
  • 我在适配器类中添加了长按监听器。看看吧。
  • 天哪,非常感谢。我不知何故导入了AdapterView.onItemClickListener 版本,而不是View.onClickListener,它给了我到处都是错误。 Android Studio 并不总是更新您的导入,所以我真的很高兴您向我展示了正确的!仍然无法删除我的文件,但这是另一个问题。我在我的适配器类中获得了两个点击监听器,这可不是小事!我的长按会弹出对话框警报,就像它应该的那样。谢谢你。 :) 感激不尽。
【解决方案2】:

对 imageview 使用 click 和 long click 会更好,或者在 gridview 项上同时使用两者。

如果你想在 imageview 上,不要设置 GridViewListener 并在你的适配器中尝试这个:

holder.imageView.setOnLongClickListener(new View.OnLongClickListener() {

    @Override
    public boolean onLongClick(View v) {
                    //your code
        return true;
    }
});

holder.imageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

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

        });

【讨论】:

  • 谢谢,这就是问题所在!另一张海报对此有所帮助。 :)
  • 太好了!在我发布之前没有看到答案:)。
  • 在适配器中效果很好。但是如果你想在网格视图中这样做,你会怎么做呢?
【解决方案3】:

-首先检查是否有任何 Views 在您的 gridview 中是 FocusableClickable 或不使它们 False 然后再次检查您的日志 - 让我通知是否存在进一步的问题 -谢谢

【讨论】:

  • 我唯一拥有的东西,根据 S.O.建议,是这样的吗:gridView.setLongClickable(true); 但是没有它就不行,所以我不认为就是这样。我只有 1 个 ImageView 作为自定义 GridView 设置的一部分,但 xml 布局中的任何一个都没有可聚焦或可点击的。
  • 查看这里stackoverflow.com/questions/11931177/…ImageViews也可以拦截点击
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多