Android: хронометр как постоянный секундомер. Как установить время начала? Что такое хронометр "База"? - PullRequest
8 голосов
/ 24 февраля 2010

У меня есть одна служба, работающая в фоновом режиме. Всякий раз, когда он запускается, я сохраняю в памяти время запуска в миллисекундах:

startingTime = new Date().getTime();

Я хочу отобразить хронометр, который начинает отсчет при запуске службы и никогда не останавливается, пока пользователь не нажмет кнопку. Я хочу, чтобы пользователь мог покинуть активность, отображающую хронометр, сделать некоторые вещи и затем вернуться. Но идея в том, что когда пользователь возвращается, я не хочу, чтобы хронометр снова перешел на 0:00. Insted Я хочу, чтобы он показывал точное время, прошедшее с момента запуска сервиса.

Я могу рассчитать elapsedTime каждый раз, когда пользователь возвращается к активности хронометра:

elapsedTime =  new Date().getTime() - startingTime;

Дело в том, что я не знаю, как сказать хронометру начать отсчет с того времени!

Установка его в качестве основания хронометра не работает. Кто-нибудь может объяснить, что именно означает «база» или как этого добиться?

спасибо большое! BYE

Ответы [ 7 ]

21 голосов
/ 25 февраля 2010

Вы можете использовать Хронометр .

Вы также должны проверить эту тему .

РЕДАКТИРОВАТЬ: Решение:

public class ChronoExample extends Activity {
 Chronometer mChronometer;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);

     LinearLayout layout = new LinearLayout(this);
     layout.setOrientation(LinearLayout.VERTICAL);

     mChronometer = new Chronometer(this);

     // Set the initial value
     mChronometer.setText("00:10");
     layout.addView(mChronometer);

     Button startButton = new Button(this);
     startButton.setText("Start");
     startButton.setOnClickListener(mStartListener);
     layout.addView(startButton);

     Button stopButton = new Button(this);
     stopButton.setText("Stop");
     stopButton.setOnClickListener(mStopListener);
     layout.addView(stopButton);

     Button resetButton = new Button(this);
     resetButton.setText("Reset");
     resetButton.setOnClickListener(mResetListener);
     layout.addView(resetButton);        

     setContentView(layout);
 }

 private void showElapsedTime() {
     long elapsedMillis = SystemClock.elapsedRealtime() - mChronometer.getBase();            
     Toast.makeText(ChronoExample.this, "Elapsed milliseconds: " + elapsedMillis, 
             Toast.LENGTH_SHORT).show();
 }

 View.OnClickListener mStartListener = new OnClickListener() {
     public void onClick(View v) {
      int stoppedMilliseconds = 0;

         String chronoText = mChronometer.getText().toString();
         String array[] = chronoText.split(":");
         if (array.length == 2) {
           stoppedMilliseconds = Integer.parseInt(array[0]) * 60 * 1000
               + Integer.parseInt(array[1]) * 1000;
         } else if (array.length == 3) {
           stoppedMilliseconds = Integer.parseInt(array[0]) * 60 * 60 * 1000 
               + Integer.parseInt(array[1]) * 60 * 1000
               + Integer.parseInt(array[2]) * 1000;
         }

         mChronometer.setBase(SystemClock.elapsedRealtime() - stoppedMilliseconds);
         mChronometer.start();
     }
 };

 View.OnClickListener mStopListener = new OnClickListener() {
     public void onClick(View v) {
         mChronometer.stop();
         showElapsedTime();
     }
 };

 View.OnClickListener mResetListener = new OnClickListener() {
     public void onClick(View v) {
         mChronometer.setBase(SystemClock.elapsedRealtime());
         showElapsedTime();
     }
 };
}
4 голосов
/ 03 апреля 2014

Для запуска хронометра вы должны использовать метод setBase() вашего хронометра с SystemClock.elapsedRealTime(). Просто так:

mChronometer.setBase(SystemClock.elapsedRealTime())

Но если вы хотите начать в другое время, вы должны вычесть необходимое время в миллисекундах. Например, вы хотите запустить хронометр через 10 секунд:

mChronometer.setBase(SystemClock.elapsedRealTime() - 10*1000);

Через 2 минуты:

mChronometer.setBase(SystemClock.elapsedRealTime() - 2*60*1000);

Но проблема здесь в том, что хронометр покажет время «00:00» до того, как начнет отсчитывать, чтобы изменить его на ваше время, вы должны сделать это:

mChronometer.setText("02:00");
4 голосов
/ 26 февраля 2010

Базовое время - это время начала тикания Chronometer. Вы можете установить его, используя Chronometer.setBase(). Вы должны получить базовое время, используя SystemClock.getElapsedTime(). Звоните setBase() с указанием времени начала каждый раз, когда Chronometer запускается. Если существует вероятность того, что Activity будет уничтожен и воссоздан, пока таймер еще активен, вам нужно будет удерживать базовое время где-то за пределами Activity, которому принадлежит Chronometer.

1 голос
/ 29 марта 2017

Как установить время запуска? Что такое хронометр «База»?

Используйте SystemClock.elapsedRealtime() для этой цели:

   myChronometer.setBase(SystemClock.elapsedRealtime());
