> 文章列表 > Android 自定义View 之 计时文字

Android 自定义View 之 计时文字

Android 自定义View 之 计时文字

计时文字

  • 前言
  • 正文
    • 一、XML样式
    • 二、构造方法
    • 三、API方法
    • 四、使用
    • 五、源码

前言

  在Android开发中,常常会有计时的一些操作,例如收验证码的时候倒计时,秒表的计时等等,于是我就有了一个写自定义View的想法,本文效果图。

在这里插入图片描述

正文

  那么现在我们将想法换成现实,这个自定义View比较简单,我们来看怎么写的,首先我们还是在EasyView中进行添加。

一、XML样式

  根据上面的效果图,我们首先来确定XML中的属性样式,在attrs.xml中增加如下代码

    <!--计时文字--><declare-styleable name="TimingTextView"><!--倒计时--><attr name="countdown" format="boolean" /><!--时间最大值--><attr name="max" format="integer" /><!--时间单位,时:h,分:m,秒:s--><attr name="unit"><enum name="h" value="1" /><enum name="m" value="2" /><enum name="s" value="3" /></attr></declare-styleable>

  这里的计时文字目前有3个属性,第一个boolean用来确定是计时还是倒计时,第二个是最大时间,第三个是时间单位:时分秒。

二、构造方法

  之前我说自定义View有三种方式,一种是继承View,一种是继承现有的View,还有一种是继承ViewGroup,那么今天的这个计时文字,我们就可以继承现有的View,这样做的目的就是可以让我们减少一定的工作量,专注于功能上,下面我们在com.llw.easyview包下新建一个TimingTextView类,里面的代码如下所示:

public class TimingTextView extends MaterialTextView {/*** 时间单位*/private int mUnit;/*** 计时最大值*/private int mMax;/*** 是否倒计时*/private boolean mCountDown;private int mTotal;/*** 是否计时中*/private boolean mTiming;public TimingTextView(Context context) {this(context, null);}public TimingTextView(Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);}public TimingTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);@SuppressLint("CustomViewStyleable")TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.TimingTextView);mCountDown = typedArray.getBoolean(R.styleable.TimingTextView_countdown, false);mMax = typedArray.getInteger(R.styleable.TimingTextView_max, 60);mUnit = typedArray.getInt(R.styleable.TimingTextView_unit, 3);typedArray.recycle();}
}

  因为有计时的缘故,所以我们需要一个计时监听,主要用于结束的时候进行调用,可以在com.llw.easyview下新建一个TimingListener接口,代码如下:

public interface TimingListener {void onEnd();
}

三、API方法

下面在TimingTextView中新增一些API方法和变量,首先增加变量:

    private TimingListener listener;private CountDownTimer countDownTimer;

然后增加API方法:

    /*** 设置时间单位** @param unit 1,2,3*/public void setUnit(int unit) {if (unit <= 0 || unit > 3) {throw new IllegalArgumentException("unit value can only be between 1 and 3");}mUnit = unit;}/*** 设置最大时间值** @param max 最大值*/public void setMax(int max) {mMax = max;}/*** 设置是否为倒计时** @param isCountDown true or false*/public void setCountDown(boolean isCountDown) {mCountDown = isCountDown;}public void setListener(TimingListener listener) {this.listener = listener;}public boolean isTiming() {return mTiming;}/*** 开始*/public void start() {switch (mUnit) {case 1:mTotal = mMax * 60 * 60 * 1000;break;case 2:mTotal = mMax * 60 * 1000;break;case 3:mTotal = mMax * 1000;break;}if (countDownTimer == null) {countDownTimer = new CountDownTimer(mTotal, 1000) {@Overridepublic void onTick(long millisUntilFinished) {int time = 0;if (mCountDown) {time = (int)  (millisUntilFinished / 1000);setText(String.valueOf(time));} else {time = (int) (mTotal / 1000 - millisUntilFinished / 1000);}setText(String.valueOf(time));}@Overridepublic void onFinish() {//倒计时结束end();}};mTiming = true;countDownTimer.start();}}/*** 计时结束*/public void end() {mTotal = 0;mTiming = false;countDownTimer.cancel();countDownTimer = null;if (listener != null) {listener.onEnd();}}

代码还是很简单的,你敢信,这个自定义View就写完了,不过可能存在一些问题,我将自定义View的代码都放到了一个library下面里,然后将这个library进行构建成aar,然后上传到mavenCentral()中。

四、使用

  然后我们修改一下activity_main.xml,代码如下所示:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:orientation="vertical"android:padding="16dp"tools:context=".MainActivity"><com.easy.view.MacAddressEditTextandroid:id="@+id/mac_et"android:layout_width="wrap_content"android:layout_height="wrap_content"app:boxBackgroundColor="@color/white"app:boxStrokeColor="@color/black"app:boxStrokeWidth="2dp"app:boxWidth="48dp"app:separator=":"app:textColor="@color/black"app:textSize="16sp" /><Buttonandroid:id="@+id/btn_mac"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="30dp"android:text="获取地址" /><com.easy.view.CircularProgressBarandroid:id="@+id/cpb_test"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="30dp"app:maxProgress="100"app:progress="10"app:progressbarBackgroundColor="@color/purple_500"app:progressbarColor="@color/purple_200"app:radius="80dp"app:strokeWidth="16dp"app:text="10%"app:textColor="@color/teal_200"app:textSize="28sp" /><Buttonandroid:id="@+id/btn_set_progress"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="30dp"android:text="随机设置进度" /><com.easy.view.TimingTextViewandroid:id="@+id/tv_timing"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="30dp"android:text="计时文字"android:textColor="@color/black"android:textSize="32sp"app:countdown="false"app:max="60"app:unit="s" /><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="12dp"android:gravity="center"android:orientation="vertical"><CheckBoxandroid:id="@+id/cb_flag"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="计时" /><Buttonandroid:id="@+id/btn_start"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="开始" /></LinearLayout>
</LinearLayout>

预览效果如下图所示:

在这里插入图片描述
下面我们回到MainActivity中,在onCreate()方法中添加如下代码:

        //计时文本操作TimingTextView tvTiming = findViewById(R.id.tv_timing);CheckBox cbFlag = findViewById(R.id.cb_flag);Button btnStart = findViewById(R.id.btn_start);tvTiming.setListener(new TimingListener() {@Overridepublic void onEnd() {tvTiming.setText("计时文字");btnStart.setText("开始");}});cbFlag.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {@Overridepublic void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {cbFlag.setText(isChecked ? "倒计时" : "计时");}});//计时按钮点击btnStart.setOnClickListener(v -> {if (tvTiming.isTiming()) {//停止计时tvTiming.end();btnStart.setText("开始");} else {tvTiming.setMax(6);tvTiming.setCountDown(cbFlag.isChecked());tvTiming.setUnit(3);//单位 秒//开始计时tvTiming.start();btnStart.setText("停止");}});

下面运行一下看看:

在这里插入图片描述

五、源码

如果对你有所帮助的话,不妨 Star 或 Fork,山高水长,后会有期~

源码地址:EasyView