Reputation: 1851
I writing time-tracking app, every row of listview has two buttons(Start and Stop) and some textView to display elapsed time.
After scrolling in the listview, elements are swapped.
I'm not sure in my solution, but i put in the model class, ViewHolder object for getting acces for changing view elements.
Here is the fragment of code model
private String name;
private Boolean isStart=false;
private Long elapsedTime=0L,seconds=0L,hours=0L,minutes=0L,lastPause=0L,updateTime=0L,startTime=0L,days=0L;
private Runnable updateTimeThread=new Runnable() {
@Override
public void run() {
if(isStart && startTime!=0) {
updateTime = ((System.currentTimeMillis() - startTime) + lastPause);
seconds = updateTime / 1000;
minutes = seconds / 60;
hours = minutes / 60;
seconds = seconds % 60;
minutes = minutes % 60;
hours = hours % 24;
holder.days.setText(String.format("%04d", days));
holder.hours.setText(String.format("%02d", hours));
holder.minutes.setText(String.format("%02d", minutes));
holder.seconds.setText(String.format("%02d", seconds));
Log.d("myTag",name+" "+seconds);
MainActivity.handler.post(this);
}
}
};
MyAdapter.ViewHolder holder;
public MyAdapter.ViewHolder getHolder() {
return holder;
}
public void setHolder(MyAdapter.ViewHolder holder) {
this.holder = holder;
}
public Runnable getRunnable() {
return updateTimeThread;
}
Adapter's fragment code
public View getView(final int position, final View convertView, ViewGroup parent) {
View row = convertView;
final Tracker tracker = trackerList.get(position);
final Runnable updateTimeThread=tracker.getRunnable();
View.OnClickListener onClickListener;
ViewHolder holder;
if(row == null){
holder = new ViewHolder();
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(R.layout.row,parent,false);
holder.name = (TextView)row.findViewById(R.id.tvName);
holder.days = (TextView)row.findViewById(R.id.tvDays);
holder.hours = (TextView)row.findViewById(R.id.tvHours);
holder.minutes = (TextView)row.findViewById(R.id.tvMinutes);
holder.seconds = (TextView)row.findViewById(R.id.tvSeconds);
holder.start = (Button)row.findViewById(R.id.btStart);
holder.stop = (Button)row.findViewById(R.id.btStop);
row.setTag(holder);
}else {
holder = (ViewHolder) row.getTag();
}
holder.start.setEnabled(true);
holder.stop.setEnabled(false);
holder.name.setText(tracker.getName());
final ViewHolder finalHolder = holder;
if(tracker.getIsStart()){
holder.start.setEnabled(false);
holder.stop.setEnabled(true);
}
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btStart:
tracker.setStartTime(System.currentTimeMillis());
tracker.setIsStart(true);
tracker.setHolder(finalHolder);
MainActivity.handler.post(updateTimeThread);
finalHolder.start.setEnabled(false);
finalHolder.stop.setEnabled(true);
break;
case R.id.btStop:
tracker.setLastPause(tracker.getUpdateTime());
MainActivity.handler.removeCallbacks(updateTimeThread);
finalHolder.stop.setEnabled(false);
finalHolder.start.setEnabled(true);
tracker.setIsStart(false);
break;
}
}
};
holder.start.setOnClickListener(onClickListener);
holder.stop.setOnClickListener(onClickListener);
return row;
}
static class ViewHolder{
TextView name,days,hours,minutes,seconds;
Button start,stop;
}
Upvotes: 0
Views: 74
Reputation: 1851
I just add these two methods to my adapter)
@Override
public int getViewTypeCount() {
return getCount();
}
@Override
public int getItemViewType(int position) {
return position;
}
UPDATE But with Loader Callback problem is still the same. I press Start on last item and scroll down, values not visible, scroll up a bit and values visible. Pity.
UPDATE 2 This article solve my problem, i just change layout-height and laoyut-weight from "wrap_content" to "fill_parent" to avoid multiple calling getView() method. http://gmariotti.blogspot.com/2013/06/tips-for-listview-view-recycling-use.html
Upvotes: 1
Reputation: 3721
Change this part
holder.start.setEnabled(true);
holder.stop.setEnabled(false);
holder.name.setText(tracker.getName());
final ViewHolder finalHolder = holder;
if(tracker.getIsStart()){
holder.start.setEnabled(false);
holder.stop.setEnabled(true);
}
to this
final ViewHolder finalholfder = holder;
finalholfder.start.setEnabled(true);
finalholfder.stop.setEnabled(false);
finalholfder.name.setText(tracker.getName());
if(tracker.getIsStart()){
finalholfder.start.setEnabled(false);
finalholfder.stop.setEnabled(true);
} else{
finalholfder.start.setEnabled(true);
finalholfder.stop.setEnabled(false);
}
And this
holder.start.setOnClickListener(onClickListener);
holder.stop.setOnClickListener(onClickListener);
to this
finalholfder.start.setOnClickListener(onClickListener);
finalholfder.stop.setOnClickListener(onClickListener);
Upvotes: 0