Chronometer
Chronometer is a ** “simple timer” component inherited from TextView. However, the Chronometer “does not show the current time” **, it shows how much time has passed since a certain start time.
The main XML attributes are as follows:
- Whether “Android :countDown” counts down. Default is false.
- Android: Format Sets the time display format. If specified, the first “%s” “is replaced with the current timer value in the form “MM:SS” or “H:MM:SS”.
Commonly used method
- Start () : starts the timer
- “Stop ()” : stops the timer
- SetBase (long) : sets the start time of the timer.
- SetFormat (String) : sets the display time format
- “SetCountDown (Boolean)” : sets whether to countdown (SDK version is greater than 23).
- “SetOnChronometerTickListener (OnChronometerTickListener)” : for the timer, binding event listeners when the timer changes trigger this listener.
The sample
Look at the above introduction is very simple, let’s do an example to understand it, first look at the effect diagram.
Main interface layout file
Keep only the Chronometer related layout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="@dimen/dimen_20">
<Chronometer
android:id="@+id/chronometer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="@dimen/dimen_20"
android:padding="@dimen/dimen_10"
android:layout_gravity="center_horizontal"
android:textColor="@color/color_188FFF" />
<Chronometer
android:id="@+id/ch_format"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="@dimen/dimen_20"
android:padding="@dimen/dimen_10"
android:layout_gravity="center_horizontal"
android:textColor="@color/color_ff0000" />
</LinearLayout>
Copy the code
Main interface code
public class ChronometerActivity extends AppCompatActivity implements View.OnClickListener {
private Button btn_start,btn_stop,btn_reset,btn_format_1;
private Chronometer chronometer,ch_format;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_textview_chronometer);// Load the layout file
initView();
}
private void initView(a) {
btn_start = findViewById(R.id.btn_start);
btn_stop = findViewById(R.id.btn_stop);
btn_reset = findViewById(R.id.btn_reset);
chronometer = findViewById(R.id.chronometer);
btn_start.setOnClickListener(this);
btn_stop.setOnClickListener(this);
btn_reset.setOnClickListener(this);
chronometer.setOnChronometerTickListener(new Chronometer.OnChronometerTickListener() {
@RequiresApi(api = Build.VERSION_CODES.N)
@Override
public void onChronometerTick(Chronometer chronometer) {
MLog.e(String.valueOf(chronometer.getBase()));
// Current time - baseline time >20 seconds
if(SystemClock.elapsedRealtime()-chronometer.getBase()>20*1000)
{
chronometer.setCountDown(true); }}}); btn_format_1 = findViewById(R.id.btn_format_1); ch_format = findViewById(R.id.ch_format); btn_format_1.setOnClickListener(this);
ch_format.setOnChronometerTickListener(new Chronometer.OnChronometerTickListener() {
@Override
public void onChronometerTick(Chronometer chronometer) {
// Current time - baseline time
long time = SystemClock.elapsedRealtime()-chronometer.getBase();
Date d = new Date(time);
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss", Locale.US);
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
// Set the format to HH:mm:ssch_format.setText(sdf.format(d)); }}); }@RequiresApi(api = Build.VERSION_CODES.N)
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_start:
/ / SystemClock elapsedRealtime (), after the number of milliseconds since boot.
// Set the baseline time
chronometer.setBase(SystemClock.elapsedRealtime());
/ / true, countdown
chronometer.setCountDown(false);
chronometer.setFormat("Timing: %s seconds");
// Start the timer
chronometer.start();
break;
case R.id.btn_stop:
// End the timer
chronometer.stop();
// Text display
ch_format.setText("Prefer");
break;
case R.id.btn_reset:
// Reset the baseline time
chronometer.setBase(SystemClock.elapsedRealtime());
break;
case R.id.btn_format_1:
ch_format.setBase(SystemClock.elapsedRealtime());
ch_format.setCountDown(false);
ch_format.start();
break; }}}Copy the code
Format Format modification
Change Format from the default 00:00(MM:SS) to 00:00:00(H:MM:SS).
Whenever the Chronometer changes, ** “onChronometerTick” ** will be triggered, so we can deal with it after it has been triggered. Get the style we want to display.
ch_format.setOnChronometerTickListener(new Chronometer.OnChronometerTickListener() {
@Override
public void onChronometerTick(Chronometer chronometer) {
// Current time - baseline time
long time = SystemClock.elapsedRealtime()-chronometer.getBase();
Date d = new Date(time);
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss", Locale.US);
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
// Set the format to HH:mm:ssch_format.setText(sdf.format(d)); }});Copy the code
Source code analysis
setBase()
public void setBase(long base) {
// Set the baseline time
mBase = base;
// Triggers the listener event
dispatchChronometerTick();
// Modify the current interface
updateText(SystemClock.elapsedRealtime());
}
Copy the code
dispatchChronometerTick()
// Triggers the listener event
void dispatchChronometerTick(a) {
if(mOnChronometerTickListener ! =null) {
mOnChronometerTickListener.onChronometerTick(this); }}Copy the code
updateText()
“Modify the current interface”, first “compare the current time with the mBase time”, second is the “difference” between the two **. DateUtils formats second, typically “MM:SS” or “H:MM:SS”, and outputs text.
If format is defined, use Formatter to further format text.
/ / modify
private synchronized void updateText(long now) {
mNow = now;
long seconds = mCountDown ? mBase - now : now - mBase;
seconds /= 1000;
boolean negative = false;
if (seconds < 0) {
seconds = -seconds;
negative = true;
}
String text = DateUtils.formatElapsedTime(mRecycle, seconds);
if (negative) {
text = getResources().getString(R.string.negative_duration, text);
}
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);
}
Copy the code
start()
public void start(a) {
mStarted = true;
updateRunning();
}
Copy the code
stop()
public void stop(a) {
mStarted = false;
updateRunning();
}
Copy the code
updateRunning()
The “start()” and ** “stop()” methods change the state of ** “mStarted” and then call “updateRunning()”. The Chronometer state consists of three parts: “mVisible” (whether the Window is visible), “mStarted” (when the Chronometer starts to time), and “isShown” **(whether the View is visible).
If the state changes, modify the current control.
- UpdateText (Long) Modify interface.
- DispatchChronometerTick () Triggers listening events.
- PostDelayed (Runnable, Long) Changes the screen after 1 second.
private void updateRunning(a) {
boolean running = mVisible && mStarted && isShown();
if(running ! = mRunning) {if (running) {
updateText(SystemClock.elapsedRealtime());
dispatchChronometerTick();
postDelayed(mTickRunnable, 1000);
} else{ removeCallbacks(mTickRunnable); } mRunning = running; }}Copy the code
setFormat(String)
// The default is "MM:SS" or "H:MM:SS"
public void setFormat(String format) {
mFormat = format;
if(format ! =null && mFormatBuilder == null) {
mFormatBuilder = new StringBuilder(format.length() * 2); }}Copy the code
setCountDown()
public void setCountDown(boolean countDown) {
mCountDown = countDown;
updateText(SystemClock.elapsedRealtime());
}
Copy the code
There are updateText ()
When you setCountDown(true), add a “-” to the current timing value. Such as:
- SetCountDown (false) shows: timer: ** “20” ** seconds,
- SetCountDown (true) Displays: timer: ** “-20” ** seconds,
That’s all for this article, hopefully to help and inspire you to learn the Android Chronometer.