Android自定义View实现点赞控件
程序员文章站
2022-05-31 12:44:46
本文实例为大家分享了android点赞控件的具体代码,供大家参考,具体内容如下
预览效果
目录
图片类:likeimageview
文字类:likechartextview...
本文实例为大家分享了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 *fanwei = 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) > *fanwei || math.abs(lasty - y) > *fanwei) { 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>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: 木卯先生的笔记---Object类
推荐阅读