SetOnItemLongClickListener в GridView не доступен для кликов

Я перепробовал все предложения, которые смог найти на SO, и мне удалось успешно использовать этот точный код на моем ListView, но по какой-то причине я не могу установить прослушиватель длинных кликов на моем GridView. Я вхожу в метод setupGridViewListener();, и он даже не запускается, а у меня есть метод внутри onCreateView(). Не знаю, почему это не сработает. Диалоговое окно предупреждения должно появиться после долгого щелчка, но это не так. Метод находится внизу моего класса.

ОБНОВЛЕНИЕ:

Я не упомянул, что мой onClickListener работает нормально. Так что я могу по крайней мере сделать один клик, и это отображает мою активность. Но этот код находится в моем адаптере, так что, может быть, они должны быть вместе в одном классе? Я включаю свой адаптер и мои 2 xml ниже.

ОБНОВЛЕНИЕ 2 Я обнаружил несколько вещей, о которых стоило упомянуть, даже после того, как мой код снова заработал. Во-первых, размещение прослушивателей кликов в моем адаптере было ошибкой. Это ОЧЕНЬ сильно замедлило работу... настолько, что я был в бешенстве, пытаясь найти способ получить что-то в другом потоке. Но в итоге мне это было не нужно. Я понял, что на самом деле могу получить обоих моих прослушивателей кликов в моем классе PhotoTab.java. Это сразу сделало его быстрее (вернулось к норме). Но еще одна любопытная вещь, IDE не позволяла мне использовать OnClickListener, а настаивала на том, чтобы я вернулся к OnItemClickListener. Поэтому, как только я поменял их обратно, все снова заработало. Таким образом, слушатели оказались в моих GridView переменных, например. gridView.setOnItemClickListener(new OnItemClickListener() {} не мои ImageView переменные элемента. Может быть, это и ускорило работу? Есть одна GridView, но 24 ImageViewс (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>

person Azurespot    schedule 25.03.2015    source источник
comment
Привет, я просматриваю ваш код, вы хотите удалить фотографию при долгом щелчке элемента сетки. У вас есть один щелчок, который работает нормально, потому что вы реализовали его внутри щелчка изображения. Я бы предложил вместо того, чтобы пытаться поймать длинный щелчок в виде сетки, вы можете использовать прослушиватель длинного щелчка в представлении изображения. :)   -  person Bhavdip Sagar    schedule 25.03.2015
comment
Спасибо, Бхавдип, это предложил другой постер, и это сработало! :)   -  person Azurespot    schedule 25.03.2015
comment
@Noni, мне нравятся ваши комментарии об ошибке при настройке слушателей в адаптере. Это кажется нормальным (то, что вы делали ранее), и я сделал это для ListView, а не для GridView. Google рекомендовал слушателей в адаптере для ListView. Я не знал, что использование GridView может быть таким разным. Теперь, когда вы устанавливаете прослушиватели вне адаптера, я подозреваю, что ваша текущая техника будет занимать больше памяти, но, возможно, не так много.   -  person The Original Android    schedule 26.03.2015
comment
Да, это было неожиданное открытие. Возможно, мне все же следует поместить процесс загрузки изображения в AsyncTask или другой тип Thread, но он показал значительные изменения, когда я поместил все в класс PhotoTab.java вместо класса адаптера. Спасибо за ваше дополнительное понимание!   -  person Azurespot    schedule 26.03.2015


Ответы (3)


Было бы лучше использовать щелчок и длинный щелчок для просмотра изображения или оба элемента для просмотра сетки.

Если вы хотите просмотреть изображение, не настраивайте 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);
            }

        });
person A B    schedule 25.03.2015
comment
Спасибо, это была проблема! В этом помог другой плакат. :) - person Azurespot; 25.03.2015
comment
Замечательно! Не видел ответа до того, как написал :). - person A B; 25.03.2015
comment
В адаптере работает отлично. Но как бы вы это сделали, если бы вам нужно было это внутри представления сетки? - person Dominik; 29.09.2016

– Прежде всего проверьте, являются ли какие-либо представления в вашем представлении сетки Focusable или Clickable или не делайте их False, а затем снова проверьте свой журнал - Позвольте мне сообщить, если возникнут дальнейшие проблемы - СПАСИБО

person Hardy    schedule 25.03.2015
comment
Единственное, что у меня есть, согласно S.O. предложение, таково: gridView.setLongClickable(true); Но без него не работало, так что я не думаю, что дело в этом. У меня есть только 1 ImageView как часть моей пользовательской настройки GridView, но ни в одном из xml макетов нет ни фокуса, ни клика. - person Azurespot; 25.03.2015
comment
Проверьте здесь stackoverflow.com/questions/11931177/ ImageViews также могут перехватывать клики - person Hardy; 25.03.2015

person    schedule
comment
Пожалуйста, разместите элемент строки xml для лучшего ответа. - person ; 25.03.2015
comment
Спасибо, я обновил свой код. Кстати, что происходит в вашем коде? Я не понимаю вашего предложения, спасибо. - person Azurespot; 25.03.2015
comment
Хорошо, спасибо, сейчас попробую. Получение большого количества ошибок. :( Но приятно знать, что вы думаете, что это проблема. Я дам вам знать, как это происходит. - person Azurespot; 25.03.2015
comment
Я добавил прослушиватель длинных кликов в класс адаптера. взгляните на это. - person ; 25.03.2015
comment
Омг, большое спасибо. Я каким-то образом импортировал версии AdapterView.onItemClickListener вместо View.onClickListener, и это выдавало мне ошибки повсюду. Android Studio не всегда обновляет ваш импорт, поэтому я очень рад, что вы показали мне правильный!! Все еще не могу заставить работать удаление моего файла, но это еще одна проблема. У меня есть оба прослушивателя щелчков в моем классе адаптера, немаловажный подвиг! И мой длинный щелчок вызывает диалоговое предупреждение, как и должно быть. Спасибо тебе. :) Не могу отблагодарить вас достаточно. - person Azurespot; 25.03.2015