Android: Button within ListView not receiving onClick events -
i making date picker activity looks scrolling 30 day month/calendar (think outlook calendar). date picker contains listview (for scrolling) of monthview views each of tableview of individual days. each individual day in monthview button. when monthview instantiated walk each of days (buttons) , attach click listener:
final button b = getbuttonat(i); b.setonclicklistener(new onclicklistener() { @override public void onclick(view v) { setselecteddate(buttondayclosure, b); } });
setselecteddate variety of things, turns button's background yellow signify date selected.
on emulator, works expect. activity comes up, press day, day turns yellow. no problems.
however, on of peer's emulators , on physical devices when touch day nothing happens... until scroll listview... , of sudden selected day turns yellow. so, example, touch "the 3rd" , nothing happens. wait few seconds , scroll listview (touching area of calendar not 3rd) , listview scrolls 3rd magically turns yellow.
on peer emulators show behavior, can set breakpoint on fist line of onclick , see bp in fact not hit until listview scrolled.
this behavior doesn't make sense me. expect onclick behavior unrelated encapsulating view's scrolling efforts.
any thoughts on why might case , how can rectify situation onclicks happen when button touched?
thanks.
post scriptus: arrayadapter , listview code requested:
public class montharrayadapter extends arrayadapter<date> { private monthview[] _views; private vector<procedure<date>> _dateselectionchangedlisteners = new vector<procedure<date>>(); public montharrayadapter(context context, int textviewresourceid, date minselectableday, date maxselectableday) { super(context, textviewresourceid); int zerobasedmonth = minselectableday.getmonth(); int year = 1900 + minselectableday.getyear(); if(minselectableday.after(maxselectableday)) { throw new illegalargumentexception("min day cannot after max day."); } date prevday = minselectableday; int nummonths = 1; for(date = minselectableday; !sameday(i, maxselectableday); = i.adddays(1) ) { if(i.getmonth() != prevday.getmonth()) { nummonths++; } prevday = i; } _views = new monthview[nummonths]; for(int = 0; i<nummonths; i++) { date monthdate = new date(new gregoriancalendar(year, zerobasedmonth, 1, 0, 0).gettimeinmillis()); date startsunday = findstartsunday(monthdate); this.add(monthdate); _views[i] = new monthview(this.getcontext(), startsunday, minselectableday, maxselectableday); zerobasedmonth++; if(zerobasedmonth == 12) { year++; zerobasedmonth = 0; } } for(final monthview : _views) { a.addselecteddatechangedlistener(new procedure<monthview>() { @override public void execute(monthview input) { for(final monthview b: _views) { if(a != b) { b.clearcurrentselection(); } } for(procedure<date> listener : _dateselectionchangedlisteners) { listener.execute(a.getselecteddate()); } } }); } } void addselecteddatechangedlistener(procedure<date> listener) { _dateselectionchangedlisteners.add(listener); } private boolean sameday(date a, date b) { return a.getyear() == b.getyear() && a.getmonth() == b.getmonth() && a.getdate() == b.getdate(); } @override public view getview (int position, view convertview, viewgroup parent) { return _views[position]; } private date findstartsunday(date d) { return d.subtractdays(d.getday()); } public void setselecteddate(date date) { for(monthview mv : _views) { mv.setselecteddate(date); } } }
and
public class datepicker extends activitybase { public static final string chosen_date_result_key = "resultkey"; public static final string min_selectable_day = datepicker.class.getname() + "min"; public static final string max_selectable_day = datepicker.class.getname() + "max"; private static final string selected_date = uuid.randomuuid().tostring(); private long _selecteddate = -1; private montharrayadapter _montharrayadapter; @override public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); date = new date(); bundle inputs = this.getintent().getextras(); long min = inputs.getlong(min_selectable_day, 0); date minselectabledate; if(min == 0) { minselectabledate = new date(now); } else { minselectabledate = new date(min); } log.i(datepicker.class.getname(), "min date = " + minselectabledate.tostring()); long max = inputs.getlong(max_selectable_day, 0); date maxselectabledate; if(max == 0) { maxselectabledate = new date(now.adddays(35).gettime()); } else { maxselectabledate = new date(max); } setcontentview(r.layout.date_picker); button donebutton = (button) findviewbyid(r.id.datepickerdonebutton); if(donebutton == null) { log.e(this.getclass().getname(), "could not find donebutton view id."); finish(); return; } donebutton.setonclicklistener(new onclicklistener() { @override public void onclick(view v) { intent result = new intent(); result.putextra(chosen_date_result_key, _selecteddate); setresult(result_ok, result); finish(); } }); button cancelbutton = (button) findviewbyid(r.id.datepickercancelbutton); if(cancelbutton == null) { log.e(this.getclass().getname(), "could not find cancelbutton view id."); finish(); return; } cancelbutton.setonclicklistener(new onclicklistener() { @override public void onclick(view v) { setresult(result_canceled, null); finish(); } }); listview lv = (listview)findviewbyid(r.id.datepickermonthlistview); lv.setdividerheight(0); _montharrayadapter = new montharrayadapter(this, android.r.layout.simple_list_item_1, minselectabledate, maxselectabledate); _montharrayadapter.addselecteddatechangedlistener(new procedure<date>() { @override public void execute(date input) { _selecteddate = input.gettime(); } }); lv.setadapter(_montharrayadapter); } @override public void onrestoreinstancestate(bundle savedinstancestate) { if(savedinstancestate.containskey(selected_date)) { _selecteddate = savedinstancestate.getlong(selected_date); _montharrayadapter.setselecteddate(new date(_selecteddate)); } } @override public void onsaveinstancestate(bundle savedinstancestate) { savedinstancestate.putlong(selected_date, _selecteddate); } }
having same problem, looking answer. totally didn't believe when didn't onclick method until scrolled list. i'll post answer here if find it.
right now, best guess try different events besides click (because scroll space eating complex touch events turn click event):
"downview" static variable track element being clicked.
view.setontouchlistener(new view.ontouchlistener() { @override public boolean ontouch(view v, motionevent event) { if (event.getaction() == motionevent.action_down) { downview = v; return true; } else if (event.getaction() == motionevent.action_up) { if (downview == v) { handleclick(v); return true; } downview = null; } return false; } });
Comments
Post a Comment