OnClickListener не работает для первого элемента в GridView
У меня возникла проблема с созданием календаря на основе GridView. Вот сетка:
![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 получает вызов для каждой ячейки сетки EXCEPT первый в верхнем левом углу
Ответы
Ответ 1
Хорошо, я нашел решение. Проблема заключалась в следующих строках:
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
У меня была та же проблема. Сохранение setLayoutParams внутри предложения if (view == null). Вы не должны приносить в жертву вид переустановки таким образом.
like:
if(row == null){
// inflate row
row.setLayoutParams(params);
//remaining code
}else{
holder = (ViewHolder)row.getTag();
}
// everything else
Я не знаю, почему это работает, но это сработало для меня. Я также заметил, что все коды, относящиеся к одной и той же проблеме в stackoverflow, также использовали setLayoutParams вне предложения if. Это мой первый раз, поэтому я не знаю, могу ли я опубликовать это везде. Надеюсь, что это помогло.
Источник: много следов и ошибок.
Ответ 3
Используйте OnClickListener() в своей деятельности после .setAdapter(), а не в классе адаптера.
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();
}
});
Ответ 4
Для чего это стоит, у меня была и эта проблема (первая ячейка в gridview с задержкой onclick).
В моем случае я использовал (слегка настроенные) gridviews с динамическими наборами изображений, которые я бы сделал видимым/ушел и перерисовал gridview. Все изображения, подготовленные заранее и сохраненные в адаптере.
Вначале я использовал notifyDataSetChanged() на адаптере, но это привело к проблеме с задержкой нажатия для первой ячейки всякий раз, когда набор был обновлен. Я изменил просто аннулирование gridview, и теперь все в порядке. Имейте в виду, что все мои представления уже созданы и сохранены в адаптере, это просто метод getview, который проверяет, какие из них действительно видны.
Ответ 5
У меня была такая же проблема. Событие клика по первому элементу было значительно задержано. Я уже использовал notifyDataSetInvalidated(). Использование onItemClickListener() решило проблему, хотя я до сих пор не понимаю, почему слушатель onClick для отдельных элементов имеет такое поведение.
Ответ 6
Установите onItemClickListener в объект GridView вместо установки onClickListeners на каждой кнопке.
И я нашел еще один вопрос с вашей проблемой здесь. Может быть, Bounty?
Ответ 7
Пожалуйста, обратитесь к этой ссылке , она установила цвет фона сетки на TRANSPARENT. Это может помочь вам.
Ответ 8
Потратив так много дней, установите параметры макета следующим образом.
if (view == null) {
// call the user 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();
}
это работает абсолютно нормально для меня