这里有新鲜出炉的精品教程,程序狗速度看过来!
Android 是一种基于 Linux 的自由及开放源代码的操作系统,主要使用于移动设备,如智能手机和平板电脑,由 Google 公司和开放手机联盟领导及开发。尚未有统一中文名称,中国大陆地区较多人使用 "安卓" 或 "安致"。
这篇文章主要介绍了 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 写的星评控件,代码中的注解已经比较详细了,就不多说了,
源码地址
来源: http://www.phperz.com/article/17/0822/337526.html