Android自定义控件之3D上下翻页效果的倒计时控件

这是一个自定义的倒计时控件,具有3D上下翻页翻转效果。最近项目中需要做一个倒计时控件,需要和iOS端的效果保持一样。大致效果是这样的,如下图所示:

Android自定义控件之3D上下翻页效果的倒计时控件_第1张图片

由于暂时还不会怎么样制作gif动态图,所以想看具体效果的,可以在下面的源码中下载运行查看。

废话不说了,开干吧。那么是怎么实现呢?我们首先得找到3D翻页的效果,这个效果我是参考的一个github项目,https://github.com/emilsjolander/android-FlipView。

其次,倒计时的逻辑,这个不难,最后是自定义的View了。

下面是动画的效果


1.动画的效果

(1).这里的动画效果是由Scroller类来实现的。

public void startScroll (int startX, int startY, int dx, int dy, int duration)
(2).翻页效果
           主要分为三部分

           |___绘制控件翻转页面的上半部分:

 canvas.clipRect(mTopRect);

           |___绘制控件翻转页面的下半部分: 

canvas.clipRect(mBottomRect);

           |___绘制控件中间的翻页部分:这里利用的是camera类的方法,

camera.rotateX()//看意思就明白表示沿X轴翻转,这是翻转效果的核心方法。
camera.clipRect(mTopRect,mBottom) //根据当前翻转的度数(0~180度),决定画布裁剪部分。
camera.getMatrix(mMatrix) //设置matrix矩阵的值,对中间页进行变形,达到翻页的视觉效果。
//然后通过矩阵变换,绘制视图和控件
mMatrix.preScale(0.25f, 0.25f);
mMatrix.postScale(4.0f, 4.0f);
mMatrix.preTranslate(-getWidth() / 2, -getHeight() / 2);
mMatrix.postTranslate(getWidth() / 2, getHeight() / 2);
canvas.concat(mMatrix) 
drawChild();
其中,控件中间的黑线,也是自定义的一个TextView,因为原生的TextView没有设置文字上画黑线的方法,有画线的方法,但是是跟着字体的颜色变化的,所以不符合需求,需要自定义一下,设置绘画的颜色。

不说了,上代码

clock_view_activity.xml



    
    

    
attrs.xml 自定义的属性



    
        
        
        
        
        
        
        
        
        
        
        
        
    
ids.xml 因为用到的是动态布局,为了能找到控件,得为每个控件设置一个id



     
     
     
     
time_bg.xml 控件的样式




    

    
    
    
    

clock_view_bg.xml 控件外框的样式



    

    
    

    
    
    

FlipClockView.java
package com.example.timeticker;

import android.content.Context;
import android.graphics.Camera;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;
import android.widget.Scroller;
import android.widget.TextView;

/**
 日历3D翻转效果
 */
public class FlipClockView extends FrameLayout {

	private TextView mVisibleTextView;// 可见的
	private TextView mInvisibleTextView;// 不可见

	private int layoutWidth;
	private int layoutHeight;
	private Scroller mScroller;

	private Camera mCamera = new Camera();
	private Matrix mMatrix = new Matrix();
	private Rect mTopRect = new Rect();
	private Rect mBottomRect = new Rect();
	private boolean isUp2Down = true;
	private Paint mShinePaint = new Paint();
	private Paint mShadePaint = new Paint();
	private boolean isFlipping = false;

	public FlipClockView(Context context) {
		this(context, null);
	}

	public FlipClockView(Context context, AttributeSet attrs) {
		super(context, attrs, 0);
		init(context);
	}

	public FlipClockView(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
	}

