当前位置: 移动技术网 > 移动技术>移动开发>Android > Android 自定义闪屏页广告倒计时view效果

Android 自定义闪屏页广告倒计时view效果

2019年07月24日  | 移动技术网移动技术  | 我要评论

如今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效果,希望对大家有所帮助

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网