这里有新鲜出炉的精品教程,程序狗速度看过来!
Android是一种基于Linux的自由及开放源代码的操作系统,主要使用于移动设备,如智能手机和平板电脑,由Google公司和开放手机联盟领导及开发。尚未有统一中文名称,中国大陆地区较多人使用“安卓”或“安致”。
这篇文章主要介绍了Android 自定义闪屏页广告倒计时view效果,需要的朋友可以参考下
如今APP越来越多,我们每天所使用的的软件也越来越多,可是在我们不付费的情况下,App制造商如何实现,实现收入甚至是盈利呢?答案就是在我们打开软件所必须经过的地方穿插广告,当然为了顾及用户的感受,一般都会以倒计时的形式展示给用户,用户可以选择跳过.可能是因为自己的强迫症,总想着是怎么做的,自己就尝试了一下,分享给大家的同时,顺便加深自己的理解.效果如图:
1.为了满足产品和设计,先搞几个自定义属性
1)内层背景
2)数字的颜色
3)外层圆环宽度
4)文字大小
5)外层圆环颜色
6)圆的半径
这里,我的外环颜色和文字颜色相同,具体的自定义属性如下:
- <declare-styleable name="AdTimePickView">
- <attr name="mSmallCircleBg" format="color"></attr>
- <attr name="mTextSize1" format="dimension"></attr>
- <attr name="mTextColor1" format="color"></attr>
- <attr name="mProgressWidth" format="dimension"></attr>
- <attr name="mRadius" format="dimension"></attr>
- </declare-styleable>
--------------------------------------------------------------------------------
2.在自定义View的构造方法中读取自定义属性:
- mProgressViewWidth = typedArray.getDimensionPixelSize(R.styleable.AdTimePickView_mProgressWidth, DEFAULT_PROGRESS_WIDTH);
- mRadius = typedArray.getDimensionPixelSize(R.styleable.AdTimePickView_mRadius1, DEFAULT_RADIUS);
- mSmallCircleBg = typedArray.getColor(R.styleable.AdTimePickView_mSmallCircleBg, Color.parseColor(DEFAULT_BG_COLOR));
- mTextSize = typedArray.getDimensionPixelSize(R.styleable.AdTimePickView_mTextSize1, DEFAULT_TEXT_SIZE);
- mTextColor = typedArray.getColor(R.styleable.AdTimePickView_mTextColor1, Color.parseColor(DEFAULT_TEXT_COLOR));
--------------------------------------------------------------------------------
3.重写onMeasure()方法,
根据宽高得出半径,为什么不适用自定义半径呢?因为根据宽高得出的半径才是这个View的内切圆半径,自定义半径只是为了在根据宽高无法得出半径的情况下才使用的.
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- mWidth = getViewSize(widthMeasureSpec, 0);
- mHeight = getViewSize(heightMeasureSpec, 1);
- mRadius = Math.min(mWidth, mHeight) / 2;
- setMeasuredDimension(mWidth, mHeight);
- }
getViewSize方法如下:
- private int getViewSize(int viewMeasureSpec, int type) {
- int viewValue = 0;
- int viewSize = MeasureSpec.getSize(viewMeasureSpec);
- int viewMode = MeasureSpec.getMode(viewMeasureSpec);
- if (MeasureSpec.EXACTLY == viewMode) {
- viewValue = viewSize;
- if (type == 0) {
- mCirCleX = viewSize / 2;
- } else {
- mCircleY = viewSize / 2;
- }
- } else {
- if (type == 0) {
- mCirCleX = mRadius;
- } else {
- mCircleY = mRadius;
- }
- viewValue = 2 * (mRadius + mProgressViewWidth);
- }
- return viewValue;
- }
--------------------------------------------------------------------------------
4.onDraw方法进行绘制
1)绘制内层圆
- canvas.drawCircle(mCirCleX, mCircleY, (float)(mRadius - 1.5 * mProgressViewWidth), mPaint);
2)绘制文字,要计算好文字的位置,保持居中
- Rect textRect = getTextRect(String.valueOf(mAdTIme));
- Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
- int baseLine = (int)(mHeight / 2 + (fontMetrics.descent - fontMetrics.ascent) / 2 - fontMetrics.descent);
- int x = mWidth / 2 - textRect.width() / 2;
- canvas.drawText(String.valueOf(mAdTIme), x, baseLine, mTextPaint);
- //获取绘制内容的Rect
- private Rect getTextRect(String centerContent) {
- Rect rect = new Rect();
- mTextPaint.getTextBounds(centerContent, 0, centerContent.length(), rect);
- return rect;
- }
3)绘制外层不断刷新的圆环
原理:从360度开始每隔一段时间进行圆弧绘制,角度分别为:360,359,1,0,因此需要一个轮询器,不断的去绘制刷新.
绘制圆弧的代码:
- //保存Canvans的状态,因为绘制其他地方时,Canvas坐标系不需要变化
- canvas.save();
- //将坐标系围绕View的中心逆时针旋转90度数,为了从正上方开始绘制
- canvas.rotate( - 90, mCirCleX, mCircleY);
- //计算圆弧的RectF
- RectF rectF = new RectF(mCirCleX - mRadius + mProgressViewWidth, mCirCleX - mRadius + mProgressViewWidth, mCirCleX + mRadius - mProgressViewWidth, mCirCleX + mRadius - mProgressViewWidth);
- //第四个参数表示逆时针还是顺时针绘制
- canvas.drawArc(rectF, 0, -mCurrentAngle, false, mPaint);
- //恢复坐标系
- canvas.restore();
--------------------------------------------------------------------------------
5.刷新的轮询器
1)使用RxAndroid和lambda实现
- //interval操作符:从1开始每隔一段时间发射递增的数
- Observable.interval(1, TIME_DIFF, TimeUnit.MILLISECONDS)
- //map操作符将发射的数据转换成我们需要的数据
- .map(value - >{
- return countAngel - value.intValue();
- })
- //限制发射的数据个数,让其停止,负责会一直发射下去
- .limit(361)
- //接收结果并处理
- .subscribe(action - >{
- if (action % 72 == 0) {
- mAdTIme = action / 72;
- }
- mCurrentAngle = action;
- AdTimePickView.this.postInvalidate();
- });
2)使用线程的方式实现
- new Thread(new Runnable() {
- @Override
- public void run() {
- for (int i = 360; i>=0;i--){
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- if (i % 72 == 0) {
- mAdTIme = i / 72;
- }
- mCurrentAngle = i;
- AdTimePickView.this.postInvalidate();
- }
- }
- }).start();
OK,这样我们的广告倒计时View就完成了,欢迎大家指正.
附:整个自定义View的代码
- public class AdTimePickView extends View {
- private Paint mPaint;
- private Paint mTextPaint;
- //大圆半径
- private int mRadius = 200;
- //内层小圆背景
- private int mSmallCircleBg = Color.parseColor("#66f1679b");
- //小圆外层线条宽度
- private int mProgressViewWidth = 10;
- private float mCurrentAngle;
- private static final int TIME_DIFF = 25;
- //圆心坐标
- private int mCirCleX;
- private int mCircleY;
- //测量之后View的宽高,绘制中心文字时需要用到
- private int mWidth;
- private int mHeight;
- //中心文字的大小与样式
- private int mTextSize;
- private int mTextColor;
- //广告总时间
- private int mAdTIme = 5;
- private Context mContext;
- public AdTimePickView(Context context) {
- this(context, null);
- }
- public AdTimePickView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
- public AdTimePickView(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.AdTimePickView, defStyleAttr, 0);
- mProgressViewWidth = typedArray.getDimensionPixelSize(R.styleable.AdTimePickView_mProgressWidth, 10);
- mRadius = typedArray.getDimensionPixelSize(R.styleable.AdTimePickView_mRadius1, 100);
- mSmallCircleBg = typedArray.getColor(R.styleable.AdTimePickView_mSmallCircleBg, Color.parseColor("#66f1679b"));
- mTextSize = typedArray.getDimensionPixelSize(R.styleable.AdTimePickView_mTextSize1, 20);
- mTextColor = typedArray.getColor(R.styleable.AdTimePickView_mTextColor1, Color.parseColor("#333333"));
- //注意资源的回收
- typedArray.recycle();
- this.mContext = context;
- init();
- }
- private void init() {
- mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- mPaint.setAntiAlias(true);
- mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- mTextPaint.setColor(mTextColor);
- mTextPaint.setTextSize(mTextSize);
- mTextPaint.setStyle(Paint.Style.FILL);
- mTextPaint.setAntiAlias(true);
- }@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- mWidth = getViewSize(widthMeasureSpec, 0);
- mHeight = getViewSize(heightMeasureSpec, 1);
- //大半径
- mRadius = Math.min(mWidth, mHeight) / 2;
- setMeasuredDimension(mWidth, mHeight);
- }
- private int getViewSize(int viewMeasureSpec, int type) {
- int viewValue = 0;
- int viewSize = MeasureSpec.getSize(viewMeasureSpec);
- int viewMode = MeasureSpec.getMode(viewMeasureSpec);
- if (MeasureSpec.EXACTLY == viewMode) {
- viewValue = viewSize;
- if (type == 0) {
- mCirCleX = viewSize / 2;
- } else {
- mCircleY = viewSize / 2;
- }
- } else {
- if (type == 0) {
- mCirCleX = mRadius;
- } else {
- mCircleY = mRadius;
- }
- viewValue = 2 * (mRadius + mProgressViewWidth);
- }
- return viewValue;
- }@Override protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- mPaint.setColor(mSmallCircleBg);
- mPaint.setStyle(Paint.Style.FILL);
- canvas.drawCircle(mCirCleX, mCircleY, (float)(mRadius - 1.5 * mProgressViewWidth), mPaint);
- //设置画笔状态
- mPaint.setColor(mTextColor);
- mPaint.setStyle(Paint.Style.STROKE);
- mPaint.setStrokeWidth(mProgressViewWidth);
- //保存Canvans的状态
- canvas.save();
- //将坐标系围绕View的中心逆时针旋转90度数
- canvas.rotate( - 90, mCirCleX, mCircleY);
- RectF rectF = new RectF(mCirCleX - mRadius + mProgressViewWidth, mCirCleX - mRadius + mProgressViewWidth, mCirCleX + mRadius - mProgressViewWidth, mCirCleX + mRadius - mProgressViewWidth);
- //第四个参数表示逆时针还是顺时针绘制
- canvas.drawArc(rectF, 0, -mCurrentAngle, false, mPaint);
- canvas.restore();
- Rect textRect = getTextRect(String.valueOf(mAdTIme));
- Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
- int baseLine = (int)(mHeight / 2 + (fontMetrics.descent - fontMetrics.ascent) / 2 - fontMetrics.descent);
- int x = mWidth / 2 - textRect.width() / 2;
- canvas.drawText(String.valueOf(mAdTIme), x, baseLine, mTextPaint);
- }
- private Rect getTextRect(String centerContent) {
- Rect rect = new Rect();
- mTextPaint.getTextBounds(centerContent, 0, centerContent.length(), rect);
- return rect;
- }
- public void refresh() {
- final int countAngel = 360;
- Observable.interval(1, TIME_DIFF, TimeUnit.MILLISECONDS).map(value - >{
- return countAngel - value.intValue();
- }).limit(361).subscribe(action - >{
- if (action % 72 == 0) {
- mAdTIme = action / 72;
- }
- mCurrentAngle = action;
- AdTimePickView.this.postInvalidate();
- });
- }
- }
以上所述是小编给大家介绍的Android 自定义闪屏页广告倒计时view效果,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的,在此也非常感谢大家对PHPERZ网站的支持!
来源: http://www.phperz.com/article/17/0828/337651.html