	public void init(Context context) {
		mScroller = new Scroller(context, new DecelerateInterpolator());// 减速 // 动画插入器

		mInvisibleTextView = new MyTextView(context);
		mInvisibleTextView.setText("0");
		mInvisibleTextView.setGravity(Gravity.CENTER);
		mInvisibleTextView.setIncludeFontPadding(false);
		addView(mInvisibleTextView);

		mVisibleTextView = new MyTextView(context);
		mVisibleTextView.setText("0");
		mVisibleTextView.setGravity(Gravity.CENTER);
		mVisibleTextView.setIncludeFontPadding(false);
		addView(mVisibleTextView);

		mShadePaint.setColor(Color.BLACK);
		mShadePaint.setStyle(Paint.Style.FILL);
		mShinePaint.setColor(Color.WHITE);
		mShinePaint.setStyle(Paint.Style.FILL);
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		layoutWidth = MeasureSpec.getSize(widthMeasureSpec);
		layoutHeight = MeasureSpec.getSize(heightMeasureSpec);

		setMeasuredDimension(layoutWidth, layoutHeight);
	}

	@Override
	protected void onLayout(boolean changed, int left, int top, int right,
			int bottom) {
		super.onLayout(changed, left, top, right, bottom);
		int count = getChildCount();
		//将两个textView放置进去
		for (int i = 0; i < count; i++) {
			View child = getChildAt(i);
			child.layout(0, 0, layoutWidth, layoutHeight);
		}

		mTopRect.top = 0;
		mTopRect.left = 0;
		mTopRect.right = getWidth();
		mTopRect.bottom = getHeight() / 2;

		mBottomRect.top = getHeight() / 2;
		mBottomRect.left = 0;
		mBottomRect.right = getWidth();
		mBottomRect.bottom = getHeight();
	}

	@Override
	protected void dispatchDraw(Canvas canvas) {
		super.dispatchDraw(canvas);
		if (!mScroller.isFinished() && mScroller.computeScrollOffset()) {
			drawTopHalf(canvas);
			drawBottomHalf(canvas);
			drawFlipHalf(canvas);
			postInvalidate();
		} else {
			if (isFlipping) {
				showViews(canvas);
			}

			if (mScroller.isFinished() && !mScroller.computeScrollOffset()) {
				isFlipping = false;
			}
		}
	}

	/**
	 * 显示需要显示的数字
	 * 
	 * @param canvas
	 */
	private void showViews(Canvas canvas) {
		String current = mVisibleTextView.getText().toString();
		String past = mInvisibleTextView.getText().toString();
		// Log.e("需要显示的数字--->",current+ "%%    "+past);

		mVisibleTextView.setText(past);
		mInvisibleTextView.setText(current);

		// 防止切换抖动
		drawChild(canvas, mVisibleTextView, 0);
	}

	/** 画下半部分 */
	private void drawBottomHalf(Canvas canvas) {
		canvas.save();

		canvas.clipRect(mBottomRect);
		View drawView = !isUp2Down ? mInvisibleTextView : mVisibleTextView;
		drawChild(canvas, drawView, 0);

		canvas.restore();
	}

	/** 画上半部分 */
	private void drawTopHalf(Canvas canvas) {
		canvas.save();

		canvas.clipRect(mTopRect);
		View drawView = !isUp2Down ? mVisibleTextView : mInvisibleTextView;
		drawChild(canvas, drawView, 0);

		canvas.restore();

	}

	/** 画翻页部分 */
	private void drawFlipHalf(Canvas canvas) {
		canvas.save();
		mCamera.save();

		View view = null;
		float deg = getDeg();
		if (deg > 90) {
			canvas.clipRect(!isUp2Down ? mTopRect : mBottomRect);
			mCamera.rotateX(!isUp2Down ? deg - 180 : -(deg - 180));
			view = mInvisibleTextView;
		} else {
			canvas.clipRect(!isUp2Down ? mBottomRect : mTopRect);
			mCamera.rotateX(!isUp2Down ? deg : -deg);
			view = mVisibleTextView;
		}

		mCamera.getMatrix(mMatrix);
		positionMatrix();
		canvas.concat(mMatrix);

		if (view != null) {
			drawChild(canvas, view, 0);
		}

		drawFlippingShadeShine(canvas);

		mCamera.restore();
		canvas.restore();
	}

