Android自定义控件--评分星级View

Android自定义View实现商品评价星星评分控件 先上图看实现效果: 首先在res/values/ 下建立一个attrs.xml , 在里面定义我们的属性,只定义三个,有间距、分值和是否可以编辑:<!--StarLinearLayout--> <declare-styleable name="star"> <attr name="margin" format="dimension|reference"/> 阅读详情
在开发电商项目中经常都会遇到一些星级评分控件的需求,有需求就必然有开发。废话不多说,没图没真相,上图:

image

确定需求:

  • 可以控制子item之间的边距
  • 自定义选中图片和未选中图片
  • 摆放纵向或者横向
  • 可选择选中数量

基本绘制流程:

  • 1 自定义属性
<!--星星控件属性-->
    <declare-styleable name="StarBarView">
        <!--设置星星间的间隔-->
        <attr name="space_width" format="dimension" />
        <!--星星间宽度-->
        <attr name="star_width" format="dimension" />
        <!--星星间高度-->
        <attr name="star_height" format="dimension" />
        <!--最大数量-->
        <attr name="star_max" format="integer" />
        <!--选中数量-->
        <attr name="star_rating" format="float" />
        <!--未选中图片-->
        <attr name="star_hollow" format="reference" />
        <!--选中图片-->
        <attr name="star_solid" format="reference" />
        <!--是否可以滑动改变选中数量-->
        <attr name="star_isIndicator" format="boolean" />
        <!--排列方向-->
        <attr name="star_orientation" format="enum">
            <enum name="vertical" value="1" />
            <enum name="horizontal" value="0" />
        </attr>
    </declare-styleable>
  • 2 构造函数中获取自定义属性值
    //星星水平排列
    public static final int HORIZONTAL = 0;
    //星星垂直排列
    public static final int VERTICAL = 1;
    //实心图片
    private Bitmap mSolidBitmap;
    //空心图片
    private Bitmap mHollowBitmap;
    private Context context;
    //最大的数量
    private int starMaxNumber;
    private float starRating;
    private Paint paint;
    private int mSpaceWidth;//星星间隔
    private int mStarWidth;//星星宽度
    private int mStarHeight;//星星高度
    private boolean isIndicator;//是否是一个指示器(用户无法进行更改)
    private int mOrientation;

    public StarBarView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public StarBarView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        paint = new Paint();
        this.context = context;
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.StarBarView, defStyle, 0);
        mSpaceWidth = a.getDimensionPixelSize(R.styleable.StarBarView_space_width, 0);
        mStarWidth = a.getDimensionPixelSize(R.styleable.StarBarView_star_width, 0);
        mStarHeight = a.getDimensionPixelSize(R.styleable.StarBarView_star_height, 0);
        starMaxNumber = a.getInt(R.styleable.StarBarView_star_max, 0);
        starRating = a.getFloat(R.styleable.StarBarView_star_rating, 0);
        mSolidBitmap = getZoomBitmap(BitmapFactory.decodeResource(context.getResources(), a.getResourceId(R.styleable.StarBarView_star_solid, 0)));
        mHollowBitmap = getZoomBitmap(BitmapFactory.decodeResource(context.getResources(), a.getResourceId(R.styleable.StarBarView_star_hollow, 0)));
        mOrientation = a.getInt(R.styleable.StarBarView_star_orientation, HORIZONTAL);
        isIndicator = a.getBoolean(R.styleable.StarBarView_star_isIndicator, false);
        a.recycle();
    }
  • 3 获取图片bitmap,设置宽高
/**
     * 获取缩放图片
     *
     * @param bitmap
     * @return
     */
    public Bitmap getZoomBitmap(Bitmap bitmap) {
        if (mStarWidth == 0 || mStarHeight == 0) {
            return bitmap;
        }
        // 获得图片的宽高
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();

        // 设置想要的大小
        int newWidth = mStarWidth;
        int newHeight = mStarHeight;
        // 计算缩放比例
        float scaleWidth = ((float) newWidth) / width;
        float scaleHeight = ((float) newHeight) / height;
        // 取得想要缩放的matrix参数
        Matrix matrix = new Matrix();
        matrix.postScale(scaleWidth, scaleHeight);
        // 得到新的图片
        Bitmap newbm = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
        return newbm;
    }
  • 4 onMeasure函数测量子控件大小,然后设置当前控件大小
@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (mOrientation == HORIZONTAL) {
            //判断是横向还是纵向,测量长度
            setMeasuredDimension(measureLong(widthMeasureSpec), measureShort(heightMeasureSpec));
        } else {
            setMeasuredDimension(measureShort(widthMeasureSpec), measureLong(heightMeasureSpec));
        }
    }

    private int measureLong(int measureSpec) {
        int result;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        if ((specMode == MeasureSpec.EXACTLY)) {
            result = specSize;
        } else {
            result = (int) (getPaddingLeft() + getPaddingRight() + (mSpaceWidth + mStarWidth) * (starMaxNumber));
            if (specMode == MeasureSpec.AT_MOST) {
                result = Math.min(result, specSize);
            }
        }
        return result;
    }

    private int measureShort(int measureSpec) {
        int result;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        if (specMode == MeasureSpec.EXACTLY) {
            result = specSize;
        } else {
            result = (int) (mStarHeight + getPaddingTop() + getPaddingBottom());
            if (specMode == MeasureSpec.AT_MOST) {
                result = Math.min(result, specSize);
            }
        }
        return result;
    }
  • 5 确定好数据后开始描绘bitmap到Canvas上
@Override
    protected void onDraw(Canvas canvas) {
        if (mHollowBitmap == null || mSolidBitmap == null) {
            return;
        }
        //绘制实心进度
        int solidStarNum = (int) starRating;
        //绘制实心的起点位置
        int solidStartPoint = 0;
        if (mOrientation == HORIZONTAL)
            for (int i = 1; i <= solidStarNum; i++) {
                canvas.drawBitmap(mSolidBitmap, solidStartPoint, 0, paint);
                solidStartPoint = solidStartPoint + mSpaceWidth + mSolidBitmap.getWidth();
            }
        else
            for (int i = 1; i <= solidStarNum; i++) {
                canvas.drawBitmap(mSolidBitmap, 0, solidStartPoint, paint);
                solidStartPoint = solidStartPoint + mSpaceWidth + mSolidBitmap.getHeight();
            }
        //虚心开始位置
        int hollowStartPoint = solidStartPoint;
        //多出的实心部分起点
        int extraSolidStarPoint = hollowStartPoint;
        //虚心数量
        int hollowStarNum = starMaxNumber - solidStarNum;
        if (mOrientation == HORIZONTAL)
            for (int j = 1; j <= hollowStarNum; j++) {
                canvas.drawBitmap(mHollowBitmap, hollowStartPoint, 0, paint);
                hollowStartPoint = hollowStartPoint + mSpaceWidth + mHollowBitmap.getWidth();
            }
        else
            for (int j = 1; j <= hollowStarNum; j++) {
                canvas.drawBitmap(mHollowBitmap, 0, hollowStartPoint, paint);
                hollowStartPoint = hollowStartPoint + mSpaceWidth + mHollowBitmap.getWidth();
            }
        //多出的实心长度
        int extraSolidLength = (int) ((starRating - solidStarNum) * mHollowBitmap.getWidth());
        Rect rectSrc = new Rect(0, 0, extraSolidLength, mHollowBitmap.getHeight());
        Rect dstF = new Rect(extraSolidStarPoint, 0, extraSolidStarPoint + extraSolidLength, mHollowBitmap.getHeight());
        canvas.drawBitmap(mSolidBitmap, rectSrc, dstF, paint);
    }
  • 6 最后通过onTouchEvent方法去监听事件
@Override
    public boolean onTouchEvent(MotionEvent event) {
        if (!isIndicator) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    if (mOrientation == HORIZONTAL) {
                        float TotalWidth = starMaxNumber * (mStarWidth + mSpaceWidth);
                        if (event.getX() <= TotalWidth) {
                            float newStarRating = (int) event.getX() / (mStarWidth + mSpaceWidth) + 1;
                            setStarRating(newStarRating);
                        }
                    }else{
                        float TotalHeight = starMaxNumber * (mStarHeight + mSpaceWidth);
                        if (event.getY() <= TotalHeight) {
                            float newStarRating = (int) event.getY() / (mStarHeight + mSpaceWidth) + 1;
                            setStarRating(newStarRating);
                        }
                    }
                    break;
                case MotionEvent.ACTION_MOVE:
//                    float starTotalWidth = starMaxNumber * (mStarWidth + mSpaceWidth);
//                    if (event.getX() <= starTotalWidth) {
//                        float newStarRating = (int) event.getX() / (mStarWidth + mSpaceWidth) + 1;
//                    setStarRating(newStarRating);
//                    }
                    break;
                case MotionEvent.ACTION_UP:
                    break;
                case MotionEvent.ACTION_CANCEL:
                    break;
            }
        }
        return super.onTouchEvent(event);
    }

如何使用:

  • xml布局
<com.caption.starbarexample.widget.StarBarView
        android:id="@+id/sbv_starbar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:layout_margin="10dp"
        app:space_width="1dp"
        app:star_height="25dp"
        app:star_hollow="@mipmap/ic_star_yellow_normal"
        app:star_isIndicator="false"
        app:star_max="5"
        app:star_orientation="horizontal"
        app:star_rating="2"
        app:star_solid="@mipmap/ic_star_yellow_selected"
        app:star_width="25dp" />
  • 代码添加
    //拿到当前星星数量
    mStarbar.getStarRating();

github:https://github.com/GHdeng/StarBarExample

Android 星级评分条的基本用法 一 、效果如图所示: 布局代码实现: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/t 阅读详情

相关推荐

Android星级评分条设计与实现

本文还有配套的精品资源,点击获取 简介:星级评分条是Android开发中常用的UI元素,用于收集用户反馈。本示例深入探讨了RatingBar的使用方法,包括XML布局声明、属性详解、编程接口、监听评分变化、自定义样式和示例代码。通过本课程,开发者可以掌握RatingBar的实际应用,提升用户体验。 1. Android星级评分条简介 星级评分条是一个常用的控...

weixin_36364707的博客 1482

推荐开源项目:StarRatingView - 简洁易用的Android星星评分视图

推荐开源项目:StarRatingView - 简洁易用的Android星星评分视图 去发现同类优质开源项目:https://gitcode.com/ 在移动应用开发中,给用户提供一种便捷的方式来表达他们的反馈或评价是非常常见的需求。 是一个为 Android 平台设计的轻量级库,它允许开发者快速集成一颗颗闪烁的星星评级视图,为你的应用增添美观且互动性强的评分功能。 项目简介 StarRating...

gitblog_00028的博客 550

Android自定义星星评分控件

http://blog.youkuaiyun.com/a756213932/article/details/51939422 博客详细说明

Android 基础知识4-3.9 RatingBar(星级评分条)详解

RatingBar是基于SeekBar和ProgressBar的扩展,用星型来显示等级评定。使用RatingBar的默认大小时,用户可以触摸/拖动或使用键来设置评分,它有两种样式(小风格用ratingBarStyleSmall,大风格用ratingBarStyleIndicator),其中大的只适合指示,不适合于用户交互。当使用可以支持用户交互的RatingBar时,无论将控件(widgets)放在它的左边还是右边都是不合适的。

yyxhzdm的博客 1757

手把手教你设计STM32的JTAG电路:从原理图到PCB布局(含JLINK连接详解)

本文详细介绍了STM32的JTAG电路设计全流程,从核心原理、接口规范到PCB布局布线技巧,特别包含JLINK调试器的连接与配置方法。通过信号滤波、上拉配置和防反接保护等关键设计要点,帮助开发者构建稳定可靠的JTAG调试环境,提升嵌入式开发效率。

weixin_29159441的博客 390

PCB之AD层次化原理图设计

PCB之AD层次化(模块化)原理图设计 软件版本:AD17.1.9(bBuild 592) 先上效果图: 可以看到,图中有RS485和W5500这两个部分是复用了原理图,当项目中需要多个功能相同的电路时,这种设计就可以大大节约PCB布局布线的时间,方法后面介绍; 1.首先确定好项目中个部分电路的功能模块 不同功能的电路分开不同原理图画,然后给出输入输出端口,这样方便复用,下面是实例项目的功能划分 2.单个模块电路的接口设计 这里以W5500以太网接口电路为例说明: 主要就分为通讯接口和电源接口:

洋洋洋的博客 3万+

推荐开源项目:StarRatingView - 一款优雅的Android评分视图库

推荐开源项目:StarRatingView - 一款优雅的Android评分视图库 在开发Android应用时,我们经常需要实现用户评价或显示商品评分的功能,这时候一个简洁而强大的评级视图组件就显得尤为重要。今天要向大家推荐的是,一个由王超iOS开发并开源的Android星标评级视图库。 项目简介 StarRatingView是一个轻量级、高度可定制的Android库,它允许开发者轻松地添加动态星...

