Android自定义控件之3D上下翻页效果的倒计时控件
這是一個自定義的倒計時控件,具有3D上下翻頁翻轉(zhuǎn)效果。最近項(xiàng)目中需要做一個倒計時控件,需要和iOS端的效果保持一樣。大致效果是這樣的,如下圖所示:
由于暫時還不會怎么樣制作gif動態(tài)圖,所以想看具體效果的,可以在下面的源碼中下載運(yùn)行查看。
廢話不說了,開干吧。那么是怎么實(shí)現(xiàn)呢?我們首先得找到3D翻頁的效果,這個效果我是參考的一個github項(xiàng)目,https://github.com/emilsjolander/android-FlipView。
其次,倒計時的邏輯,這個不難,最后是自定義的View了。
下面是動畫的效果
1.動畫的效果
(1).這里的動畫效果是由Scroller類來實(shí)現(xiàn)的。
public void startScroll (int startX, int startY, int dx, int dy, int duration)(2).翻頁效果? ? ? ? ? ?主要分為三部分
? ? ? ? ? ?|___繪制控件翻轉(zhuǎn)頁面的上半部分:
canvas.clipRect(mTopRect);? ? ? ? ? ?|___繪制控件翻轉(zhuǎn)頁面的下半部分:?
canvas.clipRect(mBottomRect);? ? ? ? ? ?|___繪制控件中間的翻頁部分:這里利用的是camera類的方法,
camera.rotateX()//看意思就明白表示沿X軸翻轉(zhuǎn),這是翻轉(zhuǎn)效果的核心方法。 camera.clipRect(mTopRect,mBottom) //根據(jù)當(dāng)前翻轉(zhuǎn)的度數(shù)(0~180度),決定畫布裁剪部分。 camera.getMatrix(mMatrix) //設(shè)置matrix矩陣的值,對中間頁進(jìn)行變形,達(dá)到翻頁的視覺效果。 //然后通過矩陣變換,繪制視圖和控件 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,因?yàn)樵腡extView沒有設(shè)置文字上畫黑線的方法,有畫線的方法,但是是跟著字體的顏色變化的,所以不符合需求,需要自定義一下,設(shè)置繪畫的顏色。不說了,上代碼
clock_view_activity.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:customs="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#3B96FD"android:gravity="center_horizontal"android:orientation="vertical" ><com.example.timeticker.MyClockViewandroid:id="@+id/clockView"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="14dp"android:background="@mipmap/tcd_timer_bg"customs:dayTextBackground="@drawable/time_bg"customs:dayTextColor="#ffffff"customs:hourTextBackground="@drawable/time_bg"customs:hourTextColor="#ffffff"customs:minTextBackground="@drawable/time_bg"customs:minTextColor="#ffffff"customs:secTextBackground="@drawable/time_bg"customs:secTextColor="#ffffff" ></com.example.timeticker.MyClockView><Buttonandroid:id="@+id/button1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="倒計時" /></LinearLayout> attrs.xml 自定義的屬性<?xml version="1.0" encoding="utf-8"?> <resources><declare-styleable name="MyClock"><attr name="dayTextSize" format="dimension" /><attr name="hourTextSize" format="dimension" /><attr name="minTextSize" format="dimension" /><attr name="secTextSize" format="dimension" /><attr name="dayTextColor" format="color" /><attr name="hourTextColor" format="color" /><attr name="minTextColor" format="color" /><attr name="secTextColor" format="color" /><attr name="dayTextBackground" format="reference|color" /><attr name="hourTextBackground" format="reference|color" /><attr name="minTextBackground" format="reference|color" /><attr name="secTextBackground" format="reference|color" /></declare-styleable> </resources> ids.xml 因?yàn)橛玫降氖莿討B(tài)布局,為了能找到控件,得為每個控件設(shè)置一個id <?xml version="1.0" encoding="utf-8"?> <resources><item name="dayTextView" type="id" /><item name="hourTextView" type="id" /><item name="minTextView" type="id" /><item name="secTextView" type="id" /> </resources> time_bg.xml 控件的樣式 <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" ><corners android:radius="3dp" /><!-- 實(shí)心 即填充顏色 --><solid android:color="#0B315C" /><!-- 按鈕文字和邊緣距離(內(nèi)邊距) --><paddingandroid:bottom="3dp"android:left="6dp"android:right="6dp"android:top="3dp" /></shape> clock_view_bg.xml 控件外框的樣式
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" ><corners android:radius="10dp" /><!-- 實(shí)心 即填充顏色 --><solid android:color="#00000000" /><strokeandroid:width="2dp"android:color="#2F80E9" /><!-- 按鈕文字和邊緣距離(內(nèi)邊距) --><paddingandroid:bottom="5dp"android:left="5dp"android:right="5dp"android:top="5dp" /></shape> 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翻轉(zhuǎn)效果*/ 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);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);layoutWidth = MeasureSpec.getSize(widthMeasureSpec);layoutHeight = MeasureSpec.getSize(heightMeasureSpec);setMeasuredDimension(layoutWidth, layoutHeight);}@Overrideprotected void onLayout(boolean changed, int left, int top, int right,int bottom) {super.onLayout(changed, left, top, right, bottom);int count = getChildCount();//將兩個textView放置進(jìn)去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();}@Overrideprotected 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;}}}/*** 顯示需要顯示的數(shù)字* * @param canvas*/private void showViews(Canvas canvas) {String current = mVisibleTextView.getText().toString();String past = mInvisibleTextView.getText().toString();// Log.e("需要顯示的數(shù)字--->",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* 方向標(biāo)識 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();}/*** 獲取當(dāng)前View值* * @return*/public int getCurrentValue() {return Integer.parseInt(mVisibleTextView.getText().toString());}/*** 設(shè)置view的時間值* @param textTime*/public void setClockTime(String textTime) {mVisibleTextView.setText(textTime);}/*** 設(shè)置時間數(shù)字的背景* @param drawable*/public void setClockBackground(Drawable drawable) {mVisibleTextView.setBackground(drawable);mInvisibleTextView.setBackground(drawable);}/*** 設(shè)置時間數(shù)字的顏色* @param color*/public void setClockTextColor(int color) {mVisibleTextView.setTextColor(color);mInvisibleTextView.setTextColor(color);}/*** 設(shè)置時間數(shù)字的大小* @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;//超過的最大計數(shù)的時間(秒數(shù))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;}/*** 獲取設(shè)置倒計時的總時間* @return*/public long getDownCountTime() {return totalTime;}/*** 設(shè)定需要倒計時的總共時間** @param totalDownCountTimes*/public void setDownCountTime(long totalDownCountTimes) {this.totalTime = totalDownCountTimes;pauseDownCountTimer();}/*** 設(shè)定倒計時的時間開始時間和結(jié)束時間** @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() {@Overridepublic 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("時間結(jié)束----->", 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);}/*** 獲取倒計時剩余的時間,數(shù)組的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;}/*** 根據(jù)給定的時間轉(zhuǎn)換為 天、時、分** @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.javaimport 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);}@Overrideprotected 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;@Overrideprotected 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);}@Overridepublic void onClick(View view) {switch (view.getId()) {case R.id.button1:myClockView.setDownCountTime(1000L * 60L + 1000L * 12L);myClockView.startDownCountTimer();break;default:break;}}@Overridepublic void stopDownCountTimer() {Toast.makeText(this,"結(jié)束了",Toast.LENGTH_SHORT).show();} }
PS.上面的效果,可能在某些手機(jī)上翻轉(zhuǎn)時的效果會出現(xiàn)閃爍的現(xiàn)象,是因?yàn)槭謾C(jī)的硬件加速功能開啟了的原因,為此。你需要在初始化view的時候關(guān)閉硬件加速。
還有,有些手機(jī)上適配效果不好,可以在布局文件里添加padding的屬性,保證控件都在所包裹的父布局中。
好了,上面應(yīng)該比較清楚了,有不清楚的,可以留言,歡迎探討。
喜歡本文的,點(diǎn)個贊。
點(diǎn)擊下載Demo
總結(jié)
以上是生活随笔為你收集整理的Android自定义控件之3D上下翻页效果的倒计时控件的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MySQL之介绍
- 下一篇: Android Motion Still