	private float getDeg() {
		return mScroller.getCurrY() * 1.0f / layoutHeight * 180;
	}

	/** 绘制翻页时的阳面和阴面 */
	private void drawFlippingShadeShine(Canvas canvas) {
		final float degreesFlipped = getDeg();
		// Log.d(TAG, "deg: " + degreesFlipped);
		if (degreesFlipped < 90) {
			final int alpha = getAlpha(degreesFlipped);
			// Log.d(TAG, "小于90度时的透明度-------------------> " + alpha);
			mShinePaint.setAlpha(alpha);
			mShadePaint.setAlpha(alpha);
			canvas.drawRect(!isUp2Down ? mBottomRect : mTopRect, !isUp2Down ? mShinePaint
					: mShadePaint);
		} else {
			final int alpha = getAlpha(Math.abs(degreesFlipped - 180));
			// Log.d(TAG, "大于90度时的透明度-------------> " + alpha);
			mShadePaint.setAlpha(alpha);
			mShinePaint.setAlpha(alpha);
			canvas.drawRect(!isUp2Down ? mTopRect : mBottomRect, !isUp2Down ? mShadePaint
					: mShinePaint);
		}
	}

	private int getAlpha(float degreesFlipped) {
		return (int) ((degreesFlipped / 90f) * 100);
	}

	private void positionMatrix() {
		mMatrix.preScale(0.25f, 0.25f);
		mMatrix.postScale(4.0f, 4.0f);
		mMatrix.preTranslate(-getWidth() / 2, -getHeight() / 2);
		mMatrix.postTranslate(getWidth() / 2, getHeight() / 2);
	}

	/** 初始化隐藏textView显示的值 */
	private void initTextView() {
		int visibleValue = Integer.parseInt(mVisibleTextView.getText()
				.toString());
	//	int invisibleValue = isUp2Down ? visibleValue - 1 : visibleValue + 1;//这里控制是 + 还是 -
		int invisibleValue = visibleValue - 1;
		if (invisibleValue < 10) {
			mInvisibleTextView.setText("0" + invisibleValue);
		} else {
			mInvisibleTextView.setText("" + invisibleValue);
		}
	}

	/**
	 *
	 * @param isUp2Down
	 *     方向标识 true: 从上往下翻  , false: 从下往上翻
	 */
	public void setFlipDirection(boolean isUp2Down) {
	    this.isUp2Down = isUp2Down;
	}
	
	public void smoothFlip() {
		//Log.e(TAG, "翻动 ");
		initTextView();
		isFlipping = true;

		mScroller.startScroll(0, 0, 0, layoutHeight, 700);
		postInvalidate();
	}

	public TextView getmVisibleTextView() {
		return mVisibleTextView;
	}

	public TextView getmInvisibleTextView() {
		return mInvisibleTextView;
	}

	public boolean isFlipping() {
		return isFlipping && !mScroller.isFinished()
				&& mScroller.computeScrollOffset();
	}

	/**
	 * 获取当前View值
	 * 
	 * @return
	 */
	public int getCurrentValue() {
		return Integer.parseInt(mVisibleTextView.getText().toString());
	}

	/**
	 * 设置view的时间值
	 * @param textTime
	 */
	public void setClockTime(String textTime) {
		mVisibleTextView.setText(textTime);
	}

	/**
	 * 设置时间数字的背景
	 * @param drawable
	 */
	public void setClockBackground(Drawable drawable) {
		mVisibleTextView.setBackground(drawable);
		mInvisibleTextView.setBackground(drawable);
	}

	/**
	 * 设置时间数字的颜色
	 * @param color
	 */
	public void setClockTextColor(int color) {
		mVisibleTextView.setTextColor(color);
		mInvisibleTextView.setTextColor(color);
	}

	/**
	 * 设置时间数字的大小
	 * @param size
	 */
	public void setClockTextSize(float size){
		mVisibleTextView.setTextSize(size);
		mInvisibleTextView.setTextSize(size);
	}

}

MyClockView.java

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.TextView;

