当前位置: 移动技术网 > IT编程>移动开发>Android > Android自定义View实现点赞控件

Android自定义View实现点赞控件

2020年03月09日  | 移动技术网IT编程  | 我要评论

于佩,湖南营销型网站建设,杨恒均博客

本文实例为大家分享了android点赞控件的具体代码,供大家参考,具体内容如下

预览效果

目录

图片类:likeimageview
文字类:likechartextview
整合类:likeview.java
自定义属性:attrs.xml

代码

likechartextview

public class likechartextview extends view {

 public static final int default_textcolor = color.black;
 public static final int default_textsize = 36;

 private textpaint newtextpaint, oldtextpaint;

 private animatorset addanimator;
 private animatorset minusanimator;

 private int  measurewidth;
 private int  measureheight;

 private int  textcolor  = default_textcolor;
 private int  textsize  = default_textsize;

 private int  num;
 private int  oldnum;
 private int  newnum;

 private int  animatoroldy;
 private float  animatoroldalpha = 1;

 private int  animatornewy;
 private float  animatornewalpha = 0;
 private int  baseline;

 public likechartextview(context context) {
 super(context);

 init();
 }

 public likechartextview(context context, @nullable attributeset attrs) {
 super(context, attrs);

 initattr(context, attrs);

 init();
 }

 public likechartextview(context context, @nullable attributeset attrs,
    int defstyleattr) {
 super(context, attrs, defstyleattr);

 initattr(context, attrs);

 init();
 }

 /**
 * 初始化属性
 *
 * @param context
 * @param attrs
 */
 private void initattr(context context, @nullable attributeset attrs) {
 typedarray typedarray = context.obtainstyledattributes(attrs,
  r.styleable.likechartextview);
 textcolor = typedarray.getcolor(r.styleable.likechartextview_textcolor,
  default_textcolor);
 textsize = typedarray.getdimensionpixelsize(r.styleable.likechartextview_textsize,
  default_textsize);
 num = typedarray.getint(r.styleable.likechartextview_number, 0);
 if (0 > num || num > 10) {
  throw new illegalargumentexception("number is only 0-9");
 }
 oldnum = num;

 typedarray.recycle();
 }

 /**
 * 初始化
 */
 private void init() {
 initpaints();
 initparams();
 }

 /**
 * 初始化画笔
 */
 private void initpaints() {
 newtextpaint = new textpaint(paint.anti_alias_flag);
 newtextpaint.setstyle(paint.style.fill);
 newtextpaint.settextsize(textsize);
 newtextpaint.setcolor(textcolor);
 newtextpaint.settextalign(paint.align.center);

 oldtextpaint = new textpaint(paint.anti_alias_flag);
 oldtextpaint.set(newtextpaint);
 }

 /**
 * 初始化参数
 */
 private void initparams() {
 paint.fontmetrics fontmetrics = newtextpaint.getfontmetrics();
 measurewidth = (int) newtextpaint.measuretext(string.valueof(num));
 measureheight = (int) (fontmetrics.bottom - fontmetrics.top);

 float distance = (fontmetrics.bottom - fontmetrics.top) / 2 - fontmetrics.bottom;
 baseline = (int) (measureheight * 1.0f / 2 + distance);

 animatoroldy = baseline;
 }

 @override
 protected void onmeasure(int widthmeasurespec, int heightmeasurespec) {
 super.onmeasure(widthmeasurespec, heightmeasurespec);

 int widthmode = measurespec.getmode(widthmeasurespec);
 int widthsize = measurespec.getsize(widthmeasurespec);
 switch (widthmode) {
  case measurespec.unspecified:
  break;
  case measurespec.at_most:
  widthsize = measurewidth;
  break;
  case measurespec.exactly:
  break;
 }

 int heightmode = measurespec.getmode(widthmeasurespec);
 int heightsize = measurespec.getsize(widthmeasurespec);
 switch (heightmode) {
  case measurespec.unspecified:
  break;
  case measurespec.at_most:
  heightsize = measureheight;
  break;
  case measurespec.exactly:
  break;
 }

 setmeasureddimension(widthsize, heightsize);
 }