gitblog_00073的博客 597

ClickHouse集群扩容实战:用clickhouse-copier搞定数据迁移与分片重平衡

本文详细介绍了使用clickhouse-copier工具实现ClickHouse集群从3分片到5分片的平滑扩容实战。通过分片级并行处理、原子性保证等核心机制,该工具能高效完成数据迁移与分片重平衡,同时保持服务连续性。文章涵盖集群拓扑规划、表结构检查、迁移配置、执行监控及迁移后优化等关键步骤,为大数据量场景下的ClickHouse扩容提供完整解决方案。

weixin_29091837的博客 294

星星评价控件android开发_android自定义星级评分控件,可实现只显示实心星星

话不多说,上图近日app需求弄一个等级展示,看了下UI图,只显示实星(点亮的星星).如图但是网上关于星级评分的例子大多这样也展示虚心星星通过自定义Viewpackage com.starsbar;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Bitmap;im...

weixin_39865625的博客 238

Aruco标签定位、测距、三维位置估算 opencv应用

摄像头要一开始对准aruco标签才开始运行。+ 相机标定文件(参考我的上篇文章)+ aruco标签6*6。

dgut_guangdian的博客 4222

某勾网之登录过程逆向

拉勾网的登录过程逆向,包含请求头(X-S-HEADER、X-K-HEADER、X-SS-REQ-HEADER等) 以及 请求参数/返回数据的加解密。

shanf7921的博客 3万+

android自定义星级评分控件,可实现只显示实心星星

话不多说,上图 近日app需求弄一个等级展示,看了下UI图,只显示实星(点亮的星星).如图 但是网上关于星级评分的例子大多这样 也展示虚心星星 通过自定义View package com.starsbar; import android.content.Context; import android.content.res.TypedArray; import android.graphic...

每一件自己觉得值得的事都要不留余力的去做 2596

Imagenet数据集1000类别中英文

