Dennis Zinkovski
Dennis Zinkovski

Reputation: 1851

After scrolling in the listview, elements are swapped

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

Answers (2)

Dennis Zinkovski
Dennis Zinkovski

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

Ankit Kumar
Ankit Kumar

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

Related Questions