Android 如何侦听列表视图上发生在列表项之外的单击事件?

Android 如何侦听列表视图上发生在列表项之外的单击事件?,android,listview,android-listview,Android,Listview,Android Listview,我有一个占据整个屏幕的ListView,但有时它没有足够的项目来完全覆盖ListView小部件。我希望能够对点击最后一个项目下方的空白区域做出响应,该区域实际上不包含任何项目(这意味着setOnItemClickListener不合适) 我在父视图上尝试了setOnClickListener(他们对ListView本身禁用了该功能),但单击似乎没有达到目的。我还在列表视图上尝试了setOnTouchListener,但由于某种原因,导致某些项目的单击无法注册。关于如何实现这一点有什么想法吗?一种

我有一个占据整个屏幕的
ListView
,但有时它没有足够的项目来完全覆盖
ListView
小部件。我希望能够对点击最后一个项目下方的空白区域做出响应,该区域实际上不包含任何项目(这意味着
setOnItemClickListener
不合适)


我在父视图上尝试了
setOnClickListener
(他们对
ListView
本身禁用了该功能),但单击似乎没有达到目的。我还在
列表视图上尝试了
setOnTouchListener
,但由于某种原因,导致某些项目的单击无法注册。关于如何实现这一点有什么想法吗?

一种可能的实现方法是将ListView设置为
height=“wrap\u content”
如果这样做,那么您可以为您的活动覆盖
onTouchEvent()
,以便在用户触摸空白时获取事件

Layout.xml

<ListView
    android:id="@+id/list"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:entries="@array/list" />

Activity.java

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ListView mList = (ListView)findViewById(R.id.list);
        mList.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View v, int pos,long id) {
                Toast.makeText(v.getContext(), ""+pos, Toast.LENGTH_SHORT).show();
            }
        });
    }
    @Override
    public boolean onTouchEvent(MotionEvent me){
        if(me.getAction() == MotionEvent.ACTION_DOWN){
            Toast.makeText(this, "Empty space", Toast.LENGTH_SHORT).show();
            return true;
        }
        return false;
    }
}
公共类MainActivity扩展活动{
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView mList=(ListView)findViewById(R.id.list);
mList.setOnItemClickListener(新的OnItemClickListener(){
@凌驾
public void onItemClick(AdapterView父视图、视图v、整数位置、长id){
Toast.makeText(v.getContext(),“”+pos,Toast.LENGTH_SHORT.show();
}
});
}
@凌驾
公共事件(MotionEvent me){
if(me.getAction()==MotionEvent.ACTION\u向下){
Toast.makeText(这是“空白”,Toast.LENGTH_SHORT).show();
返回true;
}
返回false;
}
}

但是,如果出于某种原因(即背景可绘制),您指望ListView高度与父级匹配,那么这将不是一个理想的解决方案

下面是我的示例:

通过为listview设置适当的高度,在listview下方放置一个空的linearlayout。将onClick()方法放置到该线性布局。必须这样做。

遇到了类似的问题,我需要在单击空白时关闭展开的列表元素。下面是我如何解决它的

public class CustomListView extends ListView {

  private OnNoItemClickListener mOnNoItemClickListener;

  public interface OnNoItemClickListener {
    void onNoItemClicked();
  }

  public CustomListView(Context context) {
    super(context);
  }

  public CustomListView(Context context, AttributeSet attrs) {
    super(context, attrs);
  }

  public CustomListView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
  }

  @Override
  public boolean dispatchTouchEvent(MotionEvent ev) {
    //check whether the touch hit any elements INCLUDING ListView footer
    if(pointToPosition((int) (ev.getX() * ev.getXPrecision()), 
       (int) (ev.getY() * ev.getYPrecision())) == -1 && ev.getAction() == MotionEvent.ACTION_DOWN) {
      if(mOnNoItemClickListener != null) {
        mOnNoItemClickListener.onNoItemClicked();
      }
    }
    return super.dispatchTouchEvent(ev);
  }

  public void setOnNoItemClickListener(OnNoItemClickListener listener) {
    mOnNoItemClickListener = listener;
  }

}
然后在XML文件中使用此CustomListView而不是常规ListView,并在活动/片段中实现OnNoItemClickListener,并调用mListView.setOnNoItemClickListener(this);在onCreate中启用对onNoItemClicked()函数的回调


请注意,如果您的ListView有页眉或页脚,则这些被视为列表元素,并且不会调用onNoItemClicked()

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
  ... setup list view and other view state
  listView.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
      if (event.getAction() == MotionEvent.ACTION_DOWN &&
          listView.pointToPosition((int) (event.getX() * event.getXPrecision()), (int) (event.getY() * event.getYPrecision())) == -1) {
        collapseExpandedListItem();
        return true;
      }
      return false;
    }
  });
}

FWIW,我提出了一个问题,以解除
setOnClickListener()
限制,因为您提出了一个很好的观点:您是否尝试过这个方法,或者您是否立即知道ListView是否与wrap\u内容交互良好?我的直觉告诉我,这是一件无法很好处理的事情:它是否会尝试测量ListView的所有子项?我在ListView中尝试了这一点,它包含带有TextWatchers的EditText的行。我能够捕捉到空白的点击事件,但编辑文本在键入时会变慢