前言:
2017年的短视频行业,盛况空前,风头无二,市场中不断涌现出各类短视频平台,已多达上百家,小咖秀可以说是短视频中的“元老”,功能齐全,拍摄体验也很棒。我个人觉得小咖秀的拍摄倒计时设计是很人性化的,支持选择时长,有三秒、五秒、十秒等,玩起来还是很舒服的。作为移动端开发者,看到有意思的功能,第一个想到的当然是我能不能也做成这样!所以我简单写了个demo,仅仅模仿了一下倒计时效果。
github:https://github.com/kb18519142009/CountDownDemo
效果图:
正文:
一、思路以及准备
1、说到倒计时,我想到了CountDownTimer这个类,它实现了倒计时的基本功能,先看看它的构造方法:
public CountDownTimer(long millisInFuture, long countDownInterval) {
......
}
第一个参数millisInFuture表示倒计时的总时长,第二个参数countDownInterval表示倒计时的间隔时间,比如CountDownTimer(3000, 1000) ,表示倒计时总时长为3s,间隔为1s。
2、接下来就是动画,我选择了缩放动画ScaleAnimation,它有四个构造方法,我用了参数最多的一个:
public ScaleAnimation(float fromX, float toX, float fromY, float toY,
int pivotXType, float pivotXValue, int pivotYType, float pivotYValue) {
......
}
fromX:X轴开始动画缩放的比例
toX:X轴结束时动画缩放的比例
fromY:Y轴开始动画缩放的比例
toY:Y轴结束动画缩放的比例
pivotXType:指定pivotXValue的相对位置,取值:Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, Animation.RELATIVE_TO_PARENT
pivotXValue:固定点X轴坐标,取值1%~100%
pivotYType:取值:Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, Animation.RELATIVE_TO_PARENT
pivotYValue:固定点Y轴坐标,取值1%~100%
除了构造函数的这些参数,我们还可以给动画设置时长,重复次数,重复模式等等。
二、具体实现
1、布局文件
在这里倒计时可以是单纯的数字,用TextView实现,也可以直接用图片搞定。
TextView的方式:
<TextView
android:id="@+id/tv_count_timer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center"
android:background="@drawable/bg_video_duration"
android:paddingBottom="5dp"
android:paddingEnd="25dp"
android:paddingStart="25dp"
android:paddingTop="5dp"
android:textColor="#fff"
android:textSize="80sp"/>
其中我们给了TextView一个background,来实现透明阴影的效果,在drawable下创建shape如下:
<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="rectangle" xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="15dip" />
<solid android:color="#7F000000"/>
</shape>
2、创建倒计时类RecordCountTimer
这个类继承至CountDownTimer,在构造函数中拿到要执行动画的view并且创建了动画,实现了onTick和onFinish方法,onTick在每个间隔时间调用,onFinish在倒计时结束时调用,然后在onTic中执行动画即可,代码比较简单,我就直接贴上来啦:
public class RecordCountTimer extends CountDownTimer {
private static final int TIME_COUNT = 3100; //倒计时总时间为3.1s,时间防止从2s开始显示(以倒计时3s为例子)
private static final int TIME_INTERVAL = 1000; //倒计时间隔为1s
private View view; //要设置动画的view
private boolean mIsAnimStart;
private AlphaAnimation alphaAnimation; //渐变动画
private ScaleAnimation scaleAnimation; //缩放动画
private OnCountTimerListener mOnCountTimerListener;
public void setOnCountTimerListener(OnCountTimerListener onFinishListener) {
this.mOnCountTimerListener = onFinishListener;
}
//倒计时开始和结束的监听
public interface OnCountTimerListener {
void onStart();
void onFinish();
}
/**
* @param view 要执行动画的view
*/
public RecordCountTimer(View view) {
this(TIME_COUNT, TIME_INTERVAL, view);
}
/**
* 倒计时的view 可以是TextView、Button或者ImageView
*
* @param millisInFuture 表示从计时开始到结束的毫秒数
* @param countDownInterval 表示onTick(long)回调的间隔时间
* @param view 要执行动画的view
*/
public RecordCountTimer(long millisInFuture, long countDownInterval, View view) {
super(millisInFuture, countDownInterval);
this.view = view;
// 设置透明度渐变动画
alphaAnimation = new AlphaAnimation(0, 1);
// 设置动画持续时间
alphaAnimation.setDuration(500);
// 设置缩放渐变动画
scaleAnimation = new ScaleAnimation(0.1f, 1f, 0.1f, 1f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
scaleAnimation.setDuration(500); //设置动画时长
scaleAnimation.setRepeatCount(1); //设置重复次数
scaleAnimation.setRepeatMode(Animation.REVERSE); //重复模式,reverse表示反向进行,在这里先放大,后缩小
scaleAnimation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
if (mOnCountTimerListener != null) {
mOnCountTimerListener.onFinish();
}
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
}
@Override
public void onTick(long millisUntilFinished) {
if (!mIsAnimStart) {
mIsAnimStart = true;
if (mOnCountTimerListener != null) {
mOnCountTimerListener.onStart();
}
}
//每隔一秒修改一次UI
if (view instanceof ImageView) { // 如果是图片,在此判断,每隔一秒,改变一次图片
if (millisUntilFinished / 1000 == 1) {
((ImageView) view).setImageResource(R.drawable.img_show_count_down_1);
} else if (millisUntilFinished / 1000 == 2) {
((ImageView) view).setImageResource(R.drawable.img_show_count_down_2);
} else if (millisUntilFinished / 1000 == 3) {
((ImageView) view).setImageResource(R.drawable.img_show_count_down_3);
}
} else if (view instanceof TextView) {
((TextView) view).setText(String.valueOf(millisUntilFinished / 1000));
}
view.setVisibility(View.VISIBLE);
view.setEnabled(false);
view.startAnimation(alphaAnimation);
view.startAnimation(scaleAnimation);
}
@Override
public void onFinish() {
}
}
3、再贴上MainActivity的代码
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
// private TextView mCountTimerView; // 数字倒计时
private ImageView mCountTimerView; // 图片倒计时
private Button mBtnCountDown; //开始按钮
private RecordCountTimer mCountTimer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// mCountTimerView = findViewById(R.id.tv_count_timer);
mCountTimerView = findViewById(R.id.iv_count_timer);
mBtnCountDown = findViewById(R.id.btn_count_down);
mBtnCountDown.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (v == mBtnCountDown) {
mCountTimer = new RecordCountTimer(mCountTimerView);
mCountTimer.setOnCountTimerListener(new RecordCountTimer.OnCountTimerListener() {
@Override
public void onStart() {
//倒计时开始
mBtnCountDown.setVisibility(View.GONE);
}
@Override
public void onFinish() {
//倒计时结束
mCountTimerView.setVisibility(View.GONE);
mBtnCountDown.setVisibility(View.VISIBLE);
}
});
mCountTimer.start();
}
}
}
这里我加了一个按钮,点击按钮倒计时动画开始,在开始回调onStart()中隐藏按钮;动画结束,在结束回调中隐藏倒计时view,显示按钮。
看看布局:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
tools:context="com.example.countdowndemo.MainActivity">
<ImageView
android:id="@+id/iv_count_timer"
android:layout_width="60dp"
android:layout_height="100dp"
android:layout_centerInParent="true"
android:visibility="gone" />
<TextView
android:id="@+id/tv_count_timer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center"
android:background="@drawable/bg_video_duration"
android:paddingBottom="5dp"
android:paddingEnd="25dp"
android:paddingStart="25dp"
android:paddingTop="5dp"
android:textColor="#fff"
android:textSize="80sp"
android:visibility="gone" />
<Button
android:id="@+id/btn_count_down"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="3S倒计时开始"/>
</RelativeLayout>
OK!搞定啦!很简单的小Demo,有想看源码的请移步github:
https://github.com/kb18519142009/CountDownDemo
个人水平有限,大家有建议请尽管提,一起学习一起进步!谢谢!