NumberPicker分析(一)

news2024/9/24 17:15:33

NumberPicker分析(一)

NumberPicker可实现连续滚动的字符串选择,其实现方式很有借鉴的意义

以最基本的使用方式为例,在layout中布局:

    <NumberPicker
        android:id="@+id/number_picker"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        />

然后设置minValuemaxValue。(当然也可以设置DisplayedValues,这里以最简单的使用方式为例)

mNumberPicker.setMaxValue(4);
mNumberPicker.setMinValue(0);

其显示效果如下:
显示效果
分析下NumberPicker构造方法(源码可参考NumberPicker.java)

mHasSelectorWheel = (layoutResId != DEFAULT_LAYOUT_RESOURCE_ID);

mHasSelectorWheel表示 - 是否具有选择轮
如果在源码处添加一个debug的断点,会发现mHasSelectorWheel结果是true,即表示layoutResId不是DEFAULT_LAYOUT_RESOURCE_IDR.layout.number_picker

通过官方文档对NumberPicker的介绍,可发现其style与主题有关:

  • 如果当前主题是从 R.style.Theme 派生的,则小部件将当前值显示为可编辑的输入字段,上面有一个递增按钮,下面有一个递减按钮。 长按按钮可以快速更改当前值。 点击输入字段允许输入所需的值。
  • 如果当前主题是从 R.style.Theme_HoloR.style.Theme_Holo_Light 派生的,则小部件将当前值显示为可编辑的输入字段,上面的值较小,下面的值较大。 点击较小或较大的值,通过向上或向下动画数字轴来选择它,使所选值成为当前值。 向上或向下滑动允许当前值的多个增量或减量。 长按较小和较大的值也可以快速更改当前值。 点击当前值可以输入所需的值。
  • 如果当前主题是从 R.style.Theme_Material 派生的,则小部件将当前值显示为滚动的垂直选择器,所选值位于中心,前后数字由分隔符分隔。 通过垂直滑动来更改值。 可以使用 R.attr.selectionDividerHeight 属性更改分隔线的厚度,可以使用 R.attr.colorControlNormal 属性更改分隔线的颜色。

在android源码中搜索下number_picker.xml相关的布局(frameworks/base/core/res/res/layout/number_picker.xml)
布局
Holo主题中NumberPicker定义如下(frameworks/base/core/res/res/values/styles_holo.xml)

    <style name="Widget.Holo.NumberPicker" parent="Widget.NumberPicker">
        <item name="internalLayout">@layout/number_picker_with_selector_wheel</item>
        <item name="solidColor">@color/transparent</item>
        <item name="selectionDivider">@drawable/numberpicker_selection_divider</item>
        <item name="selectionDividerHeight">2dip</item>
        <item name="selectionDividersDistance">48dip</item>
        <item name="internalMinWidth">64dip</item>
        <item name="internalMaxHeight">180dip</item>
        <item name="virtualButtonPressedDrawable">?attr/selectableItemBackground</item>
    </style>

internalLayout对应的布局为number_picker_with_selector_wheel
number_picker_with_selector_wheel.xml布局文件内容如下:

<merge xmlns:android="http://schemas.android.com/apk/res/android">

    <view class="android.widget.NumberPicker$CustomEditText"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:id="@+id/numberpicker_input"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:singleLine="true"
        android:background="@null" />

</merge>

可见其中的view,是一个EditText,类型是NumberPicker的内部类CustomEditText
如果点击下上面创建的NumberPicker的中间部分,会弹出键盘编辑值
弹出键盘

setMinValue 和 setMaxValue