 @override
 protected void ondraw(canvas canvas) {
 super.ondraw(canvas);
 int width = getwidth();
 int height = getheight();
 oldtextpaint.setalpha((int) (255 * animatoroldalpha));
 canvas.drawtext(string.valueof(oldnum), width / 2, animatoroldy, oldtextpaint);

 newtextpaint.setalpha((int) (255 * animatornewalpha));
 canvas.drawtext(string.valueof(newnum), width / 2, animatornewy, newtextpaint);
 }

 public void settextcolor(int textcolor) {
 this.textcolor = textcolor;
 init();
 invalidate();
 }

 public void settextsize(int textsize) {
 this.textsize = textsize;
 init();
 invalidate();
 }

 public void setanimatoroldy(int animatoroldy) {
 this.animatoroldy = animatoroldy;
 invalidate();
 }

 public void setanimatoroldalpha(float animatoroldalpha) {
 this.animatoroldalpha = animatoroldalpha;
 invalidate();
 }

 public void setanimatornewy(int animatornewy) {
 this.animatornewy = animatornewy;
 invalidate();
 }

 public void setanimatornewalpha(float animatornewalpha) {
 this.animatornewalpha = animatornewalpha;
 invalidate();
 }

 public void setnum(int num) {
 this.num = num;
 if (0 > num || num > 10) {
  throw new illegalargumentexception("number is only 0-9");
 }
 oldnum = num;
 invalidate();
 }

 public void add() {
 logger.e("执行加动画.基线:" + baseline);
 objectanimator oldyanimator = objectanimator.ofint(this, "animatoroldy", baseline, 0);
 objectanimator oldalphaanimator = objectanimator.offloat(this, "animatoroldalpha", 1, 0);
 objectanimator newyanimator = objectanimator.ofint(this, "animatornewy", baseline * 2,
  baseline);
 objectanimator newalphaanimator = objectanimator.offloat(this, "animatornewalpha", 0, 1);

 addanimator = new animatorset();
 addanimator.playtogether(oldyanimator, oldalphaanimator, newyanimator, newalphaanimator);
 addanimator.setinterpolator(new linearinterpolator());
 addanimator.setduration(300);
 addanimator.start();
 }

 public void minus() {
 logger.e("执行减动画.基线:" + baseline);
 objectanimator oldyanimator = objectanimator.ofint(this, "animatoroldy", baseline,
  baseline * 2);
 objectanimator oldalphaanimator = objectanimator.offloat(this, "animatoroldalpha", 1, 0);
 objectanimator newyanimator = objectanimator.ofint(this, "animatornewy", 0, baseline);
 objectanimator newalphaanimator = objectanimator.offloat(this, "animatornewalpha", 0, 1);

 minusanimator = new animatorset();
 minusanimator.playtogether(oldyanimator, oldalphaanimator, newyanimator, newalphaanimator);
 minusanimator.setinterpolator(new linearinterpolator());
 minusanimator.setduration(300);
 minusanimator.start();
 }

 public void change(boolean isadd) {
 logger.e("chartextvie.点击事件:" + isadd);
 if (isadd) {
  if (null != addanimator && addanimator.isstarted()) {
  logger.e("chartextvie.加动画已执行.取消");
  addanimator.cancel();
  }
  if (null != minusanimator && minusanimator.isstarted()) {
  logger.e("chartextvie.减动画已执行.取消");
  minusanimator.cancel();
  }
  sumnum(false);
  minus();
 } else {
  if (null != minusanimator && minusanimator.isstarted()) {
  logger.e("chartextvie.减动画已执行.取消");
  minusanimator.cancel();
  }
  if (null != addanimator && addanimator.isstarted()) {
  logger.e("chartextvie.加动画已执行.取消");
  addanimator.cancel();
  }
  sumnum(true);
  add();
 }
 }

 /**
 * 重新计算绘画的值
 *
 * @param isadd
 */
 private void sumnum(boolean isadd) {
 logger.e("计算值开始");
 oldnum = num;
 newnum = num + (isadd ? 1 : -1);
 if (newnum < 0) {
  newnum = 9;
 } else if (newnum > 9) {
  newnum = 0;
 }
 num = newnum;
 logger.e("计算值结束:" + num);
 }
}