public class MyClockView extends RelativeLayout {
	private float dayTextSize, hourTextSize, minTextSize, secTextSize;
	private FlipClockView dayTextView, hourTextView, minTextView, secTextView;
	private TextView dTextView, hTextView, mTextView, sTextView;
	private LayoutParams dayLayoutParams, hourLayoutParams, minLayoutParams,
			secLayoutParams;
	private DownCountTimerListener mDownCountTimerListener;
	private Handler mHandler;
	private Runnable mRunnable;
	private long totalTime = 0;
	private boolean isRunning = true;
    private int screenW;
	private long outNumber=0;//超过的最大计数的时间(秒数)

	public MyClockView(Context context, AttributeSet attrs) {
		super(context, attrs);
		initView(context, attrs);
	}

	public MyClockView(Context context) {
		this(context, null);
	}

	public MyClockView(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		initView(context, attrs);
	}

	public void initView(Context context, AttributeSet attrs) {
		screenW=getScreenWidth(context);
		TypedArray tArray = context.obtainStyledAttributes(attrs,
				R.styleable.MyClock);
		dayTextSize = tArray.getDimension(R.styleable.MyClock_dayTextSize, 26f);
		hourTextSize = tArray.getDimension(R.styleable.MyClock_hourTextSize,
				26f);
		minTextSize = tArray.getDimension(R.styleable.MyClock_minTextSize, 26f);
		secTextSize = tArray.getDimension(R.styleable.MyClock_secTextSize, 26f);
		int dayTextColor = tArray.getColor(R.styleable.MyClock_dayTextColor,
				0xffffff);
		int hourTextColor = tArray.getColor(R.styleable.MyClock_hourTextColor,
				0xffffff);
		int minTextColor = tArray.getColor(R.styleable.MyClock_minTextColor,
				0xffffff);
		int secTextColor = tArray.getColor(R.styleable.MyClock_secTextColor,
				0xffffff);
		Drawable dayTextBg = tArray
				.getDrawable(R.styleable.MyClock_dayTextBackground);
		Drawable hourTextBg = tArray
				.getDrawable(R.styleable.MyClock_hourTextBackground);
		Drawable minTextBg = tArray
				.getDrawable(R.styleable.MyClock_minTextBackground);
		Drawable secTextBg = tArray
				.getDrawable(R.styleable.MyClock_secTextBackground);

		tArray.recycle();

		dayTextView = new FlipClockView(context);
		hourTextView = new FlipClockView(context);
		minTextView = new FlipClockView(context);
		secTextView = new FlipClockView(context);
		
		dayTextView.setId(R.id.dayTextView);
		hourTextView.setId(R.id.hourTextView);
		minTextView.setId(R.id.minTextView);
		secTextView.setId(R.id.secTextView);
		
		dTextView = new TextView(context);
		hTextView = new TextView(context);
		mTextView = new TextView(context);
		sTextView = new TextView(context);
		dTextView.setText("DAYS");
		hTextView.setText("HOURS");
		mTextView.setText("MINUTES");
		sTextView.setText("SECONDS");
		dTextView.setTextColor(Color.parseColor("#ffffff"));
		hTextView.setTextColor(Color.parseColor("#ffffff"));
		mTextView.setTextColor(Color.parseColor("#ffffff"));
		sTextView.setTextColor(Color.parseColor("#ffffff"));
		dTextView.setTextSize(10f);
		hTextView.setTextSize(10f);
		mTextView.setTextSize(10f);
		sTextView.setTextSize(10f);

		dayTextView.setClockBackground(dayTextBg);
		dayTextView.setClockTextSize(dayTextSize);
		dayTextView.setClockTextColor(dayTextColor);
		hourTextView.setClockBackground(hourTextBg);
		hourTextView.setClockTextSize(dayTextSize);
		hourTextView.setClockTextColor(hourTextColor);
		minTextView.setClockBackground(minTextBg);
		minTextView.setClockTextSize(dayTextSize);
		minTextView.setClockTextColor(minTextColor);
		secTextView.setClockBackground(secTextBg);
		secTextView.setClockTextSize(dayTextSize);
		secTextView.setClockTextColor(secTextColor);
		//secTextView.setFlipDirection(false);

		//Log.e("---->","屏幕的宽"+screenW);
        int viewWidth=(int)(screenW*0.14);
		int viewMargin=(int)(screenW*0.05);
		dTextView.setWidth(viewWidth);
		dTextView.setGravity(Gravity.CENTER);
		hTextView.setWidth(viewWidth);
		hTextView.setGravity(Gravity.CENTER);
		mTextView.setWidth(viewWidth);
		mTextView.setGravity(Gravity.CENTER);
		sTextView.setWidth(viewWidth);
		sTextView.setGravity(Gravity.CENTER);

		dayLayoutParams = new LayoutParams(viewWidth,
                viewWidth);
		dayLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT, TRUE);
		dayLayoutParams.setMargins(0, 60, 0, 0);
		addView(dayTextView, dayLayoutParams);
		LayoutParams dLayoutParams = new LayoutParams(
				ViewGroup.LayoutParams.WRAP_CONTENT,
				ViewGroup.LayoutParams.WRAP_CONTENT);
		dLayoutParams.addRule(RelativeLayout.BELOW, R.id.dayTextView);
		dLayoutParams.addRule(RelativeLayout.ALIGN_LEFT, R.id.dayTextView);
		dLayoutParams.setMargins(0, 5, 0, 60);
		addView(dTextView, dLayoutParams);

