onClick 事件不适用于 android 中的嵌套列表视图项控件

Posted

技术标签:

【中文标题】onClick 事件不适用于 android 中的嵌套列表视图项控件【英文标题】:onClick event doesn't work on nested listview item control in android 【发布时间】:2017-01-02 03:23:08 【问题描述】:

我有 2 个弹出窗口。在第一个弹出窗口中,我有 ListView 和可选项目。当我从第一个列表中单击项目时,会出现第二个弹出窗口,其中还有 ListView 以及可供选择的选项。

我已经将第一个列表视图项实现为自定义 View 并订阅视图构造函数内的点击,如下所示:

class CustomListItem extends RelativeLayout
    public CustomListItem()
        ...
       //inflating stuff there
       ((Button)findViewById(R.id.listItemButton)).setOnClickListener(
           //This code not working as expected, but then could fire a lot of times
           v -> System.out.println("item clicked");  
       );
    

当我第一次打开第一个对话框时,onClick 处理程序按预期触发并出现第二个弹出窗口。但是当我关闭第二个弹出窗口并返回(调用Dialog.dismiss() 弹出窗口)到第一个弹出窗口时,第一个列表视图上的onClick 处理程序停止工作。还有一些其他有趣的东西:

    onTouch 列表视图项的侦听器仍在工作(要求 action=ACTION_DOWNaction=ACTION_UP); 当我设置 listview onItemClickListener 它总是被调用 (第一次弹出窗口打开并返回时); 当我多次单击列表视图中的项目时,有时onClick 发生,之后它被调用的次数与我点击的次数一样多 之前。

您有什么想法可能是问题的原因吗?

更新

似乎适配器内部的getView 方法有问题。我尝试在其中创建一个自定义列表项控件(或从缓存中获取):

@Override
public View getView(int position, View view, ViewGroup parent) 
    if (!constructedViewCache.containsKey(position)) 
        constructedViewCache.put(position, new CustomListItem ());
    

    return constructedViewCache.get(position);

当我将此代码更改为以下代码时,一切正常:

@Override
public View getView(int position, View view, ViewGroup parent) 
    if (view == null)
    
       view = LayoutInflater.from(context).inflate(R.layout.list_view_item, null);
    

    view.setOnClickListener(v -> 
         v -> System.out.println("item clicked");
    );

    return view;

为什么不能使用new CustomListItem () 创建视图?或者如果可能的话我应该怎么做?

【问题讨论】:

我理解正确吗,onclick 不能正常工作,但是如果你点击很多次,比如说 20-30 它可能会触发,之后 onclick 的代码将被执行 20-30 次?跨度> 你能分享更多代码吗? @vovaxo 完整的代码非常复杂。哪部分代码可能对你有用? @silent_coder 是的,你是对的 @Natasha 这取决于您单击的位置还是您尝试单击一次然后等待? 【参考方案1】:

尝试在放置listItemButton 的列表项的父布局声明中插入属性android:descendantFocusability="blocksDescendants"

where属性android:descendantFocusability

在寻找要获得焦点的 View 时定义 ViewGroup 与其后代之间的关系。

而常量blocksDescendants表示:

ViewGroup 将阻止其后代接收焦点。

第二个问题

可以使用新的 CustomListItem () 创建视图。请参见下面的示例:

@Override
public View getView(int i, View view, ViewGroup viewGroup) 
    return new CustomListItem(context);

编辑

我没有看到你的完整代码,看起来你有问题。这是工作示例,请看:

public class CustomAdapter extends BaseAdapter 
private Context context;
private HashMap<Integer, CustomListItem> constructedViewCache = new HashMap<>();

public CustomAdapter(Context context) 
    this.context = context;


@Override
public int getCount() 
    return 20;


@Override
public Object getItem(int i) 
    return null;


@Override
public long getItemId(int i) 
    return 0;


@Override
public View getView(int position, View view, ViewGroup viewGroup) 
    if (!constructedViewCache.containsKey(position)) 
        constructedViewCache.put(position, new CustomListItem(context, position));
    
    return constructedViewCache.get(position);


二等:

public class CustomListItem extends RelativeLayout 
private static final String TAG = "CustomListItem";

public CustomListItem(Context context, int position) 
    super(context);

      View view = LayoutInflater.from(context).inflate(R.layout.item_view, this);
    Button button = (Button) view.findViewById(R.id.button);
    button.setOnClickListener(view1 -> 
        Log.e(TAG, "CustomListItem: " + position );
        FragmentManager fragmentManager = ((AppCompatActivity) context).getSupportFragmentManager();
        new CustomDialog().show(fragmentManager, "tag");
    );



编辑 2

我已更新CustomListItem 以在单击按钮时显示对话框。有自定义 DialogFragment 的代码,它使用与活动相同的布局和适配器的项目列表:

public class CustomDialog extends DialogFragment 

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) 
    View view = inflater.inflate(R.layout.activity_main, container, false);
    ListView listView = (ListView) view.findViewById(R.id.list);
    listView.setAdapter(new CustomAdapter(getActivity()));
    return view;


【讨论】:

android:descendantFocusability 不会影响结果,但您创建new CustomListItem() 的第二个建议可以正常工作并且不会“中断”点击。还是不明白问题的原因:为什么缓存item会导致点击问题? 我检查了你的代码。我做的完全一样。你试过用对话框吗?我有第一个带有列表和按钮的对话框,它打开另一个对话框,当我们从第二个对话框返回到第一次点击时停止工作。最初它们工作得很好(两个对话框全屏 - 不确定它是否重要) 这很奇怪。你能分享创建对话框(第一级和第二级)的代码吗? 让我们continue this discussion in chat。 @Natasha 是的,你是对的。最好使用 ViewHolder 模式来提高性能。您可以使用 ViewHolder 内置的RecyclerView

以上是关于onClick 事件不适用于 android 中的嵌套列表视图项控件的主要内容,如果未能解决你的问题,请参考以下文章

QuerySelectorAll 不适用于 onclick 事件

jQuery对话框上的Onclick事件不适用于IOS

onClick() 事件适用于一个 div,但不适用于另一个。为啥?

ReactJS onClick 不适用于菜单中的第一个元素

SumoSelect 处理事件不适用于 Android 设备

Android控件onClick事件