1 голос
/ 16 ноября 2014

Когда вы устанавливаете базовое время с помощью .setBase (SystemClock.elapsedRealTime ()), хронометр начинает отсчитывать с 00.00, но время, которое он сохраняет, представляет собой количество милисек при загрузке. Когда вы используете .stop, внутренний счетчик не останавливается, только время, которое вы видите на часах. Таким образом, если вы снова используете .start, счетчик часов перейдет к реальному счету. Если вы хотите сохранить время, прошедшее с начала, вы должны снова получить истекшее время системы и изменить значение .setTime

1 голос
/ 25 сентября 2014

Это работает для меня:

Date now = new Date();
long elapsedTime = now.getTime() - startTime.getTime(); //startTime is whatever time you want to start the chronometer from. you might have stored it somwehere
myChronometer.setBase(SystemClock.elapsedRealtime() - elapsedTime);
myChronometer.start();
1 голос
/ 27 сентября 2013

Несколько странно с SystemClock.getElapsedTime (), я сделал некоторые изменения для обычного использования с датой начала, например

myChron.setBase(startDate.getTime());

Вот дитя хронометра внизу, TimeView

import android.R;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.text.format.DateUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.Chronometer;
import android.widget.RemoteViews;

import java.util.Formatter;
import java.util.IllegalFormatException;
import java.util.Locale;

@RemoteViews.RemoteView
public class TimeView extends Chronometer {
    private static final String TAG = "TimeView";

    private long mBase;
    private boolean mVisible;
    private boolean mStarted;
    private boolean mRunning;
    private boolean mLogged;
    private String mFormat;
    private Formatter mFormatter;
    private Locale mFormatterLocale;
    private Object[] mFormatterArgs = new Object[1];
    private StringBuilder mFormatBuilder;
    private OnChronometerTickListener mOnChronometerTickListener;
    private StringBuilder mRecycle = new StringBuilder(8);

    private static final int TICK_WHAT = 2;

    /**
     * Initialize this Chronometer object.
     * Sets the base to the current time.
     */
    public TimeView(Context context) {
        this(context, null, 0);
    }

    /**
     * Initialize with standard view layout information.
     * Sets the base to the current time.
     */
    public TimeView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    /**
     * Initialize with standard view layout information and style.
     * Sets the base to the current time.
     */
    public TimeView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {
        mBase = System.currentTimeMillis();
        updateText(mBase);
    }

    public void setBase(long base) {
        mBase = base;
        dispatchChronometerTick();
        updateText(System.currentTimeMillis());
    }

    /**
     * Return the base time as set through {@link #setBase}.
     */
    public long getBase() {
        return mBase;
    }

    public void start() {
        mStarted = true;
        updateRunning();
    }

    /**
     * Stop counting up.  This does not affect the base as set from {@link #setBase}, just
     * the view display.
     * <p/>
     * This stops the messages to the handler, effectively releasing resources that would
     * be held as the chronometer is running, via {@link #start}.
     */
    public void stop() {
        mStarted = false;
        updateRunning();
    }

    /**
     * The same as calling {@link #start} or {@link #stop}.
     *
     * @hide pending API council approval
     */
    public void setStarted(boolean started) {
        mStarted = started;
        updateRunning();
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        mVisible = false;
        updateRunning();
    }

    @Override
    protected void onWindowVisibilityChanged(int visibility) {
        super.onWindowVisibilityChanged(visibility);
        mVisible = visibility == VISIBLE;
        updateRunning();
    }

    private synchronized void updateText(long now) {
        long seconds = now - mBase;
        seconds /= 1000;
        String text = DateUtils.formatElapsedTime(mRecycle, seconds);

        if (mFormat != null) {
            Locale loc = Locale.getDefault();
            if (mFormatter == null || !loc.equals(mFormatterLocale)) {
                mFormatterLocale = loc;
                mFormatter = new Formatter(mFormatBuilder, loc);
            }
            mFormatBuilder.setLength(0);
            mFormatterArgs[0] = text;
            try {
                mFormatter.format(mFormat, mFormatterArgs);
                text = mFormatBuilder.toString();
            } catch (IllegalFormatException ex) {
                if (!mLogged) {
                    Log.w(TAG, "Illegal format string: " + mFormat);
                    mLogged = true;
                }
            }
        }
        setText(text);
    }

    private void updateRunning() {
        boolean running = mVisible && mStarted;
        if (running != mRunning) {
            if (running) {
                updateText(System.currentTimeMillis());
                dispatchChronometerTick();
                mHandler.sendMessageDelayed(Message.obtain(mHandler, TICK_WHAT), 1000);
            } else {
                mHandler.removeMessages(TICK_WHAT);
            }
            mRunning = running;
        }
    }

    private Handler mHandler = new Handler() {
        public void handleMessage(Message m) {
            if (mRunning) {
                updateText(System.currentTimeMillis());
                dispatchChronometerTick();
                sendMessageDelayed(Message.obtain(this, TICK_WHAT), 1000);
            }
        }
    };

    void dispatchChronometerTick() {
        if (mOnChronometerTickListener != null) {
            mOnChronometerTickListener.onChronometerTick(this);
        }
    }
}

Просто скопируйте и используйте, у меня все работает

...