		hourLayoutParams = new LayoutParams(viewWidth,
                viewWidth);
		hourLayoutParams.addRule(RelativeLayout.RIGHT_OF, R.id.dayTextView);
		hourLayoutParams.setMargins(viewMargin, 60, viewMargin, 0);
		addView(hourTextView, hourLayoutParams);
		LayoutParams hLayoutParams = new LayoutParams(
				ViewGroup.LayoutParams.WRAP_CONTENT,
				ViewGroup.LayoutParams.WRAP_CONTENT);
		hLayoutParams.addRule(RelativeLayout.ALIGN_LEFT, R.id.hourTextView);
		hLayoutParams.addRule(RelativeLayout.BELOW, R.id.hourTextView);
		hLayoutParams.setMargins(0, 5, 0, 0);
		addView(hTextView, hLayoutParams);

		minLayoutParams = new LayoutParams(viewWidth,
				viewWidth);
		minLayoutParams.setMargins(0, 60, 0, 0);
		minLayoutParams.addRule(RelativeLayout.RIGHT_OF, R.id.hourTextView);
		addView(minTextView, minLayoutParams);
		LayoutParams mLayoutParams = new LayoutParams(
				ViewGroup.LayoutParams.WRAP_CONTENT,
				ViewGroup.LayoutParams.WRAP_CONTENT);
		mLayoutParams.addRule(RelativeLayout.ALIGN_LEFT, R.id.minTextView);
		mLayoutParams.addRule(RelativeLayout.BELOW, R.id.minTextView);
		mLayoutParams.setMargins(0, 5, 0, 0);
		addView(mTextView, mLayoutParams);

		secLayoutParams = new LayoutParams(viewWidth,
                viewWidth);
		secLayoutParams.addRule(RelativeLayout.RIGHT_OF, R.id.minTextView);
		secLayoutParams.setMargins(viewMargin, 60, 0, 0);
		addView(secTextView, secLayoutParams);
		LayoutParams sLayoutParams = new LayoutParams(
				ViewGroup.LayoutParams.WRAP_CONTENT,
				ViewGroup.LayoutParams.WRAP_CONTENT);
		sLayoutParams.addRule(RelativeLayout.ALIGN_LEFT, R.id.secTextView);
		sLayoutParams.addRule(RelativeLayout.BELOW, R.id.secTextView);
		sLayoutParams.setMargins(0, 5, 0, 0);
		addView(sTextView, sLayoutParams);

