22

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

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

4

7 回答 7

15

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

像 :

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

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

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

于 2014-03-24T13:23:12.113 回答
9

在.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();
    }
});
于 2014-01-15T19:01:16.327 回答
8

好的,我找到了解决方案。问题是这些行:

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

于 2012-08-08T15:11:51.643 回答
1

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

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

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

于 2013-12-04T16:49:03.620 回答
1

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

于 2014-02-08T16:49:54.910 回答
0

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

我在这里发现了与您的问题有关的另一个问题。赏金可能吗?

于 2012-08-02T13:29:11.863 回答
0

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

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();
    }

它对我来说绝对没问题

于 2019-01-21T07:14:11.970 回答