【问题标题】:OnClickListener not working for first item in GridViewOnClickListener 不适用于 GridView 中的第一项
【发布时间】:2012-08-02 13:16:35
【问题描述】:

我在创建基于 GridView 的日历时遇到问题。这是网格:

这应该是一个充满事件的日历,所以我让我的适配器实现 OnClickListener 并为日历中的每个按钮设置该侦听器。它适用于每个按钮除了第一个(在本例中为 30 号)。当我单击它时它不起作用,但是当我在尝试单击第一个按钮后单击另一个按钮时,它会在单击另一个按钮之前执行第一个按钮的单击。

我已经浏览了大约 10 页的相关问题,但没有发现有人遇到此问题。请帮忙!

按照要求,这是我的代码的 getView 函数:

    public View getView(int position, View convertView, ViewGroup parent)
    {
        View row = convertView;
        ViewHolder holder;
        if (row == null)
        {
            holder = new ViewHolder();
            LayoutInflater inflater = (LayoutInflater) _context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            row = inflater.inflate(R.layout.calendar_day_gridcell, parent, false);
            holder.gridCell = (Button) row.findViewById(R.id.calendar_day_gridcell);
            holder.multiDayEvent = (EventLengthView)row.findViewById(R.id.eventLengthView);
        }
        else{
            holder = (ViewHolder)row.getTag();
        }

        int calendarGridHeight = (calendarView.getHeight()-5)/(getCount()/7);
        AbsListView.LayoutParams params = new AbsListView.LayoutParams(
                android.view.ViewGroup.LayoutParams.FILL_PARENT,
                calendarGridHeight);
        row.setLayoutParams(params);

        //Change the background drawable depending on the position in the calendar
        if ((position+1) % 7 == 0){
            holder.gridCell.setBackgroundDrawable(getResources().getDrawable(R.drawable.calendar_button_selector_end_row));
        }
        if (getCount() - position < 8){
            holder.gridCell.setBackgroundDrawable(getResources().getDrawable(R.drawable.calendar_button_selector_end_column));
        }
        if (position == getCount()-1){
            holder.gridCell.setBackgroundDrawable(getResources().getDrawable(R.drawable.calendar_button_selector_end));
        }
        holder.gridCell.setOnClickListener(this);

        holder.gridCell.setTag(null);//clear tags

        // ACCOUNT FOR SPACING
        String[] day_color = list.get(position).split("-");
        int theday = Integer.parseInt(day_color[0]);
        int themonth = Integer.parseInt(day_color[2]);
        int theyear = Integer.parseInt(day_color[3]);
        String date = DateFormat.format("dd/M/yy", new Date(theyear,themonth,theday)).toString();
        if ((!eventsMap.isEmpty()) && (eventsMap != null))
        {
            if (eventsMap.containsKey(date))
            {
                holder.multiDayEvent.SetMeasure(calendarView.getWidth()/7, calendarGridHeight);

                holder.multiDayEvent.setVisibility(View.VISIBLE);
                //holder.singleDayEvent.setVisibility(View.VISIBLE);
                Event event = (Event) eventsMap.get(date);
                holder.multiDayEvent.AddEvent(event);
                holder.gridCell.setTag(event);
            }
            else{
                //holder.singleDayEvent.setVisibility(View.GONE);
                holder.multiDayEvent.setVisibility(View.GONE);
            }
        }

        // Set the Day GridCell
        holder.gridCell.setText(Integer.toString(theday));

        if (day_color[1].equals("GREY"))
        {
            holder.gridCell.setTextColor(Color.GRAY);
        }
        if (day_color[1].equals("WHITE"))
        {
            holder.gridCell.setTextColor(Color.WHITE);
        }
        if (day_color[1].equals("BLUE"))
        {
            holder.gridCell.setTextColor(Color.BLUE);
        }

        row.setTag(holder);
        return row;
    }

    public class ViewHolder{
        Button gridCell;
        ImageView singleDayEvent;
        EventLengthView multiDayEvent;
    }

    public void onClick(View view)
    {
        if (view.getTag() != null){
            Event event = (Event)view.getTag();

            eventListView.setAdapter(new EventListAdapter(CalendarScreen.this, event));
            eventListViewLayout.setVisibility(View.VISIBLE);
            eventListViewLayout.startAnimation(fadeIn);
        }
        else if (eventListViewLayout.getVisibility() == View.VISIBLE){
            onBackPressed();
        }
    }

