setText in CountDownTimer in ListView Adapter in Android?

2.8k views Asked by At

I am working in an Wedding App where I am maintaining a ListView of feeds.

The First element of my Feed Screen ListView is having a TIMER for the CURRENT DATE to the WEDDING DATE.

As I have taken the TIMER in a ListView, it getting hard to update the text of the TextView in onTick() method.

Wedding time is only visible in the first element of the list view.

_time = new CountDownTimer(WeddingTimeinMiliSec, 5000) {
                String showDate;
                long subtractvalue = 1000;

                Calendar currentTime = Calendar.getInstance();

                public void onTick(long millisUntilFinished) {
                    long diff = Day.getTimeInMillis() - currentTime.getTimeInMillis();
                    diff-=subtractvalue;
                    StringBuffer text = new StringBuffer("");
                    if (diff > DAY) {
                        //showDate = showDate+""+(diff / DAY)+("days ");
                        final long dif = diff;
                        if(holder!=null && holder._dayRespTextView!=null){
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    holder._dayRespTextView.setText(String.valueOf((dif / DAY)));
                                }
                            });
                        }
                        text.append(diff / DAY).append(" days ");
                        diff %= DAY;
                    }
                    if (diff > HOUR) {
                        //  showDate = showDate+""+(diff / HOUR)+("hours ");
                        final long dif = diff;
                        if(holder!=null && holder._hoursRespTextView!=null){
                            runOnUiThread(new Runnable() {
                                public void run() {
                                    holder._hoursRespTextView.setText(String.valueOf((dif / HOUR)));
                                }
                            });
                        }
                        text.append(diff / HOUR).append(" hours ");
                        diff %= HOUR;
                    }
                    if (diff > MINUTE) {
                        //  showDate = showDate+""+(diff / MINUTE)+("minutes ");
                        final long dif = diff;
                        if(holder!=null && holder._minRespTextView!=null){
                            runOnUiThread(new Runnable() {
                                public void run() {
                                    holder._minRespTextView.setText(String.valueOf((dif / MINUTE)));
                                }
                            });
                        }

                        text.append(diff / MINUTE).append(" minutes ");
                        diff %= MINUTE;
                    }
                    if (diff > SECOND) {
                        //  showDate = showDate+""+(diff / SECOND)+("seconds ");
                        final long dif = diff;
                        if(holder!=null && holder._secRespTextView!=null){
                            runOnUiThread(new Runnable() {
                                public void run() {
                                    holder._secRespTextView.setText(String.valueOf((dif / SECOND)));
                                }
                            });                         
                        }

                        text.append(diff / SECOND).append(" seconds ");
                        diff %= SECOND;
                    }
                    /*_tvTime.setText(""+WeddingTime);*/    
                    showDate="";
                    subtractvalue+=1000;
                    notifyDataSetChanged();
                }
                public void onFinish() {

                }
            }.start();

This is my CountDownTimer code that I am using inside the CONSTRUCTOR of my ListView ADAPTER.

How can I update the text of the TextViews in the ListView's first element on onTick event. Please suggest me.

2

There are 2 answers

0
Anjali Tripathi On BEST ANSWER

try this..

/**
* ADDING HEADER LAYOUT TO THE LISTVIEW
*/

View headerView = ((LayoutInflater)PostScreen.this.getSystemService(PostScreen.this.LAYOUT_INFLATER_SERVICE)).
inflate(R.layout.header_layout, null, false);
textview = (TextView)headerView.findViewById(R.id.countdown_tv);


 _time = new CountDownTimer(WeddingTimeinMiliSec, 5000) {
String showDate;
long subtractvalue = 1000;

Calendar currentTime = Calendar.getInstance();
public void onTick(long millisUntilFinished) {
long diff = Day.getTimeInMillis() - currentTime.getTimeInMillis();
diff-=subtractvalue;
StringBuffer text = new StringBuffer("");
if (diff > DAY) {
//showDate = showDate+""+(diff / DAY)+("days ");
final long dif = diff;
dayThread = String.valueOf((dif / DAY));
text.append(diff / DAY).append(" days ");
diff %= DAY;
}
if (diff > HOUR) {
final long dif = diff;
hoursThread = String.valueOf((dif / HOUR));
text.append(diff / HOUR).append(" hours ");
diff %= HOUR;
}
if (diff > MINUTE) {
final long dif = diff;
minThread = String.valueOf((dif / MINUTE));
text.append(diff / MINUTE).append(" minutes ");
diff %= MINUTE;
}
if (diff > SECOND) {
final long dif = diff;
secThread = String.valueOf((dif / SECOND));
text.append(diff / SECOND).append(" seconds ");
diff %= SECOND;
}
showDate="";
subtractvalue+=1000;

String dateText = "<font color="+countDown_TextColor+">"+dayThread+
" DIAS </font> <font color="+countDown_TextColor+">"+hoursThread+
" HOURAS </font><font color="+countDown_TextColor+">"+minThread+" MIN</font>" +
"<font color="+countDown_TextColor+">"+secThread+" MIN</font>";
textview.setText(Html.fromHtml(dateText));
}

public void onFinish() {

}
}.start();
0
dm78 On

