应用启动页自定义跳转计时器View Demo:
CircleTextProgressbar.java:
package com.demo.startpageskiptimerdemo.widget;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.text.TextUtils;
import android.util.AttributeSet;
import com.demo.startpageskiptimerdemo.R;
/**
* Created by Administrator on 2016/8/26. (自定义TextView,用于欢迎页跳过图标)
*/
public class CircleTextProgressbar extends android.support.v7.widget.AppCompatTextView {
/**
* 外部轮廓的颜色。
*/
private int outLineColor = Color.BLACK;
/**
* 外部轮廓的宽度。
*/
private int outLineWidth = 2;
/**
* 内部圆的颜色。
*/
private ColorStateList inCircleColors = ColorStateList.valueOf(Color.TRANSPARENT);
/**
* 中心圆的颜色。
*/
private int circleColor;
/**
* 进度条的颜色。
*/
private int progressLineColor = Color.WHITE;
/**
* 进度条的宽度。
*/
private int progressLineWidth = 8;
/**
* 画笔。
*/
private Paint mPaint = new Paint();
/**
* 进度条的矩形区域。
*/
private RectF mArcRect = new RectF();
/**
* 进度。
*/
private int progress = 100;
/**
* 进度条类型。
*/
private ProgressType mProgressType = ProgressType.COUNT;
/**
* 进度倒计时时间。
*/
private long timeMillis = 5000;
/**
* View的显示区域。
*/
final Rect bounds = new Rect();
/**
* 进度条通知。
*/
private OnCountdownProgressListener mCountdownProgressListener;
/**
* Listener what。
*/
private int listenerWhat = 0;
private String seconds;
public CircleTextProgressbar(Context context) {
this(context, null);
}
public CircleTextProgressbar(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CircleTextProgressbar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initialize(context, attrs);
}
public void setSeconds(String seconds) {
this.seconds = seconds;
invalidate();
}
/**
* 初始化。
*
* @param context 上下文。
* @param attributeSet 属性。
*/
private void initialize(Context context, AttributeSet attributeSet) {
mPaint.setAntiAlias(true);
TypedArray typedArray = context.obtainStyledAttributes(attributeSet, R.styleable.CircleTextProgressbar);
if (typedArray.hasValue(R.styleable.CircleTextProgressbar_in_circle_color))
inCircleColors = typedArray.getColorStateList(R.styleable.CircleTextProgressbar_in_circle_color);
else
inCircleColors = ColorStateList.valueOf(Color.TRANSPARENT);
circleColor = inCircleColors.getColorForState(getDrawableState(), Color.TRANSPARENT);
typedArray.recycle();
}
/**
* 设置外部轮廓的颜色。
*
* @param outLineColor 颜色值。
*/
// public void setOutLineColor(@ColorInt int outLineColor) {
public void setOutLineColor(int outLineColor) {
this.outLineColor = outLineColor;
invalidate();
}
/**
* 设置外部轮廓的颜色。
*
* @param outLineWidth 颜色值。
*/
// public void setOutLineWidth(@ColorInt int outLineWidth) {
public void setOutLineWidth(int outLineWidth) {
this.outLineWidth = outLineWidth;
invalidate();
}
/**
* 设置圆形的填充颜色。
*
* @param inCircleColor 颜色值。
*/
// public void setInCircleColor(@ColorInt int inCircleColor) {
public void setInCircleColor(int inCircleColor) {
this.inCircleColors = ColorStateList.valueOf(inCircleColor);
invalidate();
}
/**
* 是否需要更新圆的颜色。
*/
private void validateCircleColor() {
int circleColorTemp = inCircleColors.getColorForState(getDrawableState(), Color.TRANSPARENT);
if (circleColor != circleColorTemp) {
circleColor = circleColorTemp;
invalidate();
}
}
/**
* 设置进度条颜色。
*
* @param progressLineColor 颜色值。
*/
// public void setProgressColor(@ColorInt int progressLineColor) {
public void setProgressColor(int progressLineColor) {
this.progressLineColor = progressLineColor;
invalidate();
}
/**
* 设置进度条线的宽度。
*
* @param progressLineWidth 宽度值。
*/
public void setProgressLineWidth(int progressLineWidth) {
this.progressLineWidth = progressLineWidth;
invalidate();
}
/**
* 设置进度。
*
* @param progress 进度。
*/
public void setProgress(int progress) {
this.progress = validateProgress(progress);
invalidate();
}
/**
* 验证进度。
*
* @param progress 你要验证的进度值。
* @return 返回真正的进度值。
*/
private int validateProgress(int progress) {
if (progress > 100)
progress = 100;
else if (progress < 0)
progress = 0;
return progress;
}
/**
* 拿到此时的进度。
*
* @return 进度值,最大100,最小0。
*/
public int getProgress() {
return progress;
}
/**
* 设置倒计时总时间。
*
* @param timeMillis 毫秒。
*/
public void setTimeMillis(long timeMillis) {
this.timeMillis = timeMillis;
invalidate();
}
/**
* 拿到进度条计时时间。
*
* @return 毫秒。
*/
public long getTimeMillis() {
return this.timeMillis;
}
/**
* 设置进度条类型。
*
* @param progressType {@link ProgressType}.
*/
public void setProgressType(ProgressType progressType) {
this.mProgressType = progressType;
resetProgress();
invalidate();
}
/**
* 重置进度。
*/
private void resetProgress() {
switch (mProgressType) {
case COUNT:
progress = 0;
break;
}
}
/**
* 拿到进度条类型。
*
* @return
*/
public ProgressType getProgressType() {
return mProgressType;
}
/**
* 设置进度监听。
*
* @param mCountdownProgressListener 监听器。
*/
public void setCountdownProgressListener(int what, OnCountdownProgressListener mCountdownProgressListener) {
this.listenerWhat = what;
this.mCountdownProgressListener = mCountdownProgressListener;
}
/**
* 开始。
*/
public void start() {
stop();
post(progressChangeTask);
}
/**
* 重新开始。
*/
public void reStart() {
resetProgress();
start();
}
/**
* 停止。
*/
public void stop() {
removeCallbacks(progressChangeTask);
}
@Override
protected void onDraw(Canvas canvas) {
// 获取view的边界
getDrawingRect(bounds);
int size = bounds.height() > bounds.width() ? bounds.width() : bounds.height();
float outerRadius = size / 2;
// 画内部背景
int circleColor = inCircleColors.getColorForState(getDrawableState(), 0);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(circleColor);
canvas.drawCircle(bounds.centerX(), bounds.centerY(), outerRadius - outLineWidth, mPaint);
// 画边框圆
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(outLineWidth);
mPaint.setColor(outLineColor);
canvas.drawCircle(bounds.centerX(), bounds.centerY(), outerRadius - outLineWidth / 2, mPaint);
// 画字
Paint paint = getPaint();
paint.setColor(getCurrentTextColor());
paint.setAntiAlias(true);
paint.setTextAlign(Paint.Align.CENTER);
float textY = bounds.centerX();
float textS = (bounds.bottom + paint.ascent() / 2) - 10;
if (!TextUtils.isEmpty(seconds))
canvas.drawText(seconds, bounds.centerX(), textS, paint);
canvas.drawText(getText().toString(), bounds.centerX(), textY, paint);
// 画进度条
mPaint.setColor(progressLineColor);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(progressLineWidth);
mPaint.setStrokeCap(Paint.Cap.ROUND);
int deleteWidth = progressLineWidth + outLineWidth;
mArcRect.set(bounds.left + deleteWidth / 2, bounds.top + deleteWidth / 2, bounds.right - deleteWidth / 2,
bounds.bottom - deleteWidth / 2);
canvas.drawArc(mArcRect, 270, 360 * progress / 100, false, mPaint);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int lineWidth = 4 * (outLineWidth + progressLineWidth);
int width = getMeasuredWidth();
int height = getMeasuredHeight();
int size = (width > height ? width : height) + lineWidth;
setMeasuredDimension(size, size);
}
@Override
protected void drawableStateChanged() {
super.drawableStateChanged();
validateCircleColor();
}
/**
* 进度更新task。
*/
private Runnable progressChangeTask = new Runnable() {
@Override
public void run() {
removeCallbacks(this);
switch (mProgressType) {
case COUNT:
progress += 1;
break;
}
if (progress >= 0 && progress <= 100) {
if (mCountdownProgressListener != null)
mCountdownProgressListener.onProgress(listenerWhat, progress);
invalidate();
postDelayed(progressChangeTask, timeMillis / 100);
} else
progress = validateProgress(progress);
}
};
/**
* 进度条类型。
*/
public enum ProgressType {
/**
* 顺数进度条,从0-100;
*/
COUNT,
}
/**
* 进度监听。
*/
public interface OnCountdownProgressListener {
/**
* 进度通知。
*
* @param progress 进度值。
*/
void onProgress(int what, int progress);
}
}
attrs.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 欢迎页跳过按钮样式 -->
<declare-styleable name="CircleTextProgressbar">
<attr name="in_circle_color" format="color" />
<attr name="cenerTextSie" format="dimension"></attr>
<attr name="secondsTextSize" format="dimension"></attr>
<attr name="secondsText" format="string"></attr>
</declare-styleable>
</resources>
StartPageActivity.java:
package com.demo.startpageskiptimerdemo.activity;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import com.bumptech.glide.Glide;
import com.bumptech.glide.signature.StringSignature;
import com.demo.startpageskiptimerdemo.R;
import com.demo.startpageskiptimerdemo.widget.CircleTextProgressbar;
import java.util.Timer;
import java.util.TimerTask;
/**
* 启动页面
*
* @author chenke
* @time 2017/12/7 10:13
* @mail ch_chenke@163.com
*/
public class StartPageActivity extends AppCompatActivity implements View.OnTouchListener {
private final static String TAG = "StartPageActivity";
CircleTextProgressbar mTvSkip;
ImageView mStartPageImag;
LinearLayout skipLayout;
RelativeLayout welBgRlay;
// 倒计时timer
private Timer timer;
// 启动页图片地址
private String imgUrl = "https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=1851053687,4000575540&fm=27&gp=0.jpg";
private int waitTime = 5;// 时长5秒
Handler mHandler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message message) {
switch (message.what) {
case 1:
gotoHomeActivity();
break;
}
return false;
}
});
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start_page);
init();
}
private void init() {
mTvSkip = (CircleTextProgressbar) findViewById(R.id.tv_red_skip);
mStartPageImag = (ImageView) findViewById(R.id.star_page_icon);
skipLayout = (LinearLayout) findViewById(R.id.skip_layout);
welBgRlay = (RelativeLayout) findViewById(R.id.start_goadvert_lay);
mTvSkip.setOutLineColor(Color.TRANSPARENT);
mTvSkip.setInCircleColor(Color.parseColor("#AAC6C6C6"));
mTvSkip.setProgressColor(Color.WHITE);
mTvSkip.setProgressLineWidth(5);
// 开始时计
mCountDowntimer();
mTvSkip.reStart();
// 设置skipLayout浮在整个页面的最上层
welBgRlay.bringChildToFront(skipLayout);
mTvSkip.setOnTouchListener(this);
mStartPageImag.setOnTouchListener(this);
// 加载图片
if (!TextUtils.isEmpty(imgUrl)) {
Glide.with(this).load(imgUrl).signature(new StringSignature("1")).into
(mStartPageImag);
}
}
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
if (null != timer) {
timer.cancel();
timer = null;
}
switch (view.getId()) {
case R.id.star_page_icon: // 广告
//********** 跳转网页 (进入启动页面广告详情)***********
break;
case R.id.tv_red_skip: // 跳转计时view
if (null != timer) {
timer.cancel();
timer = null;
}
mHandler.sendEmptyMessage(1);
return true;
}
}
return false;
}
/**
* 进入首页
*/
public void gotoHomeActivity() {
Intent homeIntent = new Intent();
homeIntent.setClass(this, MainActivity.class);
startActivity(homeIntent);
finish();
}
/**
* 计时器
*/
private void mCountDowntimer() {
timer = new Timer();
mTvSkip.setSeconds(waitTime + "s");
timer.schedule(task, 1000, 1000);
}
/**
* 计时器线程
*/
TimerTask task = new TimerTask() {
@Override
public void run() {
runOnUiThread(new Runnable() { // UI thread
@Override
public void run() {
waitTime--;
mTvSkip.setSeconds(waitTime + "s");
if (waitTime <= 0) {
if (null != timer) {
timer.cancel();
timer = null;
}
mHandler.sendEmptyMessage(1);
}
}
});
}
};
}
activity_start_page.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/start_goadvert_lay"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:
<ImageView
android:id="@+id/star_page_icon"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:scaleType="fitXY" />
<LinearLayout
android:id="@+id/skip_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:gravity="center"
android:orientation="horizontal"
android:paddingRight="10dp"
android:paddingTop="10dp"
android:visibility="visible">
<com.demo.startpageskiptimerdemo.widget.CircleTextProgressbar
android:id="@+id/tv_red_skip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="跳过"
android:textColor="@android:color/white"
android:textSize="10dp" />
</LinearLayout>
</RelativeLayout>
styles.xml:
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<!--启动页面跳过按钮自定义style-->
<style name="CustomProgressStyle" parent="@android:style/Widget.ProgressBar.Large">
<item name="android:minWidth">35dip</item>
<item name="android:maxWidth">35dip</item>
<item name="android:minHeight">35dip</item>
<item name="android:maxHeight">35dip</item>
</style>
</resources>
AndroidManifest.xml中添加请求网络权限:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
build.gradle中dependencies添加:
// 异步加载图片
compile 'com.github.bumptech.glide:glide:3.7.0'
compile 'com.android.support:support-v4:23.3.0'