likeimageview

public class likeimageview extends view {

 private paint imagepaint, shiningpaint;

 private int shiningmovex;
 private int shiningmovey;

 private int measurewidth;
 private int measureheight;
 private bitmap selectedbtimap;
 private bitmap selectedshiningbtimap;
 private bitmap unselectedbtimap;

 private boolean isadd = false;

 private float shiningalpha = isadd ? 1f : 0f;

 public likeimageview(context context) {
 super(context);

 init();
 }

 public likeimageview(context context, @nullable attributeset attrs) {
 super(context, attrs);

 init();
 }

 public likeimageview(context context, @nullable attributeset attrs, int defstyleattr) {
 super(context, attrs, defstyleattr);

 init();
 }

 private void init() {
 imagepaint = new paint(paint.anti_alias_flag);
 shiningpaint = new paint(paint.anti_alias_flag);

 selectedbtimap = bitmapfactory.decoderesource(getresources(), r.mipmap.ic_like_selected);
 selectedshiningbtimap = bitmapfactory.decoderesource(getresources(),
  r.mipmap.ic_like_selected_shining);
 unselectedbtimap = bitmapfactory.decoderesource(getresources(),
  r.mipmap.ic_like_unselected);
 }

 @override
 protected void onmeasure(int widthmeasurespec, int heightmeasurespec) {
 super.onmeasure(widthmeasurespec, heightmeasurespec);

 int widthmode = measurespec.getmode(widthmeasurespec);
 int widthsize = measurespec.getsize(widthmeasurespec);
 switch (widthmode) {
  case measurespec.unspecified:
  break;
  case measurespec.at_most:
  widthsize = math.max(selectedbtimap.getwidth(), unselectedbtimap.getwidth());
  shiningmovex = (int) (widthsize * 1.0f - selectedshiningbtimap.getwidth()) - 2;
  break;
  case measurespec.exactly:
  break;
 }

 int heightmode = measurespec.getmode(widthmeasurespec);
 int heightsize = measurespec.getsize(widthmeasurespec);
 switch (heightmode) {
  case measurespec.unspecified:
  break;
  case measurespec.at_most:
  heightsize = math.max(selectedbtimap.getheight(), unselectedbtimap.getheight());
  shiningmovey = (int) (selectedshiningbtimap.getheight() * 1.0f / 3);
  heightsize += shiningmovey;
  break;
  case measurespec.exactly:
  break;
 }

 setmeasureddimension(widthsize, heightsize);
 }

 @override
 protected void ondraw(canvas canvas) {
 super.ondraw(canvas);

 int width = getwidth();
 int height = getheight();
 rect src = new rect(0, 0, width, height);
 rect selectdst = new rect(0, shiningmovey, selectedbtimap.getwidth(), height);
 if (isadd) {
  //画红赞
  canvas.drawbitmap(selectedbtimap, src, selectdst, imagepaint);
  //画阴影
  shiningpaint.setalpha((int) (255 * shiningalpha));
  rect shiningdst = new rect(shiningmovex, 0,
   shiningmovex + selectedshiningbtimap.getwidth(), selectedshiningbtimap.getheight());
  canvas.drawbitmap(selectedshiningbtimap, src, shiningdst, shiningpaint);
 } else {
  //画灰赞
  canvas.drawbitmap(unselectedbtimap, src, selectdst, imagepaint);
 }
 }

 public void setshiningalpha(float shiningalpha) {
 this.shiningalpha = shiningalpha;
 invalidate();
 }

 public void setadd(boolean add) {
 isadd = add;
 shiningalpha = 1.0f;
 invalidate();
 }

 public void changelike(boolean isadd) {
 this.isadd = !isadd;
 invalidate();
 anim();
 }

 private void anim() {
 objectanimator scalexanim = objectanimator.offloat(this, "scalex", 0.7f, 1f);
 scalexanim.setduration(500);
 objectanimator scaleyanim = objectanimator.offloat(this, "scaley", 0.7f, 1f);
 scaleyanim.setduration(500);
 objectanimator alphaanim = objectanimator.offloat(this, "shiningalpha", 0f, 1f);
 alphaanim.setduration(500);
 animatorset animatorset = new animatorset();
 animatorset.playtogether(scalexanim, scaleyanim, alphaanim);
 animatorset.setinterpolator(new bounceinterpolator());
 animatorset.start();
 }
}