setMinValue 方法 和 setMaxValue 方法中逻辑有共通之处

    /**
     * Sets the min value of the picker.
     *
     * @param minValue The min value inclusive.
     *
     * <strong>Note:</strong> The length of the displayed values array
     * set via {@link #setDisplayedValues(String[])} must be equal to the
     * range of selectable numbers which is equal to
     * {@link #getMaxValue()} - {@link #getMinValue()} + 1.
     */
    public void setMinValue(int minValue) {
        if (mMinValue == minValue) {
            return;
        }
        if (minValue < 0) {
            throw new IllegalArgumentException("minValue must be >= 0");
        }
        mMinValue = minValue;
        if (mMinValue > mValue) {
        	//设置了当前值
            mValue = mMinValue;
        }
        updateWrapSelectorWheel();
        initializeSelectorWheelIndices();
        updateInputTextView();
        tryComputeMaxWidth();
        invalidate();
    }

    /**
     * Sets the max value of the picker.
     *
     * @param maxValue The max value inclusive.
     *
     * <strong>Note:</strong> The length of the displayed values array
     * set via {@link #setDisplayedValues(String[])} must be equal to the
     * range of selectable numbers which is equal to
     * {@link #getMaxValue()} - {@link #getMinValue()} + 1.
     */
    public void setMaxValue(int maxValue) {
        if (mMaxValue == maxValue) {
            return;
        }
        if (maxValue < 0) {
            throw new IllegalArgumentException("maxValue must be >= 0");
        }
        mMaxValue = maxValue;
        if (mMaxValue < mValue) {
            mValue = mMaxValue;
        }
        updateWrapSelectorWheel();
        initializeSelectorWheelIndices();
        updateInputTextView();
        tryComputeMaxWidth();
        invalidate();
    }

如都调用量initializeSelectorWheelIndices方法

    /**
     * Resets the selector indices and clear the cached string representation of
     * these indices.
     */
    @UnsupportedAppUsage
    private void initializeSelectorWheelIndices() {
        mSelectorIndexToStringCache.clear();
        int[] selectorIndices = mSelectorIndices;
        int current = getValue();
        for (int i = 0; i < mSelectorIndices.length; i++) {
        	/**
        	* 1.SELECTOR_MIDDLE_ITEM_INDEX表示中间行,总共3行,中间行index就为1
        	* 2.current表示当前值,在上面的初始设置中,即为mMinValue
        	*/
            int selectorIndex = current + (i - SELECTOR_MIDDLE_ITEM_INDEX);
            if (mWrapSelectorWheel) {
            	//处理selectorIndex大于最大值和小于最小值的情况
                selectorIndex = getWrappedSelectorIndex(selectorIndex);
            }
            selectorIndices[i] = selectorIndex;
            ensureCachedScrollSelectorValue(selectorIndices[i]);
        }
    }

    /**
     * @return The wrapped index <code>selectorIndex</code> value.
     */
    private int getWrappedSelectorIndex(int selectorIndex) {
        if (selectorIndex > mMaxValue) {
            return mMinValue + (selectorIndex - mMaxValue) % (mMaxValue - mMinValue) - 1;
        } else if (selectorIndex < mMinValue) {
            return mMaxValue - (mMinValue - selectorIndex) % (mMaxValue - mMinValue) + 1;
        }
        return selectorIndex;
    }

如何理解上面的代码?

mSelectorIndices是一个int数组,我自己的理解,其保存的是页面上从上到下显示的字符串,在数组中对应的索引index
例如在上面设置minValue0maxValue4,可理解要显示的字符串数组为[0, 1, 2, 3, 4]
所以第一次要展示的字符串为[4, 0, 1],其index也对应为[4, 0, 1]

由于是循环滚动,所以如果计算的selectorIndex小于了最小值0, 即表示要从数组[0, 1, 2, 3, 4]逆序寻找,即从maxValue往前去获取
如第一次遍历中,selectorIndex = -1,即从往前maxValue找一个,即为maxValue本身
小于最小值
getWrappedSelectorIndex方法中的

mMaxValue - (mMinValue - selectorIndex) % (mMaxValue - mMinValue) + 1

如果current == 4selectorIndex = 5时,此时selectorIndex超过了最大值4,即表示要从数组[0, 1, 2, 3, 4]正序寻找,从minValue开始寻找

minValue
getWrappedSelectorIndex方法中的

mMinValue + (selectorIndex - mMaxValue) % (mMaxValue - mMinValue) - 1

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

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

相关文章

