【问题标题】:onClick event doesn't work on nested listview item control in androidonClick 事件不适用于 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 处理程序停止工作。还有一些其他有趣的东西:

  1. onTouch 列表视图项的侦听器仍在工作(要求 action=ACTION_DOWN 和action=ACTION_UP);
  2. 当我设置 listview onItemClickListener 它总是被调用 (第一次弹出窗口打开并返回时);
  3. 当我多次单击列表视图中的项目时,有时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 这取决于您单击的位置还是您尝试单击一次然后等待?

标签: android listview android-dialog


【解决方案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会导致点击问题?
  • 我检查了你的代码。我做的完全一样。你试过用对话框吗?我有第一个带有列表和按钮的对话框,它打开另一个对话框,当我们从第二个对话框返回到第一次点击时停止工作。最初它们工作得很好(两个对话框全屏 - 不确定它是否重要)
  • 这很奇怪。你能分享创建对话框(第一级和第二级)的代码吗?
  • @Natasha 是的,你是对的。最好使用 ViewHolder 模式来提高性能。您可以使用 ViewHolder 内置的RecyclerView。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-10-27
  • 1970-01-01
  • 2016-06-02
  • 2016-04-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-03
相关资源
最近更新 更多