Android ListView OnItemClick 事件有时会触发,但并非总是如此

发布于 2024-11-27 05:35:13 字数 6125 浏览 0 评论 0原文

我的 Android ListView 组件有一个非常奇怪的问题。

情况:我基本上利用 setOnItemClickListener 方法,然后重写“onItemClick”方法,以在单击列表视图中的项目时实现自定义操作。

问题: onItemClick 事件按其应该在项目点击时触发的方式触发,但是在点击了相当数量的项目 (20-30-40) 后,突然只有一个项目变得不可点击,这意味着当您点击时什么也不会发生点击它。与此同时,所有其他项目仍然可以点击。

我已经重写了 ListView 组件来捕获“dispatchTouchEvent”(参见下面的代码),这表明当一个项目突然变得不可点击时,dispatchTouchEvent 确实仍然被触发,具有合理的 X 和 Y 坐标,但不知何故“onItemClick” “事件未能触发。

public class ExtendedListView extends ListView 
{
public ExtendedListView(Context context) {
    super(context);     
}

@Override
public boolean dispatchTouchEvent(MotionEvent ev)
{
    Log.v("dispatchTouchEvent", "click|X:" + ev.getX() + "|Y:" + ev.getY());
    return super.dispatchTouchEvent(ev);        
}

任何

启动ListView 的方法:

@SuppressWarnings("unchecked")
private void renderHomeScreenItemsList() {
    HomeScreenItemAdapter m_adapter;
    ArrayList<HomeScreenItem> lHomeScreenItems = null;

    LayoutParams lpHomeScreenItems = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);        
    lpHomeScreenItems.leftMargin = Util.dipsToPx(0, this);
    lpHomeScreenItems.topMargin = Util.dipsToPx(155, this);     
    lpHomeScreenItems.gravity = 3; //3 = LEFT. Some gravity is necessary.       
    lvHomeScreenItems = new ExtendedListView(this);
    lvHomeScreenItems.setLayoutParams(lpHomeScreenItems);

    ColorDrawable sage = new ColorDrawable(this.getResources().getColor(R.color.HomeScreenDividerColor));        
    lvHomeScreenItems.setDivider(sage);
    lvHomeScreenItems.setDividerHeight(1);

    lvHomeScreenItems.setCacheColorHint(Color.WHITE);
    lvHomeScreenItems.setBackgroundColor(Color.WHITE);      

    lHomeScreenItems = new ArrayList<HomeScreenItem>();        

    Iterator<EnabledSection> ite = Global.EnabledSectionsVector.iterator();     

    while (ite.hasNext()) {
        EnabledSection es = (EnabledSection) ite.next();

        HomeScreenItem h1 = new HomeScreenItem();
        h1.setItemText(es.FunctionTitle);
        h1.setFunctionName(es.FunctionName);

        int imageId = getResources().getIdentifier("homescreen_" + es.FunctionName.toLowerCase(), "drawable", "XXXXXXXXX");

        h1.setItemImageResourceId(imageId);

        lHomeScreenItems.add(h1);
    }

    HomeScreenItem hCopyright = new HomeScreenItem();
    hCopyright.setItemText("copyright");
    hCopyright.setItemImageResourceId(-1);
    lHomeScreenItems.add(hCopyright);       

    m_adapter = new HomeScreenItemAdapter(this, R.layout.row, lHomeScreenItems);
    lvHomeScreenItems.setAdapter(m_adapter);        

    lvHomeScreenItems.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            Log.v("onItemClick", "Click Detected");
            HomeScreenItem hmi = (HomeScreenItem)parent.getItemAtPosition(position);

            Boolean blnAcceptClick = true;
            if (WrapperWebView == null)
                blnAcceptClick = true;
            else
                if (WrapperWebView.getProgress() != 100)
                    blnAcceptClick = false;