likeview

public class likeview extends linearlayout {
 private final int imagepadding = 4;

 private boolean isadd = false;

 private int num;
 private int textsize;
 private int textcolor;

 private int imagepadding;

 private list<likechartextview> chartvs = new arraylist<>();
 private likeimageview likeimageview;

 public likeview(context context) {
 super(context);
 init();
 }

 public likeview(context context, @nullable attributeset attrs) {
 super(context, attrs);

 initattr(context, attrs);

 init();
 }

 public likeview(context context, @nullable attributeset attrs, int defstyleattr) {
 super(context, attrs, defstyleattr);

 initattr(context, attrs);

 init();
 }

 private void initattr(context context, attributeset attrs) {
 typedarray typedarray = context.obtainstyledattributes(attrs, r.styleable.likeview);
 textcolor = typedarray.getcolor(r.styleable.likeview_textcolor,
  likechartextview.default_textcolor);
 textsize = typedarray.getdimensionpixelsize(r.styleable.likeview_textsize,
  likechartextview.default_textsize);
 num = typedarray.getint(r.styleable.likeview_number, 0);
 imagepadding = typedarray.getdimensionpixelsize(r.styleable.likeview_imagepadding, imagepadding);

 typedarray.recycle();
 }

 /**
 * 初始化
 */
 private void init() {

 initview();
 }

 protected void initview() {
 removeallviews();

 likeimageview = new likeimageview(getcontext());
 likeimageview.setadd(isadd);
 linearlayout.layoutparams layoutparams = new linearlayout.layoutparams(viewgroup.layoutparams.wrap_content, viewgroup.layoutparams.wrap_content);
 layoutparams.rightmargin = imagepadding;
 likeimageview.setlayoutparams(layoutparams);
 addview(likeimageview);

 chartvs.clear();
 string str_num = string.valueof(num);
 for (int i = 0; i < str_num.length(); i++) {
  likechartextview textview = new likechartextview(getcontext());
  int show_num = integer.valueof(str_num.substring(i, i + 1));
  log.e("zanview", "show_num:" + show_num);
  textview.settextsize(textsize);
  textview.settextcolor(textcolor);
  textview.setnum(show_num);
  addview(textview);
  chartvs.add(textview);
 }
 }

 public void setnum(int num) {
 this.num = num;
 init();
 invalidate();
 }

 public void setadd(boolean add) {
 isadd = add;
 }

 @override
 protected void onmeasure(int widthmeasurespec, int heightmeasurespec) {
 super.onmeasure(widthmeasurespec, heightmeasurespec);
 //计算出所有的childview的宽高
 measurechildren(widthmeasurespec, heightmeasurespec);
 setmeasureddimension(measurewidth(widthmeasurespec), measureheight(heightmeasurespec));
 }

 /**
 * 测量宽度
 *
 * @param widthmeasurespec
 * @return
 */
 private int measurewidth(int widthmeasurespec) {
 int widthmode = measurespec.getmode(widthmeasurespec);
 int widthsize = measurespec.getsize(widthmeasurespec);
 switch (widthmode) {
  case measurespec.unspecified:
  break;
  case measurespec.at_most:
  widthsize = 0;
  for (int i = 0; i < getchildcount(); i++) {
   view childview = getchildat(i);
   //获取子view的宽
   int cwidth = childview.getmeasuredwidth();
   marginlayoutparams params = (marginlayoutparams) childview.getlayoutparams();
   widthsize += cwidth + params.leftmargin + params.rightmargin;
  }
  break;
  case measurespec.exactly:
  break;
 }
 return widthsize;
 }

