在GridView上,OnItemClickListener无法工作,但OnItemLongClickListener可以工作

13

我在我的网格视图上使用clickListener遇到了问题。LongClickListener没有问题,但是我似乎无法从clickListener获得任何响应。

我的代码如下。

我困惑于为什么长按可以工作而普通点击却不能,

如果有任何指针,将不胜感激

谢谢

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

编辑 我现在感到非常困扰 :) 我正在更新代码示例,以获得更多数据。 我注意到,如果我不在具有ID = R.id.grid_item_number的TextView上设置文本,则它可以正常工作。 一旦我在其上设置文本,就会失去单击侦听器。

从我所见,链接的问题/答案对我没有帮助。 有人能帮帮我愚蠢的我吗?

编辑 已添加适配器代码。

提前致谢。


请查看这个问题/答案:https://dev59.com/C1fUa4cB1Zd3GeqPEyLF - Sven Niehus
请问您能否发布GridCell的完整XML代码? - Harsh4789
你能分享一下适配器内部的代码吗? - Ankit Aggarwal
嗨,@ankitaggarwal,我刚刚从适配器类中添加了getView。如果您需要更多的代码,请告诉我。感谢您的关注。 - RNJ
你是同时使用两个吗?即使你移除了onLongClickListener,onClickListener也不起作用吗? - Ruchira Randana
7个回答

10

问题出在 row_cell 中的 EditText 上。当你点击这个控件时,它会获得焦点并阻止整个条目被再次点击。如你所见,只有长按才有效。

这里有一个类似的问题。

要解决这个问题,我建议将你的 OnItemClickListener 从 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可获得焦点和启用时进行一些技巧处理。以下是相关主题:

  1. Android:强制EditText取消焦点?
  2. ListView项目焦点行为
  3. ListView中可获得焦点的EditText
  4. Android:强制EditText取消焦点?

另外,请考虑一下这个答案:

不要在网格中使用可点击的对象。在这种情况下,Android 无法处理 GridView 的点击事件。

相反,使用一些东西来显示类似的用户界面视图。然后处理该对象的点击操作。

不要:将按钮放在 GridView 中执行某些点击操作。

做:将 ImageView 替换为 ImageButton,并处理 ImageView 的点击事件。

编辑:请在我的Github上找到该项目的链接


感谢 @mmBs 提供非常全面的答案!我会在接下来的一天左右检查一下。 - RNJ
今晚我会在 @mmBs 进行检查。 - RNJ
嗨@mmBs。它似乎不起作用,我认为这是因为textView / EditText部分彼此在下面。我看到android:layout_below =“@id/grid_item_number”。对于我的代码,它们实际上是相互重叠的。我认为你肯定让我更接近了,但还会继续一段时间。当我点击TextView部分时,似乎可以调用,但当我点击EditText部分时,它没有传递。 - RNJ
现在我可能要求更多了 ;) 但是理想情况下,我希望在点击时打开键盘。我已经尝试用打开键盘的代码替换调试代码,但也不起作用。感谢你到目前为止的帮助。 - RNJ
嗨@RNJ,请在此处找到存储库链接here - mmBs
显示剩余3条评论

3

使用gridView.setOnItemClickListener(.....),并在根视图下添加以下行:

android:descendantFocusability="blocksDescendants"

ViewGroup会阻止其子元素获得焦点。

2
尝试添加
android:focusable="false"
android:focusableInTouchMode="false"

在你的GridCell里面-->TextView

1

如果您熟悉使用RecyclerView,请尝试使用它。

除此之外,它没有其他问题,而且它有自己的优点。

请访问链接以获取完整解释。


1
如果您的行布局中有任何可聚焦视图,则不会调用onItemClickListener。针对此问题,您需要自定义getView代码,并在convertView上设置onClickListener(),并使用接口将回调传递给activity。我已更新您的Adapter代码如下。现在您需要在活动中实现GridViewItemClickListener并在创建Adapter实例时传递该实例。
 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);
}
}

1
如果在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,需要在GridCell.java的根组件上设置android:clickable="true"


1
你可以在适配器中使用点击监听器,它会工作,应该像这样工作: 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);
        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;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接