            if (hmi.getItemImageResourceId() != -1 && blnAcceptClick)
            {   
                Global.IsLoadingWrapper = true;
                vSelectedItem = view;

                ImageView ivIcon = (ImageView)view.findViewById(R.id.rightarrow);

                LinearLayout ll = (LinearLayout)view.findViewById(R.id.RowContainer);
                TextView ll2 = (TextView)view.findViewById(R.id.toptext);

                ll.setBackgroundResource(R.color.BlueActive);
                ll2.setBackgroundResource(R.color.BlueActive);
                ll2.setTextColor(Color.WHITE);                  

                int[] intCoordinates = new int[2];                  
                view.getLocationInWindow(intCoordinates);
                lpLoadingSpinner.topMargin = intCoordinates[1] - Util.dipsToPx(10, HomeScreen.this); 
                ivLoadingSpinner.setVisibility(View.VISIBLE);
                ivLoadingSpinner.bringToFront();

                LoadingSpinnerAnimation.start();

                ivIcon.setVisibility(View.GONE);
                ivClickedItemIcon = ivIcon;                 

                InitializeWebView(hmi.getFunctionName());        
            }               
        }
    });
}

帮助将不胜感激。该错误已确认发生在多个设备和多个 Android 版本上。

更新:问题已解决 我已经设法找到问题并解决它。基本上,项目列表包含所有“正常”项目(在我的上下文中),除了底部的项目,它是一个“版权”项目,带有必须可单击的链接(蓝色)。为了使此点击效果发挥作用,我使用了:

tt.setMovementMethod(LinkMovementMethod.getInstance());

如果正在渲染的项目是版权项目。

但是,如果正在渲染的项目是“正常”项目,我不会反驳这种效果,因此仅在渲染正常项目时添加下面的行,问题就消失了:

tt.setMovementMethod(null);

完整的示例代码(删除了不相关的代码) )

public class HomeScreenItemAdapter extends ArrayAdapter<HomeScreenItem> {

private ArrayList<HomeScreenItem> items;

public HomeScreenItemAdapter(Context context, int textViewResourceId, ArrayList<HomeScreenItem> items) {
    super(context, textViewResourceId, items);
    this.items = items;
}

@Override
public View getView(int position, View convertView, ViewGroup parent)
{   
    View v = convertView;
    if (v == null) {
        LayoutInflater vi = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = vi.inflate(R.layout.row, null);
    }        

    HomeScreenItem o = items.get(position);
    if (o != null) {            
        TextView tt = (TextView) v.findViewById(R.id.toptext);

        if (iv != null && tt != null)
        {
            if (position != (items.size() - 1))
            {       
            tt.setMovementMethod(null);                 
            }
            else
            {
                //last element, so setup element to show copyright notice instead
                tt.setMovementMethod(LinkMovementMethod.getInstance()); //this makes the link clickable                 
            }
        }
    }
    return v;
}

}

I have a very wierd problem with the Android ListView component.

Situation: I'm basically utilizing the setOnItemClickListener method and subsequently overriding the "onItemClick" method to implement a custom action when clicking on an item in the listview.

Problem: The onItemClick event fires as it should on an item tap, however having tapped a decent amount of items (20-30-40), suddenly one, and only one, of the items become un-tapable, meaning nothing happens when you tap it. Meanwhile, all the other items are still tapable.

I have overridden the ListView component to capture the "dispatchTouchEvent" (see code below), and that reveals that when an item suddenly becomes un-tapable, the dispatchTouchEvent is indeed still fired, with reasonable X and Y coordinates, but somehow the "onItemClick" event failes to fire.

public class ExtendedListView extends ListView 
{
public ExtendedListView(Context context) {
    super(context);     
}

@Override
public boolean dispatchTouchEvent(MotionEvent ev)
{
    Log.v("dispatchTouchEvent", "click|X:" + ev.getX() + "|Y:" + ev.getY());
    return super.dispatchTouchEvent(ev);        
}

}

Method that initiates the ListView:

@SuppressWarnings("unchecked")
private void renderHomeScreenItemsList() {
    HomeScreenItemAdapter m_adapter;
    ArrayList<HomeScreenItem> lHomeScreenItems = null;

    LayoutParams lpHomeScreenItems = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);        
    lpHomeScreenItems.leftMargin = Util.dipsToPx(0, this);
    lpHomeScreenItems.topMargin = Util.dipsToPx(155, this);     
    lpHomeScreenItems.gravity = 3; //3 = LEFT. Some gravity is necessary.       
    lvHomeScreenItems = new ExtendedListView(this);
    lvHomeScreenItems.setLayoutParams(lpHomeScreenItems);

    ColorDrawable sage = new ColorDrawable(this.getResources().getColor(R.color.HomeScreenDividerColor));        
    lvHomeScreenItems.setDivider(sage);
    lvHomeScreenItems.setDividerHeight(1);

    lvHomeScreenItems.setCacheColorHint(Color.WHITE);
    lvHomeScreenItems.setBackgroundColor(Color.WHITE);      

    lHomeScreenItems = new ArrayList<HomeScreenItem>();        

    Iterator<EnabledSection> ite = Global.EnabledSectionsVector.iterator();     

    while (ite.hasNext()) {
        EnabledSection es = (EnabledSection) ite.next();

        HomeScreenItem h1 = new HomeScreenItem();
        h1.setItemText(es.FunctionTitle);
        h1.setFunctionName(es.FunctionName);

        int imageId = getResources().getIdentifier("homescreen_" + es.FunctionName.toLowerCase(), "drawable", "XXXXXXXXX");

        h1.setItemImageResourceId(imageId);

        lHomeScreenItems.add(h1);
    }

    HomeScreenItem hCopyright = new HomeScreenItem();
    hCopyright.setItemText("copyright");
    hCopyright.setItemImageResourceId(-1);
    lHomeScreenItems.add(hCopyright);       

    m_adapter = new HomeScreenItemAdapter(this, R.layout.row, lHomeScreenItems);
    lvHomeScreenItems.setAdapter(m_adapter);        

    lvHomeScreenItems.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            Log.v("onItemClick", "Click Detected");
            HomeScreenItem hmi = (HomeScreenItem)parent.getItemAtPosition(position);

            Boolean blnAcceptClick = true;
            if (WrapperWebView == null)
                blnAcceptClick = true;
            else
                if (WrapperWebView.getProgress() != 100)
                    blnAcceptClick = false;

            if (hmi.getItemImageResourceId() != -1 && blnAcceptClick)
            {   
                Global.IsLoadingWrapper = true;
                vSelectedItem = view;

                ImageView ivIcon = (ImageView)view.findViewById(R.id.rightarrow);

                LinearLayout ll = (LinearLayout)view.findViewById(R.id.RowContainer);
                TextView ll2 = (TextView)view.findViewById(R.id.toptext);

                ll.setBackgroundResource(R.color.BlueActive);
                ll2.setBackgroundResource(R.color.BlueActive);
                ll2.setTextColor(Color.WHITE);                  

                int[] intCoordinates = new int[2];                  
                view.getLocationInWindow(intCoordinates);
                lpLoadingSpinner.topMargin = intCoordinates[1] - Util.dipsToPx(10, HomeScreen.this); 
                ivLoadingSpinner.setVisibility(View.VISIBLE);
                ivLoadingSpinner.bringToFront();

                LoadingSpinnerAnimation.start();

                ivIcon.setVisibility(View.GONE);
                ivClickedItemIcon = ivIcon;                 

                InitializeWebView(hmi.getFunctionName());        
            }               
        }
    });
}

Any help would be greatly appeciated. The bug is confirmed to happen on multiple devices and on multiple android versions.

UPDATE: Problem fixed
I've managed to find the problem and fix it. Basically, the list of items contained all "normal" items (in my context), except for the bottom one, which was a "copyright" item with a link (in blue) that had to be clickable. To get this click effect working, I used:

tt.setMovementMethod(LinkMovementMethod.getInstance());

if the item being rendered was the copyright item.

However, I didn't counter that effect if the item being rendered was a "normal" item, so by only adding the line below when a normal item is rendered, the problem went away:

tt.setMovementMethod(null);

Full example code (with non-relevant code removed)

public class HomeScreenItemAdapter extends ArrayAdapter<HomeScreenItem> {

private ArrayList<HomeScreenItem> items;

public HomeScreenItemAdapter(Context context, int textViewResourceId, ArrayList<HomeScreenItem> items) {
    super(context, textViewResourceId, items);
    this.items = items;
}

@Override
public View getView(int position, View convertView, ViewGroup parent)
{   
    View v = convertView;
    if (v == null) {
        LayoutInflater vi = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = vi.inflate(R.layout.row, null);
    }        

    HomeScreenItem o = items.get(position);
    if (o != null) {            
        TextView tt = (TextView) v.findViewById(R.id.toptext);

        if (iv != null && tt != null)
        {
            if (position != (items.size() - 1))
            {       
            tt.setMovementMethod(null);                 
            }
            else
            {
                //last element, so setup element to show copyright notice instead
                tt.setMovementMethod(LinkMovementMethod.getInstance()); //this makes the link clickable                 
            }
        }
    }
    return v;
}

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文