		dayTextView.setClockTime("00");
		hourTextView.setClockTime("00");
		minTextView.setClockTime("00");
		secTextView.setClockTime("00");

		mHandler = new Handler();
	}

	public interface DownCountTimerListener {

		void stopDownCountTimer();

	}

	/**
	 * 暂停计时
	 */
	public void pauseDownCountTimer() {
		if (mRunnable != null) {
			mHandler.removeCallbacks(mRunnable);
			dayTextView.setClockTime("00");
			hourTextView.setClockTime("00");
			minTextView.setClockTime("00");
			secTextView.setClockTime("00");
		//	Log.e("暂停计时", "-=-=-=-=-=");
		}
	}

	public void setDownCountTimerListener(DownCountTimerListener listener) {
		this.mDownCountTimerListener = listener;
	}

	/**
	 * 获取设置倒计时的总时间
	 * @return
	 */
	public long getDownCountTime() {
		return totalTime;
	}

	/**
	 * 设定需要倒计时的总共时间
	 *
	 * @param totalDownCountTimes
	 */
	public void setDownCountTime(long totalDownCountTimes) {
		this.totalTime = totalDownCountTimes;
		pauseDownCountTimer();
	}

	/**
	 * 设定倒计时的时间开始时间和结束时间
	 *
	 * @param startTime
	 * @param endTime
	 */
	public void setDownCountTime(long startTime, long endTime) {
		this.totalTime = endTime - startTime;
		pauseDownCountTimer();
	}

	/**
	 * 开始倒计时
	 */
	public void startDownCountTimer() {
		isRunning=true;
		setTime2Text(getDownCountTime());
		mRunnable = new Runnable() {

			@Override
			public void run() {
				int i=secTextView.getCurrentValue();
			   // Log.e("sec时间----->",i + "");
				outNumber--;
				if (outNumber<=0) {
					if (i > 0) {
						secTextView.smoothFlip();
					} else {
						int j = getClockMinValue();
						j--;
						if (j >= 0 && i == 0) {
							//Log.e("分钟时间----->", j + "");
							minTextView.smoothFlip();
							secTextView.setClockTime("60");
							secTextView.smoothFlip();
						} else {
							int k = getClockHourValue();
							k--;

							if (k >= 0 && j < 0 && i == 0) {
								hourTextView.smoothFlip();
								minTextView.setClockTime("60");
								minTextView.smoothFlip();
								secTextView.setClockTime("60");
								secTextView.smoothFlip();
							} else {
								int d = getClockDayValue();
								d--;
								if (d < 0) {
									//	Log.e("时间结束----->", j + "    " + i);
									isRunning = false;
									if (null != mDownCountTimerListener) {
										mDownCountTimerListener.stopDownCountTimer();
									}
								} else {
									Log.e("day----->", d + "    ");
									secTextView.setClockTime("60");
									minTextView.setClockTime("60");
									hourTextView.setClockTime("24");
									d++;
									dayTextView.setClockTime("" + d);
									secTextView.smoothFlip();
									minTextView.smoothFlip();
									hourTextView.smoothFlip();
									dayTextView.smoothFlip();
								}
							}
						}
					}
				}
				if (isRunning) {
					mHandler.postDelayed(this, 1000);
				} else {
					mHandler.removeCallbacks(this);
				}
			}
		};
		mHandler.postDelayed(mRunnable, 1000);

	}
	/**
	 * 获取倒计时剩余的时间,数组的4个元素分别代表剩余的天、时、分、秒
	 * @return
	 */
	public String[] getClockRestTime(){
		String[] restTime=new String[4];
		restTime[0]=String.valueOf(getClockDayValue());
		restTime[1]=String.valueOf(getClockHourValue());
		restTime[2]=String.valueOf(getClockMinValue());
		restTime[3]=String.valueOf(getClockSecValue());
		return restTime;
	}

	public int getScreenWidth(Context mContext) {
       return mContext.getResources().getDisplayMetrics().widthPixels;
	}

	/**
	 * 根据给定的时间转换为 天、时、分
	 *
	 * @param startTime
	 */
	private void setTime2Text(long startTime) {

		int ss = 1000;
		int mi = ss * 60;
		int hh = mi * 60;
		int dd = hh * 24;

		long day = startTime / dd;
		long hour = (startTime - day * dd) / hh;
		long minute = (startTime - day * dd - hour * hh) / mi;
		long second = (startTime - day * dd - hour * hh - minute * mi) / ss;

		String strDay = day < 10 ? "0" + day : "" + day; // 天
		String strHour = hour < 10 ? "0" + hour : "" + hour;// 小时
		String strMinute = minute < 10 ? "0" + minute : "" + minute;// 分钟
		String strSecond = second < 10 ? "0" + second : "" + second;// 秒

		Log.e("时间----》", strDay+"  "+strHour +"  "+strMinute+"  "+strSecond);
		if (Integer.parseInt(strDay) >= 100) {
			dayTextView.setClockTime("99");
			hourTextView.setClockTime("23");
			minTextView.setClockTime("59");
			secTextView.getmInvisibleTextView().setText("59");
			secTextView.getmVisibleTextView().setText("59");
			outNumber=((startTime)-1000L*60L*60L*24L*100L)/1000L;
		//	Log.e("多余的时间----》",outNumber+"");
		} else {
			dayTextView.setClockTime(strDay);
			hourTextView.setClockTime(strHour);
			minTextView.setClockTime(strMinute);
			secTextView.getmVisibleTextView().setText(strSecond);
			secTextView.getmInvisibleTextView().setText(strSecond);
			outNumber=0;
		}
	}

	public int getClockDayValue() {
		return dayTextView.getCurrentValue();
	}

	public int getClockHourValue() {
		return hourTextView.getCurrentValue();
	}

	public int getClockMinValue() {
		return minTextView.getCurrentValue();
	}

	public int getClockSecValue(){
		return secTextView.getCurrentValue();
	}
	
}
MyTextView.java
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.widget.TextView;