Visual Studio 2019 C# 上位机入门(1):制作一个简单应用

Visual Studio 2019下载安装步骤可以看&#xff1a;https://blog.csdn.net/weixin_44788542/article/details/114271126 这里不赘述&#xff0c;默认电脑上已经安装好了。 1、打开安装好的Visual Studio后&#xff0c;选择创建新项目。 2、找到选择C#下面的Windows 窗体应用&…

PCIe Protocol Basics

目录 1、PCIe Layered Architecture 2、Packet Movement 3、Simplified Layer Model 4、Layers and Packedt Generation 5、Detailed Layer Model 6、Transaction Layer 7、TransactionLayer Packet 8、TLP Header Overview 9、Data Link Layer 10、Data Link Layer Pa…

Vue 样式绑定

文章目录 Vue 样式绑定Vue classclass 属性绑定数组语法 Vue.js style(内联样式) Vue 样式绑定 Vue class class 与 style 是 HTML 元素的属性&#xff0c;用于设置元素的样式&#xff0c;我们可以用 v-bind 来设置样式属性。 Vue.js v-bind 在处理 class 和 style 时&#x…

php+vue+mysql医院医护人员医生排班系统

本医护人员排班系统管理员&#xff0c;医护。管理员功能有个人中心&#xff0c;医院信息管理&#xff0c;医护信息管理&#xff0c;医护类型管理&#xff0c;排班信息管理&#xff0c;排班类型管理&#xff0c;科室信息管理&#xff0c;投诉信息管理。医护人员可以修改自己的个…

Unity WebGL监听是否进入全屏模式

今天遇到一个需求打包成WebGL之后要当做一个iframe&#xff0c;嵌入到别的网页中&#xff0c;其中遇到两个难题。 1.要增加一个全屏模式。 2.全屏的时候使用unity中的title&#xff0c;非全屏的时候要使用网页本身的title。 全屏一开始使用webkitRequestFullScreen&#xff…

python+vue 家庭理财管理系统

本论文对家庭理财管理系统的发展背景进行详细的介绍&#xff0c;并且对系统开发技术进行介绍&#xff0c;然后对系统进行需求分析&#xff0c;对家庭理财管理系统业务流程、系统结构以及数据都进行详细说明。 1.系统功能完整性&#xff1a;根据系统每一个功能模块&#xff0c;都…

维度云工业品进销存ERP解决行业6大销售痛点

01 销售了多少?成本毛利多少? 如果不使用ERP软件进行管理&#xff0c;则需要手动记录和计算销售额和成本&#xff0c;并根据这些数据手动计算毛利润。这种方法可能会导致错误和时间浪费&#xff0c;并且很难应对规模扩大的情况。因此&#xff0c;通常建议企业使用专业的管理…

jenkins安装(Linux)

文章目录 请谨慎安装最新版本的jenkins1. Jenkins 介绍1.1 jenkins使用场景 2.jenkins下载2.1上传至Linux2.2 rpm安装jenkins2.3 修改jenkins配置2.3.1 修改内容 2.4 开放端口2.5 启动jenkins2.5.1 启动错误2.5.2 添加JAVA_HOME 2.6 jenkins配置添加自定义安装java目录2.7 Erro…

leetCode算法第一天

今天开始刷算法题&#xff0c;提升自己的算法思维和代码能力&#xff0c;加油&#xff01; 文章目录 无重复字符的最长子串最长回文子串N形变换字符串转换整数 无重复字符的最长子串 leetCode链接 https://leetcode.cn/problems/longest-substring-without-repeating-characte…

解决使用Auto-GPT本地部署时无法连接Google的问题和无法连接openai的问题

解决使用Auto-GPT本地部署时无法连接Google的问题 引言 在这篇博客文章中&#xff0c;我们将介绍如何解决使用Auto-GPT本地部署时遇到的无法访问Google的问题。文章的目标受众为编程者和AI工作者。 无法访问Google的问题 在使用Auto-GPT时&#xff0c;可能会遇到无法访问Go…

C++ :Lambda函数的浅学习

