Android 自定义星评空间示例代码
程序员文章站
2023-11-12 13:20:04
没事做用自定义view方式写一个星评控件,虽说网上很多这个控件,但是这是自己写的,在这里记录一下。
首先需要自定义属性
没事做用自定义view方式写一个星评控件,虽说网上很多这个控件,但是这是自己写的,在这里记录一下。
首先需要自定义属性
<declare-styleable name="rate"> <!--属性分别是:单个的宽,高,之间的距离,激活的数量,总数量,激活的drawable,没有激活的drawable,是否可以选择数量--> <attr name="custom_rate_width" format="dimension"/> <attr name="custom_rate_height" format="dimension"/> <attr name="custom_rate_padding" format="dimension"/> <attr name="custom_rate_active_size" format="integer"/> <attr name="custom_rate_size" format="integer"/> <attr name="custom_rate_active_drawable" format="reference"/> <attr name="custom_rate_disactive_drawable" format="reference"/> <attr name="custom_rate_touch" format="boolean"/> </declare-styleable>
初始化代码
protected void init(context context, attributeset attrs) { typedarray array = context.obtainstyledattributes(attrs, r.styleable.rate); int activeid = 0; int disactiveid = 0; if (array != null) { size = array.getint(r.styleable.rate_custom_rate_size, 5); activesize = array.getint(r.styleable.rate_custom_rate_active_size, 3); ratewidth = array.getdimensionpixeloffset(r.styleable.rate_custom_rate_width, 0); rateheight = array.getdimensionpixeloffset(r.styleable.rate_custom_rate_height, 0); activeid = array.getresourceid(r.styleable.rate_custom_rate_active_drawable, 0); disactiveid = array.getresourceid(r.styleable.rate_custom_rate_disactive_drawable, 0); padding = array.getdimensionpixeloffset(r.styleable.rate_custom_rate_padding, 0); istouch = array.getboolean(r.styleable.rate_custom_rate_touch, false); array.recycle(); } //如果没有宽高就设置一个默认值 if (rateheight <= 0){ rateheight = 80; } if (ratewidth <= 0){ ratewidth = 80; } if (activeid!=0){ activebitmap = bitmapfactory.decoderesource(getresources(), activeid); //如果没有设置宽高时候 if (ratewidth <= 0) { ratewidth = activebitmap.getwidth(); } //把图片压缩到设置的宽高 activebitmap = bitmap.createscaledbitmap(activebitmap, (int) ratewidth, (int) rateheight, false); } if (disactiveid != 0){ disactivebitmap = bitmapfactory.decoderesource(getresources(), disactiveid); if (rateheight <= 0) { rateheight = activebitmap.getheight(); } disactivebitmap = bitmap.createscaledbitmap(disactivebitmap, (int) ratewidth, (int) rateheight, false); } mpaint = new paint();//初始化bitmap的画笔 mpaint.setantialias(true); activpaint = new paint();//初始化选中星星的画笔 activpaint.setantialias(true); activpaint.setcolor(color.yellow); disactivpaint = new paint();//初始化未选中星星的画笔 disactivpaint.setantialias(true); disactivpaint.setcolor(color.gray); }
onmeasure方法设置view的宽高,如果设置的每一个星星控件的宽高大于实际view的宽高,就用星星空间的宽高作于view的宽高
@override protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { int widthmode = measurespec.getmode(widthmeasurespec); int widthsize = measurespec.getsize(widthmeasurespec); int heightmode = measurespec.getmode(heightmeasurespec); int heightsize = measurespec.getsize(heightmeasurespec); //计算宽 if (widthmode == measurespec.exactly) { //如果view的宽度小于设置size*星星的宽度,就用size * (int) (padding + ratewidth)做为控件的宽度度 if (widthsize < size * (int) (padding + ratewidth)) { width = size * (int) (padding + ratewidth); } else { width = widthsize; } } else { width = size * (int) (padding + ratewidth)-padding; } //计算高 if (heightmode == measurespec.exactly) { //如果view的高度小于设置星星的高度,就用星星高度做为控件的高度 if (heightsize < rateheight) { height = (int) rateheight + 5; } else { height = heightsize; } } else { height = (int) rateheight + 5; } setmeasureddimension(width, height); }
ondraw方法中绘制
//开始画active for (int i = 0; i < activesize; i++) { if (activebitmap != null){ if (i == 0) { canvas.drawbitmap(activebitmap, ratewidth * i, (height - rateheight) / 2, mpaint); } else { canvas.drawbitmap(activebitmap, (ratewidth + padding) * i, (height - rateheight) / 2, mpaint); } }else { drawactivrate(i,canvas); } } // //开始画disactive for (int i = activesize; i < size; i++) { if (disactivebitmap != null){ if (i == 0) { canvas.drawbitmap(disactivebitmap, ratewidth * i, (height - rateheight) / 2, mpaint); } else { canvas.drawbitmap(disactivebitmap, (ratewidth + padding) * i, (height - rateheight) / 2, mpaint); } }else { drawdisactivrate(i,canvas); } }
上面用到两个方法drawactivrate和drawdisactivrate,分别是在没有设置活动中的星星和不在活动中星星的图片的时候,绘制在活动和不在活动的默认星星:
/** * 绘制黄色的五角星(在活动的) * */ private void drawactivrate(int position,canvas canvas){ float radius = ratewidth/2;//根據每一個星星的位置繪製園,確定五角星五個點的位置 float angle = 360/5; float centerx = (ratewidth+padding)*(position+1)-padding-radius;//獲取每一個星星空間的中心位置的x坐標 float centery =height/2;//獲取每一個星星空間的中心位置的y坐標 path mpath = new path(); mpath.moveto(centerx,centery-radius); mpath.lineto(centerx+(float) math.cos((angle*2-90)*math.pi / 180)*radius,centery+(float)math.sin((angle*2-90)*math.pi / 180)*radius); mpath.lineto( centerx-(float)math.sin(angle*math.pi / 180)*radius,centery-(float)math.cos(angle*math.pi / 180)*radius); mpath.lineto( centerx+(float)math.sin(angle*math.pi / 180)*radius,centery-(float)math.cos(angle*math.pi / 180)*radius); mpath.lineto( centerx-(float)math.sin((angle*3-180)*math.pi / 180)*radius,centery+(float)math.cos((angle*3-180)*math.pi / 180)*radius); // mpath.lineto(centerx,centery-radius); mpath.close(); canvas.drawpath(mpath,activpaint); } /** * 绘制灰色的五角星 * */ private void drawdisactivrate(int position,canvas canvas){ float radius = ratewidth/2; float angle = 360/5; float centerx = (ratewidth+padding)*(position+1)-padding-radius; float centery =height/2; path mpath = new path(); mpath.moveto(centerx,centery-radius); mpath.lineto(centerx+(float) math.cos((angle*2-90)*math.pi / 180)*radius,centery+(float)math.sin((angle*2-90)*math.pi / 180)*radius); mpath.lineto( centerx-(float)math.sin(angle*math.pi / 180)*radius,centery-(float)math.cos(angle*math.pi / 180)*radius); mpath.lineto( centerx+(float)math.sin(angle*math.pi / 180)*radius,centery-(float)math.cos(angle*math.pi / 180)*radius); mpath.lineto( centerx-(float)math.sin((angle*3-180)*math.pi / 180)*radius,centery+(float)math.cos((angle*3-180)*math.pi / 180)*radius); // mpath.lineto(centerx,centery-radius); mpath.close(); canvas.drawpath(mpath,disactivpaint); }
最后在ontouchevent方法中处理选中和未选中星星的处理
@override public boolean ontouchevent(motionevent event) { if (!istouch){//如果不支持觸摸 return false; } switch (event.getaction()) { case motionevent.action_down: touchx = event.getx(); touchy = event.gety(); for (int i = 0; i < size; i++) { if (i == 0) { if (0.0 < touchx && touchx < ratewidth+padding/2) { activesize = 1; } }else { if ((ratewidth+padding)*i-padding/2<touchx&&touchx<(ratewidth+padding)*(i+1)-padding/2){ activesize = i+1; } } } invalidate(); break; case motionevent.action_up: if ( null!= changelistener){ changelistener.change(activesize); } break; case motionevent.action_move: touchx = event.getx(); touchy = event.gety(); for (int i = 0; i < size; i++) { if (i == 0) { if (0.0 < touchx && touchx < ratewidth+padding/2) { activesize = 1; } }else { if ((ratewidth+padding)*i-padding/2<touchx&&touchx<(ratewidth+padding)*(i+1)-padding/2){ activesize = i+1; } } } invalidate(); if (touchx<=0){ activesize = 0; } break; } return true; }
以上就是自定义view写的星评控件,代码中的注解已经比较详细了,就不多说了,
源码地址
以上所述是小编给大家介绍的android自定义星评空间的实例代码,希望对大家有所帮助!
推荐阅读
-
Android 自定义星评空间示例代码
-
Android 自定义LineLayout实现满屏任意拖动功能的示例代码
-
Android仿QQ空间底部菜单示例代码
-
Android自定义view仿QQ的Tab按钮动画效果(示例代码)
-
Android RecycleView 实现左滑上下分层示例代码(自定义功能)
-
android仿即刻点赞文字部分的自定义View的示例代码
-
Android 自定义SeekBar 实现分段显示不同背景颜色的示例代码
-
Android 自定义加载动画Dialog弹窗效果的示例代码
-
android通过自定义toast实现悬浮通知效果的示例代码
-
Android自定义view仿QQ的Tab按钮动画效果(示例代码)