OnClickListener不适用于GridView中的第一项

时间:2012-08-02 13:16:35

标签: android android-gridview

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

GridView Calendar

这应该是一个填充了事件的日历,所以我有我的适配器实现OnClickListener,我为日历中的每个按钮设置了该监听器。它适用于每个按钮 EXCEPT 第一个按钮(在本例中为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,除了左上角的第一个

8 个答案:

答案 0 :(得分:13)

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

喜欢:

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

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

来源:很多追踪和错误。

答案 1 :(得分: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按钮的实例时,它会以某种方式混合适配器中第一个位置的单击侦听器。我最后通过在每次传递中设置持有者来修复它,而不是通过标记获取它(这对于性能更好,但是很好)。谢谢大家的帮助。

答案 2 :(得分:8)

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

答案 3 :(得分:1)

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

在我的情况下,我使用(轻微自定义)网格视图和动态的图像视图集,我将使其可见/消失并重绘网格视图。预先准备好并存储在适配器中的所有图像视图。

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

答案 4 :(得分:1)

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

答案 5 :(得分:0)

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

我发现了您的问题here的另一个问题。赏金可能吗?

答案 6 :(得分:0)

请参考此link,它已将gridview背景颜色设置为TRANSPARENT。它可能对你有帮助。

答案 7 :(得分: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();
    }

对我来说绝对正常