文章目录 前言一、lambda函数实例总结 前言 lambda表达式又被称之为lambda函数&#xff0c;是c11的新特性&#xff0c;下面我们看一下lambda表达式的参数等说明&#xff1a; [函数对象参数](操作符重载函数参数)mutable或exception声明->返回值类型{ 函数体 } 下面我们…

EFI Driver Model(下)-USB 驱动设计

1、USB简介 通用串行总线&#xff08;英语&#xff1a;Universal Serial Bus&#xff0c;缩写&#xff1a;USB&#xff09;是一种串口总线标准&#xff0c;也是一种输入输出接口的技术规范&#xff0c;被广泛地应用于个人电脑和移动设备等信息通讯产品&#xff0c;并扩展至摄影…

ZLMediaKit流媒体服务器 RTSP推流时候的堆栈

先直接看图 这是ffmpeg向流媒体服务器推流时候的堆栈 引入C 11之后 堆栈会显得特别繁复冗余 看起来 也没有 以前没有C11之前那样 简单明了 太复杂了 标记下 很多函数名字被我改了 因为原来的看起来 同名函数太多了 C11 和lambada 匿名函数 让看堆栈 成了地狱模式 断点断在…

线程安全和线程不安全之chatgpt理解

对“线程安全”和“线程不安全”&#xff0c;我之前的常规理解是&#xff1a;线程安全&#xff1a;多线程对同一个数据或者容器进行访问或者处理&#xff0c;不会导致数据出现同步问题。线程不安全&#xff1a;多线程对同一个数据或者容器进行访问或者处理&#xff0c;会出现同…

【深度学习】【部署】Flask快速部署深度学习模型【入门】

【深度学习】【部署】Flask快速部署深度学习模型【入门】 提示:博主取舍了很多大佬的博文并亲测有效,分享笔记邀大家共同学习讨论 文章目录 【深度学习】【部署】Flask快速部署深度学习模型【入门】前言搭建简单的Web服务搭建深度学习的Web服务win10下打包成exe(选看)总结 前言…

web后端-请求响应

概述 我们之前在Spring写的 Java类&#xff0c;因为没有继承任何的接口 所以tomcat其实是不识别的&#xff0c;也不能直接运行 但是tomcat识别JavaEE的一项规范-Servlet,因为tomcat就相当于一个Servlet容器 SpringBoot底层提供了一个DisPatcherServlet类(实现了servlet接口)…

C++入门篇(一)

目录 一、C关键字汇总二、命名空间2.1 命名空间的定义2.2 命名空间的使用 三、C的输入和输出四、缺省参数五、函数重载5.1 函数重载的概念5.2 C支持函数重载的原理是什么&#xff1f; 一、C关键字汇总 在C98标准下&#xff0c;C一共有63个关键字&#xff0c;C语言一共有32个关…

第二章 设计模式七大原则

文章目录 前言一、单一职责 &#x1f367;1、单一职责原则注意事项和细节2、代码实现2、1 错误示例2、2 正确示例但有缺陷2、3 最终形态 二、接口隔离原则 &#x1f969;1、代码示例 三、依赖倒转原则 &#x1f965;1、代码示例2、依赖关系传递的三种方式 四、里氏替换原则 &am…

【C 语言】习题 1 - 用代码将二进制转换为十进制

目录 1、缘起 2、算法描述 3、代码清单 4、相关知识点 5、总结 1、缘起 我以前计算二进制转换为十进制的时候&#xff0c;喜欢用笔算&#xff0c;或者电脑在手旁的时候&#xff0c;用电脑自带的程序员计算器进行计算。今天兴起&#xff0c;突然想写一个代码用于计算…

Bootstrap框架实战:轻松搭建响应式网站

Bootstrap 是一款非常受欢迎的前端开发框架&#xff0c;它可以帮助我们轻松地搭建响应式网站。在这篇文章中&#xff0c;我们将介绍如何使用 Bootstrap 框架创建一个简单的响应式网站&#xff0c;并了解其核心概念和组件。 1. Bootstrap 简介 Bootstrap 是由 Twitter 公司的开…