 /**
 * 测量高度
 *
 * @param widthmeasurespec
 * @return
 */
 private int measureheight(int widthmeasurespec) {
 int heightmode = measurespec.getmode(widthmeasurespec);
 int heightsize = measurespec.getsize(widthmeasurespec);
 switch (heightmode) {
  case measurespec.unspecified:
  break;
  case measurespec.at_most:
  heightsize = 0;
  for (int i = 0; i < getchildcount(); i++) {
   view childview = getchildat(i);
   //获取子view的宽
   int cwidth = childview.getmeasuredheight();
   marginlayoutparams params = (marginlayoutparams) childview.getlayoutparams();
   int height = cwidth + params.leftmargin + params.rightmargin;
   heightsize = math.max(heightsize, height);
  }
  break;
  case measurespec.exactly:
  break;
 }
 return heightsize;
 }

 private boolean click = false;

 private final int mohufanwei = 10;

 private float lastx = 0;
 private float lasty = 0;

 @override
 public boolean ontouchevent(motionevent event) {
 super.ontouchevent(event);
 float x = event.getx();
 float y = event.gety();

 switch (event.getaction()) {
  case motionevent.action_down:
  if (1 == event.getpointercount()) {
   click = true;
  }
  break;
  case motionevent.action_up:
  if (click) {
   onclick();
  }
  break;
  case motionevent.action_move:
  if (math.abs(lastx - x) > mohufanwei || math.abs(lasty - y) > mohufanwei) {
   click = false;
  }
  break;
 }

 lastx = x;
 lasty = y;
 return true;
 }

 private void onclick() {
 logger.e("点击事件" + isadd);
 string str_num = string.valueof(num);
 logger.e("点击事件,str_num:" + str_num);
 boolean nextanim = false;
 if (isadd) {
  likeimageview.changelike(true);
  for (int i = (str_num.length() - 1); i >= 0; i--) {
  int chr_num = integer.valueof(str_num.substring(i, i + 1));
  logger.e("点击事件,chr_num:%d,chartvs.size:%d,i:%d", chr_num, chartvs.size(), i);
  logger.e("是否执行动画:" + (chartvs.size() > i));
  if (chartvs.size() > i) {
   if (i == (str_num.length() - 1) || nextanim) {
   logger.e("点击事件,执行个位动画||%b执行执行上%d位动画", nextanim, i);
   chartvs.get(i).change(true);

   chr_num--;
   logger.e("chr_num:%d,是否执行上一位动画:", chr_num, (chr_num < 0));
   if (chr_num < 0) {
    nextanim = true;
   } else {
    nextanim = false;
   }

   logger.e("nextanim:" + nextanim);
   }
  }
  }
  num--;
  isadd = !isadd;
 } else {
  likeimageview.changelike(false);
  for (int i = (str_num.length() - 1); i >= 0; i--) {
  int chr_num = integer.valueof(str_num.substring(i, i + 1));
  logger.e("点击事件,chr_num:%d,chartvs.size:%d,i:%d", chr_num, chartvs.size(), i);
  logger.e("是否执行动画:" + (chartvs.size() > i));
  if (chartvs.size() > i) {
   if (i == (str_num.length() - 1) || nextanim) {
   logger.e("点击事件,执行个位动画||%b执行执行上%d位动画", nextanim, i);
   chartvs.get(i).change(false);

   chr_num++;
   logger.e("chr_num:%d,是否执行上一位动画:", chr_num, (chr_num > 9));
   if (chr_num > 9) {
    nextanim = true;
   } else {
    nextanim = false;
   }
   logger.e("nextanim:" + nextanim);
   }
  }
  }
  num++;
  isadd = !isadd;
 }
 }
}

attrs.xml

<attr name="textsize" format="dimension" />
 <attr name="textcolor" format="color" />
 <attr name="number" format="integer" />

 <attr name="imagewidth" format="dimension" />
 <attr name="imageheight" format="dimension" />

 <declare-styleable name="likeview">
 <attr name="textsize" />
 <attr name="textcolor" />
 <attr name="number" />
 <attr name="imagewithd" />
 <attr name="imageheight" />
 <attr name="imagepadding" format="dimension" />
 </declare-styleable>

 <declare-styleable name="likechartextview">
 <attr name="textsize" />
 <attr name="textcolor" />
 <attr name="number" />
 </declare-styleable>

 <declare-styleable name="likeimageview">
 <attr name="imagewithd" />
 <attr name="imageheight" />
</declare-styleable>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网