This is an interesting question. I've never had to do this before and this answer is just a shot in the dark, but I think you would find some way forward by looking at this answer.

Basically, you need to keep track of which items are visible in your ListView. Only update the TextViews in those visible views. To track the visible items you will need to set the ListView's OnScrollListener. Use ListView#getFirstVisiblePosition() and ListView#getLastVisiblePosition() to save the first/last positions and then do something with that information. I would try sending them to the adapter and then do what you need to in your adapter's getView() when you are dealing with one of those positions.

Personally I might do something like having my adapter implement some interface that the OnScrollListener could use to get those positions to the adapter. You may need more than one CountDownTimer, or you may need to find an alternate method of calculating the time remaining for each event.


UPDATE

The thing with the interfaces would probably suit your purposes better, but here is a proof of concept sample code that will help my point be understood.

This code displays a very simple list in which all even numbered items have a time display that is updated once per second. I make no claims as to the efficiency of this solution, only that it performs the intended task:


MainActivity.java

package com.example.selectivelistitemupdating;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView;

public class MainActivity extends Activity {

    ListView mListView;
    MyCountDownTimer mMyCountDownTimer;

    @Override
    protected void onCreate( Bundle savedInstanceState ) {

        super.onCreate( savedInstanceState );
        setContentView( R.layout.activity_main );

        mListView = (ListView) findViewById( R.id.listView );
        MyAdapter adapter = new MyAdapter( this );
        mListView.setAdapter( adapter );

        mMyCountDownTimer = new MyCountDownTimer( 1000, 1000, adapter );
    }

    @Override
    protected void onResume() {

        super.onResume();
        mMyCountDownTimer.start();
    }

    @Override
    protected void onPause() {

        mMyCountDownTimer.cancel();
        super.onPause();
    }
}

MyCountDownTimer.java

package com.example.selectivelistitemupdating;

import android.os.CountDownTimer;
import android.widget.BaseAdapter;

public class MyCountDownTimer extends CountDownTimer {

    BaseAdapter mAdapter;

    public MyCountDownTimer(long millisInFuture, long countDownInterval, BaseAdapter adapter) {

        super( millisInFuture, countDownInterval );
        mAdapter = adapter;
    }

    @Override
    public void onFinish() {

        mAdapter.notifyDataSetChanged();
        this.start();
    }

    @Override
    public void onTick( long millisUntilFinished ) {

        // NO OP
    }

}

MyAdapter.java

package com.example.selectivelistitemupdating;

import java.text.DateFormat;
import java.util.Calendar;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

public class MyAdapter extends BaseAdapter {

    private static final int COUNT = 30;

    private Context context;
    private DateFormat dateFormat;

    public MyAdapter(Context context) {

        this.context = context;
        dateFormat = DateFormat.getTimeInstance();
    }

    @Override
    public int getCount() {

        return COUNT;
    }

    @Override
    public String getItem( int position ) {

        return "Item " + String.valueOf( position );
    }

    @Override
    public long getItemId( int position ) {

        return position;
    }

    @Override
    public View getView( int position, View convertView, ViewGroup parent ) {

        if ( convertView == null ) {
            convertView = LayoutInflater.from( getContext() ).inflate( android.R.layout.two_line_list_item, parent, false );
        }

        TextView text1 = (TextView) convertView.findViewById( android.R.id.text1 );
        TextView text2 = (TextView) convertView.findViewById( android.R.id.text2 );

        text1.setText( getItem( position ) );
        text2.setText( getTimeString( position ) );

        return convertView;
    }

    private CharSequence getTimeString( int position ) {

        if ( position % 2 == 0 ) {

            return dateFormat.format( Calendar.getInstance().getTime() );
        }
        else {
            return null;
        }
    }

    private Context getContext() {

        return context;
    }
}

activity_main.xml

<ListView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/listView"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />