OnItemClickListener не работает, но OnItemLongClickListener работает над GridView

У меня проблема с clickListener в моем gridview. LongClickListener работает без проблем. Но я не могу получить ответ от прослушивателя кликов.

Мой код ниже.

Я смущен, почему работает длинный клик, но не обычный щелчок,

Любые указатели будут оценены

Спасибо

final GridView gridView = (GridView) findViewById(R.id.grid_view);
gridView.setNumColumns(numOfColumns);
gridView.getLayoutParams().width = (CELL_WIDTH * numOfColumns);
gridView.getLayoutParams().height = (CELL_WIDTH * numOfRows);

....

gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
      public void onItemClick(AdapterView<?> parent, View v,
                                int position, long id) {
            Log.d("ABCD", "Position Single Click is " + position);
            // Ideally in here I want to put to open a soft keyboard for the user to enter a value
            // InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
            // imm.showSoftInput(gridView, InputMethodManager.SHOW_IMPLICIT);
        }
    });

 gridView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
      @Override
      public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
          Log.d("ABCD", "Position Long Click is " + position);
          return true;
      }
 });

grid_view

<LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"
           xmlns:tools="http://schemas.android.com/tools"
           android:layout_width="match_parent"
           android:layout_height="match_parent"
           android:descendantFocusability="blocksDescendants"
           android:orientation="vertical">

<LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:gravity="center"
        android:orientation="horizontal">

    <View
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="2"/>

    <GridView xmlns:android="http://schemas.android.com/apk/res/android"
              android:id="@+id/my_grid_view"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:clickable="true"/>   <<--- I WANT THIS TO GET THE CLICK
    <View
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="2"/>
</LinearLayout>

<ListView xmlns:android="http://schemas.android.com/apk/res/android"
          android:id="@+id/listId"
          android:layout_weight="1"
          android:layout_width="match_parent"
          android:layout_height="0dp" />
</LinearLayout>

GridCell в виде сетки

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:padding="0dp" android:layout_margin="0dp"
           android:focusable="false"
            android:clickable="false"
            android:focusableInTouchMode="false"
   >

   <TextView
        android:id="@+id/grid_item_number"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingLeft="1dp"
        android:paddingRight="0dp"
        android:paddingTop="0dp"
        android:paddingBottom="0dp"
        android:textSize="10px"
        android:focusable="false"
        android:clickable="false"
        android:focusableInTouchMode="false"
        >
</TextView>

<EditText xmlns:android="http://schemas.android.com/apk/res/android"
          android:id="@+id/grid_item_label"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="@+id/celllabel"
          android:background="@android:color/transparent"
          android:paddingLeft="5dp"
          android:paddingRight="0dp"
          android:paddingTop="0dp"
          android:paddingBottom="0dp"
          android:layout_margin="0dp"
          android:focusable="false"
          android:focusableInTouchMode="false"
          android:clickable="false"
          android:cursorVisible="false">
</EditText>

</RelativeLayout>

Класс адаптера имеет getView и ниже

public View getView(final int position, View convertView, ViewGroup parent) {
    LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    View gridView;

    MyObject obj = myObjects.get(position);

    if (convertView == null) {
        gridView = inflater.inflate(R.layout.grid_cell, null);

        String textColour = "#000000";
        TextView textView = (TextView) gridView.findViewById(R.id.grid_item_label);
        textView.setText(Html.fromHtml(String.format("<font color='%s'>%s</font>", textColour, obj.getValue())));

        TextView superScriptTv = (TextView) gridView.findViewById(R.id.grid_item_number);
        if (obj.getNumber() > 0) {
            superScriptTv.setText(Html.fromHtml(String.format("<font>%s</font>", cell.getNumber())));
        }


    } else {
        gridView = convertView;
    }

    gridView.setBackgroundColor(obj.getBackgroundColour());

    return gridView;
}

ИЗМЕНИТЬ На самом деле ударило головой о стену здесь сейчас:) Я обновляю образец кода, чтобы иметь больше данных. Ive заметил, что в моем адаптере, если я не устанавливаю текст в текстовом виде с ID = R.id.grid_item_number, тогда он работает. Как только я устанавливаю текст на нем, я теряю прослушиватель кликов.

Связанный вопрос/ответ не помогает из того, что я вижу. Может ли кто-нибудь помочь с моей глупостью?

ИЗМЕНИТЬ Добавлен код адаптера.

Спасибо заранее.

Ответ 1

Проблема заключается в EditText внутри row_cell. Когда вы нажимаете на элемент, он фокусируется и предотвращает повторное нажатие всего элемента. Как вы заметили, работает только длинный клик. Здесь у вас есть аналогичная проблема.

Чтобы решить эту проблему, я переместил бы ваш OnItemClickListeners из Activity/Fragment в ваш GridViewAdapter, поэтому вместо:

gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
  public void onItemClick(AdapterView<?> parent, View v,
                            int position, long id) {
        Log.d("ABCD", "Position Single Click is " + position);
        // Ideally in here I want to put to open a soft keyboard for the user to enter a value
        // InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
        // imm.showSoftInput(gridView, InputMethodManager.SHOW_IMPLICIT);
    }
});

gridView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
  @Override
  public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
      Log.d("ABCD", "Position Long Click is " + position);
      return true;
  }
});

Я бы сделал что-то вроде этого:

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

    LayoutInflater layoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    View gridViewItem;

    if (convertView == null) {
        gridViewItem = new View(mContext);
        gridViewItem = layoutInflater.inflate(R.layout.grid_cell, null);
        TextView textView = (TextView)gridViewItem.findViewById(R.id.grid_item_number);
        textView.setText(mValues[position]);

        EditText editText = (EditText)gridViewItem.findViewById(R.id.grid_item_label);



    } else {
        gridViewItem = (View) convertView;
    }

    gridViewItem.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Log.e("GRID", "onClick: " );
        }
    });

    gridViewItem.setOnLongClickListener(new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {
            Log.e("GRID", "onLongClick: " );
            return true;
        }
    });

    return gridViewItem;

}

Это предотвратит это странное поведение, с которым вы сейчас боретесь.

Для этого примера, пожалуйста, найдите мой код ниже:

Макет MainActivity:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="io.github.mmbs.gridviewcheck.MainActivity"
tools:layout_editor_absoluteX="0dp"
tools:layout_editor_absoluteY="0dp">

<GridView
    android:id="@+id/gridView"
    android:numColumns="auto_fit"
    android:columnWidth="100dp"
    android:stretchMode="columnWidth"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clickable="true">

</GridView>

</android.support.constraint.ConstraintLayout>

Схема сетки:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="0dp"
            android:clickable="false"
            android:focusable="false"
            android:focusableInTouchMode="false"
            android:padding="8dp">

<TextView
    android:id="@+id/grid_item_number"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingBottom="0dp"
    android:paddingLeft="1dp"
    android:paddingRight="0dp"
    android:paddingTop="0dp"
    android:textSize="20sp"
    android:text="TEXTVIEW">
</TextView>

<EditText
          android:id="@+id/grid_item_label"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:layout_margin="0dp"
          android:background="@android:color/transparent"
          android:cursorVisible="false"
          android:layout_below="@id/grid_item_number"
          android:text="EDITTEXT">
</EditText>

</RelativeLayout>

Пожалуйста, примите во внимание, что я удалил все атрибуты макетов, ответственных за focusability.

MyGridAdapter:

public class MyGridViewAdapter extends BaseAdapter {

private Context mContext;
private final String[] mValues;

public MyGridViewAdapter(String[] values, Context context) {
    mValues = values;
    mContext = context;
}

@Override
public int getCount() {
    return mValues.length;
}

@Override
public Object getItem(int position) {
    return null;
}

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

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

    LayoutInflater layoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    View gridViewItem;

    if (convertView == null) {
        gridViewItem = new View(mContext);
        gridViewItem = layoutInflater.inflate(R.layout.grid_cell, null);
        TextView textView = (TextView)gridViewItem.findViewById(R.id.grid_item_number);
        textView.setText(mValues[position]);

        EditText editText = (EditText)gridViewItem.findViewById(R.id.grid_item_label);



    } else {
        gridViewItem = (View) convertView;
    }

    gridViewItem.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Log.e("GRID", "onClick: " );
        }
    });

    gridViewItem.setOnLongClickListener(new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {
            Log.e("GRID", "onLongClick: " );
            return true;
        }
    });

    return gridViewItem;

}
}

Если вам нравится, я также могу поделиться этим кодом на github, поэтому у вас будет полный рабочий пример.

Второй вариант заключается в том, чтобы оставить вашу реализацию такой, какой она есть, и делать взломы, когда EditText является настраиваемым и включенным. Здесь у вас есть связанные темы:

Более того, учтите что ответ:

Не используйте кликируемые объекты в сетке. В этом случае Android не сможет обработать событие щелчка GridView.

Вместо этого используйте что-то, чтобы показать аналогичный вид пользовательского интерфейса. Затем обработайте действия этого объекта click.

Не выполнять: поместите кнопку в GridView для выполнения некоторых действий с кликом.

Сделайте: поместите ImageView вместо ImageButton и обработайте события щелчка ImageView.

Изменить: найдите ссылку в проекте на моем Github.

Ответ 2

используйте gridView.setOnItemClickListener(.....) и в корневом представлении, добавив ниже строку

android:descendantFocusability="blocksDescendants"

ViewGroup блокирует своих потомков от получения фокуса.

happyCoding;

Ответ 3

Попробуйте добавить

android:focusable="false"
android:focusableInTouchMode="false"

в вашем GridCell → TextView

Ответ 4

Попробуйте использовать просмотр ресайклеров, если вам удобно с ним.

В дополнение к этому он не дает никакой такой проблемы, он имеет свои преимущества.

Следуйте ссылке для получения полного объяснения.

Ответ 5

Если у вас есть фокусное представление в вашем макете строк, то onItemClickListener не будет вызываться. Для этой проблемы вам нужно настроить код getView и установить onClickListener() в convertView и передать обратный вызов активности с помощью интерфейса. Я обновил код вашего адаптера, как показано ниже. Теперь вам нужно реализовать GridViewItemClickListener в вашей деятельности и передать экземпляр при создании экземпляра адаптера.

 public class MyGridViewAdapter extends BaseAdapter {

private Context mContext;
private final String[] mValues;
private GridViewItemClickListener mListener;

public MyGridViewAdapter(String[] values, Context context,GridViewItemClickListener listener ) {
    mValues = values;
    mContext = context; 
    mListener = listener;

}

@Override
public int getCount() {
    return mValues.length;
}

@Override
public Object getItem(int position) {
    return null;
}

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

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

    LayoutInflater layoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    View gridViewItem;

    if (convertView == null) {
        gridViewItem = new View(mContext);
        gridViewItem = layoutInflater.inflate(R.layout.grid_cell, null);
        TextView textView = (TextView)gridViewItem.findViewById(R.id.grid_item_number);
        textView.setText(mValues[position]);

        EditText editText = (EditText)gridViewItem.findViewById(R.id.grid_item_label);



    } else {
        gridViewItem = (View) convertView;
    }



    gridViewItem.setOnLongClickListener(new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {
            Log.e("GRID", "onLongClick: " );
            return true;
        }
    });
//Add an OnclickListener here
   gridViewItem.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
           if(mListener != null){
           mListener.onGridItemClick(v, position);
           }
        }
    });

    return gridViewItem;

}

public interface GridViewItemClickListener{
   void onGridItemClick(View v, int index);
}
}

Ответ 6

Как можно использовать функцию прослушивателя кликов, если вы устанавливаете корневой элемент в GridCell.java как неаккуратный?

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:padding="0dp" android:layout_margin="0dp"
           android:focusable="false"
            android:clickable="false"
            android:focusableInTouchMode="false"

Удалите эти строки из каждого из ваших компонентов в GridCell.java

android:focusable="false"
android:clickable="false"
android:focusableInTouchMode="false"

Я не думаю, что это необходимо для GridView, но иногда для RecyclerView требуется иметь android: clickable = "true" в корневом компоненте GridCell.java

Ответ 7

Вы можете щелкнуть мышью на слушателях внутри адаптера, и он будет работать следующим образом

public Просмотреть getView (конечная позиция int, View convertView, родительская группа ViewGroup) {       LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    View gridView;

    MyObject obj = myObjects.get(position);

    if (convertView == null) {
        gridView = inflater.inflate(R.layout.grid_cell, null);

        String textColour = "#000000";
        TextView textView = (TextView) gridView.findViewById(R.id.grid_item_label);
        textView.setText(Html.fromHtml(String.format("<font color='%s'>%s</font>", textColour, obj.getValue())));

        TextView superScriptTv = (TextView) gridView.findViewById(R.id.grid_item_number);
        superScriptTv.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // here you can use every item of grid acc to position
            }
        });
        if (obj.getNumber() > 0) {
            superScriptTv.setText(Html.fromHtml(String.format("<font>%s</font>", cell.getNumber())));
        }


    } else {
        gridView = convertView;
    }

    gridView.setBackgroundColor(obj.getBackgroundColour());

    return gridView;
}