public class MyTextView extends TextView {

	Paint mPaint;
	
	public MyTextView(Context context, AttributeSet attrs) {
		super(context, attrs);
		initPaint();
	}

	public MyTextView(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		initPaint();
	}

	public MyTextView(Context context) {
		this(context, null);
		initPaint();
	}
	
	private void initPaint() {
		mPaint=new Paint(Paint.ANTI_ALIAS_FLAG);
		mPaint.setStyle(Paint.Style.FILL);
		mPaint.setColor(Color.BLACK);
	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		canvas.drawRect(0,getMeasuredHeight()/2-1,getMeasuredWidth(),getMeasuredHeight()/2+1, mPaint);
		
	}

}

MainActivity.java
MainActivity.java
package com.example.timeticker;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity implements View.OnClickListener, MyClockView.DownCountTimerListener {
    Button mBtn;
    private MyClockView myClockView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.clock_view_activity);
        mBtn = (Button) findViewById(R.id.button1);
        mBtn.setOnClickListener(this);
        myClockView = (MyClockView) findViewById(R.id.clockView);
        myClockView.setDownCountTimerListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.button1:
                myClockView.setDownCountTime(1000L * 60L + 1000L * 12L);
                myClockView.startDownCountTimer();

                break;

            default:
                break;
        }
    }

    @Override
    public void stopDownCountTimer() {
        Toast.makeText(this,"结束了",Toast.LENGTH_SHORT).show();
    }
}


PS.上面的效果,可能在某些手机上翻转时的效果会出现闪烁的现象,是因为手机的硬件加速功能开启了的原因,为此。你需要在初始化view的时候关闭硬件加速。

myClockView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

还有,有些手机上适配效果不好,可以在布局文件里添加padding的属性,保证控件都在所包裹的父布局中。

好了,上面应该比较清楚了,有不清楚的,可以留言,欢迎探讨。
喜欢本文的,点个赞。


点击下载Demo

你可能感兴趣的:(Android)