Android 自定义星评空间示例代码

没事做用自定义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自定义星评空间的实例代码,希望对大家有所帮助!

时间: 2024-09-20 05:24:58

Android 自定义星评空间示例代码的相关文章

Android 自定义弹出框实现代码_Android

废话不多说了,直接给大家上关键代码了. - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. [self showAlertView:@"11111"]; } //自定义弹出框 -(void)showAlertView:(NSString *)strTipText { UIView *showView=[[UIView alloc]init]; [sho

Android 自定义弹出框实现代码

废话不多说了,直接给大家上关键代码了. - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. [self showAlertView:@"11111"]; } //自定义弹出框 -(void)showAlertView:(NSString *)strTipText { UIView *showView=[[UIView alloc]init]; [sho

Android自定义手机界面状态栏实例代码

前言 我们知道IOS上的应用,状态栏的颜色总能与应用标题栏颜色保持一致,用户体验很不错,那安卓是否可以呢?若是在安卓4.4之前,答案是否定的,但在4.4之后,谷歌允许开发者自定义状态栏背景颜色啦,这是个不错的体验!若你手机上安装有最新版的qq,并且你的安卓SDK版本是4.4及以上,你可以看下它的效果: 实现这个效果有两个方法: 1.在xml中设置主题或自定义style: Theme.Holo.Light.NoActionBar.TranslucentDecor Theme.Holo.NoActi

Android 自定义View之倒计时实例代码

Android 自定义View之倒计时实例代码 需求: 大多数app在注册的时候,都有一个获取验证码的按钮,点击后,访问接口,最终用户会收到短信验证码.为了不多次写这个获取验证码的接口,下面将它自定义成一个view,方便使用. 分析一下,这是一个TextView,点击的时候变色,不能再点击,同时里面的倒计时开始显示.那么就有了下面的代码 代码: /** * 通过selector选择器来改变背景,其中倒计时运行时为android:state_enabled="true", * 不显示倒计

Android Menu详解及示例代码_Android

Android Menu 详细介绍: 1.选项菜单 OptionsMenu 2.上下文菜单 ContextMenu 3.子菜单 SubMenu 组成Android用户界面的除了View以外,还有菜单和对话框,这一讲我们就共同学习一下菜单的使用. 菜单是用户界面中最常见的元素,使用也非常频繁,在Android中,菜单被分为如下三种,选项菜单(OptionsMenu).上下文菜单(ContextMenu)和子菜单(SubMenu),下面分别举例说明. 一.选项菜单 OptionsMenu Andro

Android GPS详解及示例代码_Android

LBS(Location Based Services)直译的话就是基于地理位置的服务,这里面至少有两层意思,第一要能轻易的获取当前的地理位置,譬如经纬度海拔等,另一个就是在当前位置的基础上提供增值服务,譬如找附近的加油站.餐馆.酒店等.这里面的第一步:获取用户当前位置,我们就可以用Android的GPS定位服务来得到.Android提供了基于网络的定位服务和基于卫星的定位服务两种.在设置->位置和安全设置里面的前三项就是,最后一个增强型GPS是为了辅助快速找卫星的.  那么我们现在就写一个简单

Android Service详解及示例代码_Android

Android Service 详细介绍: 1.Service的概念 2.Service的生命周期 3.实例:控制音乐播放的Service 一.Service的概念 Service是Android程序中四大基础组件之一,它和Activity一样都是Context的子类,只不过它没有UI界面,是在后台运行的组件. 二.Service的生命周期 Service对象不能自己启动,需要通过某个Activity.Service或者其他Context对象来启动.启动的方法有两种,Context.startS

Android SQLite详解及示例代码_Android

在Android中使用SQLite数据库的入门指南,打算分下面几部分与大家一起分享, 1.什么是SQLite 2.Android中使用SQLite 一.什么是SQLite SQLite是一款开源的.轻量级的.嵌入式的.关系型数据库.它在2000年由D. Richard Hipp发布,可以支援Java.Net.PHP.Ruby.Python.Perl.C等几乎所有的现代编程语言,支持Windows.Linux.Unix.Mac OS.Android.IOS等几乎所有的主流操作系统平台. SQLit

android自定义倒计时控件示例_Android

自定义TextView控件TimeTextView代码: 复制代码 代码如下: import android.content.Context;import android.content.res.TypedArray;import android.graphics.Paint;import android.text.Html;import android.util.AttributeSet;import android.widget.TextView; import com.new0315.R;