除了左上角的第一个网格单元外,每个网格单元都会调用 onClick

【问题讨论】:

标签: android android-gridview


【解决方案1】:

我遇到了同样的问题。将 setLayoutParams 保留在 if(view == null) 子句中解决了。您不必以这种方式牺牲视图回收。

喜欢:

 if(row == null){
   // inflate row
   row.setLayoutParams(params);
   //remaining code
 }else{
    holder = (ViewHolder)row.getTag();
 }
 // everything else

我不知道它为什么有效,但它对我有效。我还注意到,关于 stackoverflow 中同一问题的所有代码也在 if 子句之外使用了 setLayoutParams。这是我第一次,所以我不知道我是否可以到处张贴。希望对您有所帮助。

来源:大量的线索和错误。

【讨论】:

  • 为我工作并为我节省了很多时间
  • 非常感谢!它有帮助。
  • 也为我工作。
  • 它有效。但这并没有任何意义。为什么它不工作?
【解决方案2】:

.setAdapter() 方法之后,在您的活动中使用您的 OnClickListener(),而不是在您的适配器类中。

gridView.setAdapter(adapter);
gridView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView parent, View v, int position, long id) {
    Toast.makeText(GridViewActivity.this, "" + position,
             Toast.LENGTH_SHORT).show();
    }
});

【讨论】:

  • 谢谢。我的问题已经被你的解决方案解决了。
  • 这个解决方案最好
  • 这比在 gridview 适配器中实现 OnClickListener 要容易得多
【解决方案3】:

好的,我找到了解决方案。问题出在以下几行:

ViewHolder holder;
if (convertView == null)
{
    holder = new ViewHolder();
    LayoutInflater inflater = (LayoutInflater) _context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    convertView = inflater.inflate(R.layout.calendar_day_gridcell, parent, false);
    holder.gridCell = (Button) convertView.findViewById(R.id.calendar_day_gridcell_button);
    holder.multiDayEvent = (EventLengthView) convertView.findViewById(R.id.eventLengthView);
    convertView.setTag(holder);
}
else {
    holder = (ViewHolder) convertView.getTag();
}

当在那里设置 gridCell 按钮时,不知何故,它混淆了适配器中第一个位置的点击侦听器。我最终通过在每次传递中都将支架设置为固定它来修复它,而不是通过标签获取它(这对性能更好,但是哦)。感谢大家的帮助。

【讨论】:

    【解决方案4】:

    对于它的价值,我也有这个问题(gridview 中的第一个单元格延迟了 onclick)。

    在我的例子中,我使用了一个带有动态图像视图集的(轻微定制的)gridviews,我将使其可见/消失并重绘gridview。所有预先准备好的图像视图并存储在适配器中。

    最初,我在适配器上使用了 notifyDataSetChanged() ,但这会导致每当更新集合时第一个单元格的点击延迟问题。我改为只是使gridview无效,现在一切都很好。请记住,我的所有视图都已创建并存储在适配器中,它只是检查哪些视图真正可见的 getview 方法。

    【讨论】:

      【解决方案5】:

      我也有同样的问题。第一项的点击事件明显延迟。我已经在使用 notifyDataSetInvalidated()。 使用 onItemClickListener() 解决了这个问题,虽然我仍然不明白为什么单个项目上的 onClick 侦听器会有这种行为。

      【讨论】:

        【解决方案6】:

        在 GridView 对象上设置 onItemClickListener,而不是在每个按钮上设置 onClickListeners。

        我发现了另一个与您的问题有关的问题here。也许赏金?

        【讨论】:

        • 我也尝试用 ImageViews 替换按钮(因为我知道按钮会阻止 GridView 的 onItemClickListeners),但它仍然不起作用。
        【解决方案7】:

        花了这么多天,设置布局参数如下..

        if (view == null) {
        
                // call the user's implementation
                view = mInflater.inflate(mViewId, null);
                holder = createHolder(view);
                // we set the holder as tag
                view.setTag(holder);
        
                rlMainCell = (RelativeLayout)view.findViewById(R.id.rlMainCell);
                rlMainCell.setLayoutParams(new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, (int) view.getResources().getDimension(R.dimen._128sdp)));
        
            } else {
                // get holder back...much faster than inflate
                holder = (ViewHolder) view.getTag();
            }
        

        它对我来说非常好

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多