自定义 View(六) 自定义评分星星

news2024/9/29 5:23:04

先看看效果图
在这里插入图片描述

1.自定义 View 的基本流程

  • 创建 View Class
  • 创建 attr 属性文件,确定属性
  • View Class 绑定 attr 属性
  • onMeasure 测量
  • onDraw 绘制
  • onTouchEvent ( 用户交互需要处理 )

1.1 创建 View Class

package com.example.view_day05_ratingbar;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import androidx.annotation.Nullable;

public class RatingBar extends View {
    private static final String TAG = "wqq";
    private Bitmap mStartNormalBitmap,mStartFocusBitmap;
    private int mGradeNumber = 5;
    private int mCurrentGrade = 0;
    public RatingBar(Context context) {
        this(context, null);
    }

    public RatingBar(Context context, @Nullable @org.jetbrains.annotations.Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RatingBar(Context context, @Nullable @org.jetbrains.annotations.Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray array = context.obtainStyledAttributes(attrs,R.styleable.RatingBar);
        int starNormalID = array.getResourceId(R.styleable.RatingBar_starNormal,0);
        if (starNormalID == 0) {
            throw new RuntimeException("请设置属性 startNormal");
        }

        mStartNormalBitmap = BitmapFactory.decodeResource(getResources(),starNormalID);

        int startFocusId = array.getResourceId(R.styleable.RatingBar_starFocus, 0);
        if (startFocusId == 0) {
            throw new RuntimeException("请设置属性 startFocusId");
        }
        mStartFocusBitmap = BitmapFactory.decodeResource(getResources(), startFocusId);

        mGradeNumber = array.getInt(R.styleable.RatingBar_gradeNumber,0);
        array.recycle();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //高度 一张图片的高度,自己去实现 padding
        int height = mStartNormalBitmap.getHeight();
        int width = mGradeNumber * mStartFocusBitmap.getWidth();
        setMeasuredDimension(width,height);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        for (int i = 0; i < mGradeNumber; i++) {
            int x = i * mStartFocusBitmap.getWidth();
            if (mCurrentGrade > i) {
                canvas.drawBitmap(mStartFocusBitmap,x,0,null);
            } else {
                canvas.drawBitmap(mStartNormalBitmap,x,0,null);
            }
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //移动 按下 抬起 处理逻辑都是一样,判断手指的位置,根据当前位置计算出分数,再去刷新界面显示
        switch(event.getAction()) {
            case MotionEvent.ACTION_DOWN: //按下
            case MotionEvent.ACTION_MOVE: // 移动
            //case MotionEvent.ACTION_UP: // 抬起,up事件可以去掉,优化ondraw调用次数
            float moveX = event.getX(); // event.getX(),获取相对于当前控件的位置;event.getRawX(),获取屏幕的x位置
                Log.e(TAG, "movex: "+ moveX + "event:"+ event.getAction());
                int currentGrade = (int)(moveX/mStartFocusBitmap.getWidth() + 1);
            if (currentGrade < 0) {
                currentGrade = 0;
            }
            if (currentGrade > mGradeNumber) {
                currentGrade = mGradeNumber;
            }
            //相等的话,就不用重复绘制了
            if (currentGrade == mCurrentGrade) {
                return true;
            }
            mCurrentGrade = currentGrade;
            //刷新显示
            invalidate();// 由于ondraw流程很长,尽量减少ondraw的调用,减少内存
                break;
        }
        return true;
    }
}

下篇文字会分析 onTouchEvent 源码,为什么要设置返回 true

1.2 创建 attr

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="RatingBar">
        <!--未选中引用-->
        <attr name="starNormal" format="reference" />
        <!--选中引用-->
        <attr name="starFocus" format="reference" />
        <!--最大的分数-->
        <attr name="gradeNumber" format="integer" />
        <!--当前的分数-->
        <attr name="currentGrade" format="integer" />
        <!--星星之间的间距-->
        <attr name="starPadding" format="dimension" />
    </declare-styleable>
</resources>

1.3 创建图片资源

在\app\src\main\res目录下创建文件夹drawable-xhdpi,将星星图片复制进去。
在这里插入图片描述

1.4 布局文件

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <com.example.view_day05_ratingbar.RatingBar
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:background="@color/purple_200"
        app:starPadding="50dp"
        app:starFocus="@drawable/select"
        app:starNormal="@drawable/start_normal"
        app:gradeNumber="5"/>

</RelativeLayout>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/803681.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LabVIEW实现三相异步电机磁通模型

LabVIEW实现三相异步电机磁通模型 三相异步电动机由于经济和出色的机电坚固性而广泛用于工业化应用。这台机器的设计和驱动非常简单&#xff0c;但在控制扭矩和速度方面&#xff0c;它隐藏了相当大的功能复杂性。通过数学建模&#xff0c;可以理解机器动力学。 基于微分方程的…

day44-Custom Range Slider(自定义范围滑块)

50 天学习 50 个项目 - HTMLCSS and JavaScript day44-Custom Range Slider&#xff08;自定义范围滑块&#xff09; 效果 index.html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewp…

vue中tab隐藏display:none(v-show无效,v-if有效)

目录 背景 原因&#xff1a;display: table-cell>display:none 解决&#xff1a; 方法A.获取元素设置display&#xff08;适用于 简单场景&#xff09; 方法B.自定义tabs​​​​​​​ &#xff08;适用于 复杂场景&#xff09; 背景 内联样式(style“ ”) /this.$…

JVM简述

JDK&JRE&JVMJVM运行时内存结构图方法区堆区栈区程序计数器本地方法栈 JVM 的主要组成部分及其作用 JDK&JRE&JVM JVM就是java虚拟机&#xff0c;一台虚拟的机器&#xff0c;用来运行java代码 但并不是只有这台机器就可以的&#xff0c;java程序在运行时需要依赖…

Linux权限提升:自动化信息收集

在本文中&#xff0c;我们将介绍在基于Linux的设备上进行初始访问后&#xff0c;可用于后渗透阶段漏洞利用和枚举的一些自动化脚本。 ** 介绍** 大多数时候&#xff0c;当攻击者攻击Linux操作系统时&#xff0c;他们将获得基本的Shell&#xff0c;可以将其转换为TTY Shell或m…

apple pencil值不值得购买?便宜的电容笔推荐

如今&#xff0c;对ipad使用者而言&#xff0c;苹果原装的Pencil系列无疑是最佳的电容笔。只是不过这款电容笔的售价&#xff0c;实在是太高了&#xff0c;一般的用户都无法入手。因此&#xff0c;在具体的使用过程中&#xff0c;如何选用一种性能优良、价格低廉的电容笔是非常…

Jmeter+验证json结果是否正确小技巧

前言&#xff1a; 通过sql语句或者返回的参数&#xff0c;可以在查看结果树返回的结果中&#xff0c;用方法先跑一下验证是否取到自己想要的值 步骤&#xff1a; 1、添加查看结果树 2、跑出结果 3、在查看结果树中 text改成选Json Path Tester 返回的值如果是列表里面的字符…

英码“深元”智慧工厂解决方案,提升管理效率,开启生产新时代!

智慧工厂&#xff0c;作为数字化和智能化的代表&#xff0c;深度融合了边缘计算、物联网、大数据分析和人工智能等技术&#xff0c;为传统工厂管理和生产带来了深刻的影响。英码“深元”智慧工厂解决方案&#xff0c;利用智能终端——“深元”AI工作站实时采集传输现场视频&…

8个特别好用的矢量图软件,一定要收藏

在设计工作中&#xff0c;矢量图软件能帮助设计师绘制出具有更高质量&#xff0c;更高清晰度的图画作品。本文整理了市面上8个好用的矢量图软件&#xff0c;一起来看看吧&#xff01; 1、即时灵感 即时灵感是基于云端运行的矢量图软件&#xff0c;完全可以满足运营、产品经理…

荣登央视,智慧集中供冷,未来空调技术的新趋势

我们上了央视了&#xff01;这不是开玩笑也不是蹭热度&#xff0c;最近我们做的一个项目被作为正向报导了&#xff0c;可以说是一件引以为傲的事情&#xff0c;具体涉及的项目&#xff0c;就是作为未来空调技术的集中供冷系统。 今年夏天&#xff0c;想必大家也都感觉到了&…

【phpstudy】Apache切换Nginx报错nginx: [emerg] CreateFile()

【phpstudy】Apache切换Nginx报错nginx: [emerg] CreateFile() 报错内容如下&#xff1a; nginx: [emerg] CreateFile() “D:/phpstudy_pro/WWW/www.xxx.com/nginx.htaccess” failed (2: The system cannot find the file specified) in D:\phpstudy_pro\Extensions\Nginx1.…

【WebGIS实例】(10)Cesium开场效果(场景、相机旋转,自定义图片底图)

效果 漫游效果视频&#xff1a; 【WebGIS实例】&#xff08;10&#xff09;Cesium开场效果&#xff08;场景、相机 点击鼠标后将停止旋转并正常加载影像底图&#xff1a; 代码 可以直接看代码&#xff0c;注释写得应该比较清楚了&#xff1a; /** Date: 2023-07-28 16:21…

接口自动化如何做?接口自动化测试- 正则用例参数化(实例)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 我们在做接口自动…

ElasticSearch基本使用--ElasticSearch文章一

文章目录 官网学习必要性elasticsearch/kibana安装版本数据结构说明7.x版本说明ElasticSearch kibana工具测试后续我们会一起分析 官网 https://www.elastic.co/cn/ 学习必要性 1、在当前软件行业中&#xff0c;搜索是一个软件系统或平台的基本功能&#xff0c; 学习Elastic…

树莓派微型web服务器——阶段设计报告

文章目录 1. 需求分析1.1 功能需求1.1.1 访问需求1.1.2 自定义域名需求1.1.3 下载公共文件需求1.1.4 用户体验需求 1.2 技术需求1.2.1 操作系统指令1.2.2 技术栈1.2.3 内网穿透 1.3 性能需求1.3.1 处理能力1.3.2 内存1.3.3 存储空间 2. 可行性分析2.1 硬件方面2.2 软件方面 3. …

Linux近两年高危漏洞修复过程记录

一、背景 2023年8月份&#xff0c;面对即将到来的“大运会”、“亚运会”&#xff0c;今年的例行安全护网阶段也将迎来新的挑战和时刻&#xff0c;为此相关部门发布了国家级实战攻防演练已进入紧急「备战」时刻&#xff01;这里我们主要说一下Linux OS层面的漏洞处理&#xff0…

STM32 CubeMX 定时器(普通模式和PWM模式)

STM32 CubeMX STM32 CubeMX 定时器&#xff08;普通模式和PWM模式&#xff09; STM32 CubeMXSTM32 CubeMX 普通模式一、STM32 CubeMX 设置二、代码部分STM32 CubeMX PWM模式一、STM32 CubeMX 设置二、代码部分总结 STM32 CubeMX 普通模式 一、STM32 CubeMX 设置 二、代码部分 …

数据库数据恢复-Syabse数据库存储页底层数据杂乱的数据恢复案例

数据库恢复环境&#xff1a; Sybase版本&#xff1a;SQL Anywhere 8.0。 数据库故障&#xff1a; 数据库所在的设备意外断电后&#xff0c;数据库无法启动。 错误提示&#xff1a; 使用Sybase Central连接后报错&#xff1a; 数据库故障分析&#xff1a; 经过北亚企安数据恢复…

【无标题】深圳卫视专访行云创新马洪喜:拥抱AI与云原生,深耕云智一体化创新

人工智能&#xff08;AI&#xff09;是引领新一轮科技革命和产业变革的重要驱动力。因此&#xff0c;深圳出台相关行动方案&#xff0c;统筹设立规模1,000亿元的人工智能基金群&#xff0c;引导产业集聚培育企业梯队&#xff0c;积极打造国家新一代人工智能创新发展试验区和国家…

select、epoll 的快速核心理解

一、 select 最low的就是在用户代码中自旋实现所有阻塞socket的监听。但是每次判断socket是否产生数据&#xff0c;都涉及到用户态到内核态的切换。 于是select改进&#xff1a;将fd_set传入内核态&#xff0c;由内核判断是否有数据返回&#xff1b; 然后最low的只能使用自旋…