英文 {0: 'tench, Tinca tinca', 1: 'goldfish, Carassius auratus', 2: 'great white shark, white shark, man-eater, man-eating shark, Carcharodon carcharias', 3: 'tiger shark, Galeocerdo cuvieri', 4: 'hammerhead, hammerhead shark', 5: 'electric ray, cram.

识物专栏 1800

Android学习总结之自定义View实战篇

自定义view的实战篇

2301_80329517的博客 621

跟踪雷达点迹处理

1,点迹定义: 假设研究对象为位置x和速度v,预测值是根据这一时刻的x值、v值来预测下一时刻的x、v;测量值是根据传感器也就是雷达得到的,因为各种误差的存在,这两个值都不准确,所以把他们加权融合,得到一个新的量—状态值。 点迹就是所谓的测量值,由雷达对同一个目标探测到的一系列点(假设目标静止,但由于误差的存在,会扫描出不止一个点),航迹对应状态值,是点迹和预测轨迹的加权融合。 2,雷达信号和点迹处理关系: 3,点迹航迹处理流程 4,仿真 clear all; RealData=G

wangjie36的博客 1万+

135、高通 ChromaTix 调优工具入门:参数含义、调优流程与效果对比

本文介绍了高通ChromaTix色彩调优工具的核心使用要点:1. ChromaTix是位于ISP管线中的色彩处理系统,核心任务是将原始色彩映射为符合人眼感知的"舒适"效果;2. 重点解析了饱和度、色调、亮度相关饱和度等关键参数的实际含义和调试陷阱;3. 分享了四步调优流程,强调需要基于多场景数据验证;4. 通过案例展示了参数调整带来的色彩改善效果;5. 总结了实用建议,包括保持单一变量调试、量化评估色差、关注极端场景表现等。文章指出ChromaTix调优是平衡不同场景需求的"妥协艺术",需要结合客观数据和主

sundong_81的博客 109

安卓评星条_android自定义星级评分控件,可实现只显示实心星星

释放双眼,带上耳机,听听看~!话不多说,上图近日app需求弄一个等级展示,看了下UI图,只显示实星(点亮的星星).如图但是网上关于星级评分的例子大多这样也展示虚心星星通过自定义Viewpackage com.starsbar;import android.content.Context;import android.content.res.TypedArray;import android.gra...

weixin_39805364的博客 230

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Android 自定义星级评分控件

自定义Android 星级评分控件,先上一下效果图 关于控件的制作步骤: 1.首先要确定控件所需要用到的属性,那位作为一个星级评分的控件,能想到的就是大小,形状,数量,评分设置标准,是否允许点击操作,监听等内容,所以我定义了以下属性 public class Star extends View { //星星评分 private float starMark = 0.0F;

z690798364的专栏 3769

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

摸鱼学Android 十二(控件2)

摸鱼学Android 十二UI控制之二1 ProgressBar(进度条)1.1 基本属性1.2 自定义圆形进度条2 SeekBar(拖动条)2.1 基本属性2.2 监听事件3 RatingBar(星级评分条)3.1 基本属性3.2 监听事件3.3 自定义星级图标 UI控制之二 1 ProgressBar(进度条) 1.1 基本属性 max:进度条最大值 progress:当前进度值 progressDrawable:轨道资源图片 indeterminate:设置不确定模式,为true则进度条动画无限循环

qq_23470315的博客 238

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Android开发自学笔记(Android Studio)—4.5 ProgressBar及其子类

一、前言 ProgressBar本身代表了进度条组件,它还派生出了两个常用的组件:SeekBar和RatingBar,他们的使用方法类似,只是显示界面有一定的区别。我们看一下API文档中的说明: 从图中我们是可以直接看到ProgressBar继承自View类,直接子类有AbsSeekBar和ContentLoadingProgressBar,间接子类有RatingBar和Seek...

angdian2335的博客 316

Android程序里加星级评分,Android 自定义星级评分控件

自定义Android 星级评分控件,先上一下效果图 关于控件的制作步骤:1.首先要确定控件所需要用到的属性,那位作为一个星级评分的控件,能想到的就是大小,形状,数量,评分设置标准,是否允许点击操作,监听等内容,所以我定义了以下属性public class Star extends View {//星星评分private float starMark = 0.0F;//星星个数private int...

weixin_29070861的博客 790

Android UI控件学习(二)——星级评分条

Android UI控件学习(二)——星级评分条开篇自述正文——星级评价条实例项目结构具体代码参考运行效果结语 开篇自述 星级评分条与拖动条类似,都允许用户拖动来改变进度,所不同的是,星级评分条通过星星图案表示进度。通常情况下,使用星级评分条表示对某一事物的支持度或某种服务的满意程度等。 因为我上一篇拖动条已经详细介绍过了,这里就简单写了,如果有不懂的,可以先去看一下我上一篇拖动条的那篇文章。 正...

lzfengluo的博客 1005

星级评分条控件

布局代码:完整代码:public class MainActivity extends Activity {    private RatingBar ratingBar;//星级评分条 @Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    se...

Beginniqg 681

安卓评星条_Android实现根据评分添加星级条

简述在仿写豆瓣的时候,发现了根据评分不同,星级数也不同的星级条。百度一搜,发现Android有自带控件UIRatingBar,而iOS得要自己写…好吧,那就写吧。图片素材首先,要准备三张图片,图片如下:空星,半星,全星因为我们可以看到,在豆瓣的评分星级条里,只有空、半、全星,所以只需要准备这3种图片。思路豆瓣的星级条中既有图片,又有文字,所以我们自定义一个继承于UIView的starView。初始...

weixin_39764603的博客 296

android五星菜单,Android获取星级评分的分值

码农公社 210.net.cn210= 102410月24日一个重要的节日--码农(程序员)节效果实现将布局改为LinearLayout,并通过android:orientation="vertical">设置为垂直布局,然后添加一个RatingBar,并通过android:rating="5"设置其星数为5然后再添加一个Button,分别给他们添加Id。xmlns:app="ht...

weixin_36081109的博客 459

HoRain云--Android RatingBar星级评分条使用指南

本文介绍了Android中RatingBar(星级评分条)的基本使用和定制方法。首先讲解了RatingBar的基本属性,包括显示星星数量、默认评分值等,并提供了事件处理的代码示例。随后详细说明了如何自定义评分图标,通过创建layer-list文件和定义style样式,将默认星星替换为自定义表情图标。最后提醒开发者注意图标间距处理,并总结了RatingBar与SeekBar的相似性。文章内容简明实用,适合Android开发者快速掌握RatingBar的使用技巧。

sinat_57153473的博客 841
上一篇: ARGB与RGB、RGBA的区别
下一篇: 使用广播监听网络变化
caption_deng
博客等级 码龄11年 2粉丝 11原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

caption_deng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值