{"id":13643285,"url":"https://github.com/Carbs0126/NumberPickerView","last_synced_at":"2025-04-21T01:32:17.082Z","repository":{"id":50224618,"uuid":"62104107","full_name":"Carbs0126/NumberPickerView","owner":"Carbs0126","description":"another NumberPicker with more flexible attributes on Android platform","archived":false,"fork":false,"pushed_at":"2021-07-09T06:17:15.000Z","size":1880,"stargazers_count":1172,"open_issues_count":28,"forks_count":263,"subscribers_count":32,"default_branch":"master","last_synced_at":"2024-11-09T15:42:25.041Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Carbs0126.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-06-28T02:38:47.000Z","updated_at":"2024-10-17T09:16:11.000Z","dependencies_parsed_at":"2022-09-24T08:54:19.019Z","dependency_job_id":null,"html_url":"https://github.com/Carbs0126/NumberPickerView","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Carbs0126%2FNumberPickerView","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Carbs0126%2FNumberPickerView/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Carbs0126%2FNumberPickerView/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Carbs0126%2FNumberPickerView/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Carbs0126","download_url":"https://codeload.github.com/Carbs0126/NumberPickerView/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249982600,"owners_count":21355731,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-02T01:01:45.203Z","updated_at":"2025-04-21T01:32:15.296Z","avatar_url":"https://github.com/Carbs0126.png","language":"Java","readme":"# NumberPickerView\n[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-NumberPickerView-green.svg?style=true)](https://android-arsenal.com/details/1/3817)\n##### Another NumberPicker with more flexible attributes on Android platform\n\n[Chinese][6]\n\n## Forewords\nsome android projects use the android.widget.NumberPicker to provide alternative choices, but the default style of `NumberPicker` has some inflexible attibutes, and complicated to be customized.This NumberPickerView extends from View, and provide a friendly experience.\n\n### ScreenShot\n\n![Example Image][4]\u003cbr\u003e\npicking an item dynamically\n\n![Example Image][5]\u003cbr\u003e\n\n![Example Image][2]\u003cbr\u003e\n\n![Example Image][3]\u003cbr\u003e\na small project powered by NumberPickerView, a view which can pick or jump to a certain date with two modes, in Gregorian mode or in Chinese Lunar mode. The gif seem to be a little lag, but actually it runs smoothly. Check the project here:\nhttps://github.com/Carbs0126/GregorianLunarCalendar\n\n### Introduction\n\n`NumberPickerView`extends from `View` and has almost all functions of `android.widget.NumberPicker` except inputting fuction by EditText, but it has some advanced features, here are these two views' differences below:\n\n#### Features of android.widget.NumberPicker\n1. the NumberPicker's viewport can only show three items;\n2. the value of friction is big, you can not pick a new value smoothly by fling;\n3. no animation if you use setValue() in java code to set to a new value;\n4. no animation if you use setDisplayValues() to change the content of NumberPicker;\n5. has a bug if you set wrap mode by using `setWrapSelectorWheel()`, sometimes NumberPicker will not refresh canvas after setWrapSelectorWheel() until it receive a new MotionEvent;\n6. no text hint at the center position;\n7. cannot control NumberPicker to smoothly scroll to a certain item (position);\n8. NumberPicker class in early version of some customized framework has bugs when changing maxValue and displayedValues.\n\n#### Capabilities of NumberPickerView\n1. the NumberPickerView's viewport can show more than three items;\n2. able to set the value of friction in java code, you can pick a new value smoothly by fling, in java code, you can use the code below to make friction be twice as former\u003cbr\u003e `mNumberPickerView.setFriction(2 * ViewConfiguration.get(mContext).getScrollFriction());`\n3. items' texts has animation between selected mode and normal mode, including Gradient textColor and Gradient textSize;\n4. able to choose if use animation when changing displayedValues;\n5. able to setWrapSelectorWheel() dynamically in java code or in xml;\n6. able to set a hint text at the center position, default is empty; can change the hint text's color and textSize;\n7. able to scroll smoothly to a centain item (position);\n8. support `wrap_content` mode,support item's padding\n9. has some other attibutes to refine UI\n10. not respond `onValueChanged()` during scrolling\n11. press the certain item, NumberPickerView will scroll to this item automatically\n12. you can set if the `onValueChanged` callbacks invoked in main thread or in sub thread;\n13. NumberPickerView has some same compatible fuctions and interfaces with NumberPicker, this makes it easier to change NumberPicker to NumberPickerView in project:\n```java\n    //compatible fuctions\n    setOnValueChangedListener()\n    setOnScrollListener()\n    setDisplayedValues()/getDisplayedValues()\n    setWrapSelectorWheel()/getWrapSelectorWheel()\n    setMinValue()/getMinValue()\n    setMaxValue()/getMaxValue()\n    setValue()/getValue()\n\n    //compatible interfaces\n    OnValueChangeListener\n    OnScrollListener\n```\n\n### How to use\n\n1.import to project\n```groovy\n    implementation 'cn.carbswang.android:NumberPickerView:1.2.0'\n```\nor\n```xml\n    \u003cdependency\u003e\n      \u003cgroupId\u003ecn.carbswang.android\u003c/groupId\u003e\n      \u003cartifactId\u003eNumberPickerView\u003c/artifactId\u003e\n      \u003cversion\u003e1.2.0\u003c/version\u003e\n      \u003ctype\u003epom\u003c/type\u003e\n    \u003c/dependency\u003e\n```\n2.add a NumberPickerView in xml\n```xml\n    \u003ccn.carbswang.android.numberpickerview.library.NumberPickerView\n        android:id=\"@+id/picker\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"240dp\"\n        android:layout_centerHorizontal=\"true\"\n        android:layout_marginTop=\"20dp\"\n        android:background=\"#11333333\"\n        android:contentDescription=\"test_number_picker_view\"\n        app:npv_RespondChangeOnDetached=\"false\"\n        app:npv_ItemPaddingHorizontal=\"5dp\"\n        app:npv_ItemPaddingVertical=\"5dp\"\n        app:npv_ShownCount=\"5\"\n        app:npv_TextSizeNormal=\"16sp\"\n        app:npv_TextSizeSelected=\"20sp\"\n        app:npv_WrapSelectorWheel=\"true\"/\u003e\n\n```\n3.control NumberPickerView in Java code\n  1)if the displayedValues in NumberPickerView will NOT change, you can set data by this way: (same as using NumberPicker)\n```java\n        picker.setMinValue(minValue);\n        picker.setMaxValue(maxValue);\n        picker.setValue(value);\n```\n  2)if the displayedValues in NumberPickerView will change, you can set data by this way: (same as using NumberPicker)\n```java\n        int minValue = getMinValue();\n        int oldMaxValue = getMaxValue();\n        int oldSpan = oldMaxValue - minValue + 1;\n        int newMaxValue = display.length - 1;\n        int newSpan = newMaxValue - minValue + 1;\n        if (newSpan \u003e oldSpan) {\n            setDisplayedValues(display);\n            setMaxValue(newMaxValue);\n        } else {\n            setMaxValue(newMaxValue);\n            setDisplayedValues(display);\n        }\n```\nOR use NumberPickerView's method: \u003cbr\u003e\n    `refreshByNewDisplayedValues(String[] display)`\u003cbr\u003e\nbut make sure the minValue will NOT change before and after using this method, and `display` should not be null, and its length should be greater than 0.\n\n4.NumberPickerView also have methods to scroll smoothly \u003cbr\u003e\n    `public void smoothScrollToValue(int fromValue, int toValue, boolean needRespond)`\u003cbr\u003e\n\nthe same point between this method and `setValue(int)`is you can set the current picked item dynamically, the difference is this method can make `NumberPickerView` scroll smoothly from `fromValue` to `toValue` by choosing short distance, the third argument `needRespond` is a boolean flag used to set if you want NumberPickerView invoke its `onValueChanged` callback when scrolling finished this time, because if several `NumberPickerView`s have interconnections, the early stopped `NumberPickerView` invoking callbacks will effect the latter stopped ones. So you can set this flag to be false to avoid invoking `onValueChanged` callback this time. \u003cbr\u003e\n\nand you'd better not use this method in `onCreate(Bundle savedInstanceState)`, if have to do this, you can use in this way:\n\n```java\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        //some code ...\n        mNumberPickerView.post(new Runnable() {\n            @Override\n            public void run() {\n                //call smoothScrollToValue()\n            }\n        });\n    }\n```\n\n5.introduction of attibutes in xml\n```xml\n    \u003cdeclare-styleable name=\"NumberPickerView\"\u003e\n        \u003cattr name=\"npv_ShownCount\" format=\"reference|integer\" /\u003e//the count of shown items , default is 3\n        \u003cattr name=\"npv_ShowDivider\" format=\"reference|boolean\" /\u003e//if show dividers\n        \u003cattr name=\"npv_DividerColor\" format=\"reference|color\" /\u003e//color of two dividers\n        \u003cattr name=\"npv_DividerMarginLeft\" format=\"reference|dimension\" /\u003e//divider's margin to the left\n        \u003cattr name=\"npv_DividerMarginRight\" format=\"reference|dimension\" /\u003e//divider's margin to the right\n        \u003cattr name=\"npv_DividerHeight\" format=\"reference|dimension\" /\u003e//divider's height\n        \u003cattr name=\"npv_TextColorNormal\" format=\"reference|color\" /\u003e//unselected textColor\n        \u003cattr name=\"npv_TextColorSelected\" format=\"reference|color\" /\u003e//selected textColor\n        \u003cattr name=\"npv_TextColorHint\" format=\"reference|color\" /\u003e//hint text color (the text in the center item)\n        \u003cattr name=\"npv_TextSizeNormal\" format=\"reference|dimension\" /\u003e//unselected textSize\n        \u003cattr name=\"npv_TextSizeSelected\" format=\"reference|dimension\" /\u003e//selected textColor\n        \u003cattr name=\"npv_TextSizeHint\" format=\"reference|dimension\" /\u003e//hint text size\n        \u003cattr name=\"npv_TextArray\" format=\"reference\" /\u003e//displayedValues\n        \u003cattr name=\"npv_MinValue\" format=\"reference|integer\" /\u003e//minValue, see as setMinValue()\n        \u003cattr name=\"npv_MaxValue\" format=\"reference|integer\" /\u003e//maxValue, see as setMaxValue()\n        \u003cattr name=\"npv_WrapSelectorWheel\" format=\"reference|boolean\" /\u003e//if set wrap mode, see as setWrapSelectorWheel(boolean)\n        \u003cattr name=\"npv_HintText\" format=\"reference|string\" /\u003e//hint text\n        \u003cattr name=\"npv_EmptyItemHint\" format=\"reference|string\" /\u003e//empty item's text,only shown when WrapSelectorWheel==false or displayedValues length not large than showCount\n        \u003cattr name=\"npv_MarginStartOfHint\" format=\"reference|dimension\" /\u003e//distance between hint and the right side of the max wide text in displayedValues\n        \u003cattr name=\"npv_MarginEndOfHint\" format=\"reference|dimension\" /\u003e//distance between hint and the right side of the view\n        \u003cattr name=\"npv_ItemPaddingHorizontal\" format=\"reference|dimension\" /\u003e//item's horizontal padding, used for wrap_content mode\n        \u003cattr name=\"npv_ItemPaddingVertical\" format=\"reference|dimension\" /\u003e//item's vertical padding, used for wrap_content mode\n        \u003cattr name=\"npv_RespondChangeOnDetached\" format=\"reference|boolean\" /\u003e//for reusable `Dialog/PopupWindow`.\n        \u003cattr name=\"npv_SelectedItemBackground\" format=\"reference\" /\u003e//for selected item background.\n        //If `Dialog/PopupWindow` is hiding meanwhile `NumberPickerView` is still scrolling, then we need it to stop scrolling \n        //and respond (or not) `OnValueChange` callbacks and change the previous picked value. \n        //Add a new attr `npv_RespondChangeOnDetached` as a flag to set if respondding `onValueChange` callbacks, \n        //mainly for multi linked NumberPickerViews to correct other NumberPickerView's position or value.\n        //But I highly recommend every time showing a `Dialog/PopupWindow` please set certain data for NumberPickerView, \n        //and set `npv_RespondChangeOnDetached` false to avoid respondding `onValueChange` callbacks. \n        //See dialog in my `GregorianLunarCalendar` project. \n\n        \u003cattr name=\"npv_RespondChangeInMainThread\" format=\"reference|boolean\" /\u003e//set if the `onValueChanged` callbacks invoked \n        // in mainThread or in subThread, default is true, in mainThread. set it false if you want to run `onValueChanged` in \n        // subThread.\n\n    //these attibutes below are used under wrap_content mode, \n    //and if you want to change displayedValues with out making NumberPickerView changing its original position(four points of this view), \n    //then you should added these attrs to set a max width\n        \u003c!--just used to measure maxWidth for wrap_content without hint,\n            the string array will never be displayed.\n            you can set this attr if you want to keep the wraped numberpickerview\n            width unchanged when alter the content list--\u003e\n        \u003cattr name=\"npv_AlternativeTextArrayWithMeasureHint\" format=\"reference\" /\u003e//represents the maxWidth of displayedValues item plus hint width, including hint, the maxWidth used in onMeasure fuction must equal or be larger than this\n        \u003cattr name=\"npv_AlternativeTextArrayWithoutMeasureHint\" format=\"reference\" /\u003e//represents the maxWidth of displayedValues item, exclude hint text.\n        \u003c!--the max length of hint content--\u003e\n        \u003cattr name=\"npv_AlternativeHint\" format=\"reference|string\" /\u003e//represents the maxWidth of hint text\n    \u003c/declare-styleable\u003e\n\n```\n\n\u003cbr\u003e\n\n### Version\n\n#### 1.2.0\n1.merge some pull requests\u003cbr\u003e\n2.delete some dependence in library\u003cbr\u003e\n\u003cbr\u003e\n#### 1.1.0\n1.refine the duration of position rewising\u003cbr\u003e\n2.refine the interval of sending refreshing message\u003cbr\u003e\n3.refine the sample's UI\u003cbr\u003e\n\u003cbr\u003e\n#### 1.0.9\n1.add attr `app:npv_RespondChangeInMainThread=\"true\"` to set if the `onValueChanged` callbacks invoked in mainThread or in subThread, default is true, in mainThread. set it false if you want to run `onValueChanged` in subThread.\n2.update `TimePickerActivity` example, to give a How-To-Use of `app:npv_RespondChangeInMainThread=\"true\"`.\n3.fix bug: when change displayed values, if it is scrolling, then the new displayed values' position is not rewised\u003cbr\u003e\n\u003cbr\u003e\n#### 1.0.8\n1.modify method `stopScrolling`, add scroll to current Y method before `abortAnimation()` is invoked \u003cbr\u003e\n2.modify `npv_RespondChangeOnDetached`'s default value to false\u003cbr\u003e\n\u003cbr\u003e\n#### 1.0.7\n1.refine code in `onDetachToWindow()` to respond callbacks or not, for reusable `Dialog/PopupWindow`. \u003cbr\u003eIf `Dialog/PopupWindow` is hiding meanwhile `NumberPickerView` is still scrolling, then we need it to stop scrolling and respond (or not) `OnValueChange` callbacks and change the previous picked value. \u003cbr\u003eAdd a new attr `npv_RespondChangeOnDetached` as a flag to set if respondding `onValueChange` callbacks, mainly for multi linked NumberPickerViews to correct other NumberPickerView's position or value.\u003cbr\u003e\nBut I highly recommend every time showing a `Dialog/PopupWindow` please set certain data for NumberPickerView, and set `npv_RespondChangeOnDetached` false to avoid respondding `onValueChange` callbacks. See dialog in my `GregorianLunarCalendar` project. \u003cbr\u003eThese codes are not elegant, If you have any idea, please let me know, thank you.\u003cbr\u003e\n\u003cbr\u003e\n#### 1.0.6\n1.add code in `onDetachToWindow()` to respond callbacks, for reusable `Dialog/PopupWindow`.\u003cbr\u003e\n\u003cbr\u003e\n#### 1.0.5\n1.in method `onAttachToWindow()`, add code to judge if `mHandlerThread`has been `quit()`, this is to avoid of 'can not correct position when show the same Dialog(or PopupWindow) twice '\u003cbr\u003e\n\u003cbr\u003e\n#### 1.0.4\n1.modify some attrs' name\u003cbr\u003e\n\u003cbr\u003e\n#### 1.0.3\n1.fix bug : cannot scroll in `ScrollView`. Thanks Elektroktay's and anjiao's issues\u003cbr\u003e\n\u003cbr\u003e\n\n\n### Mechanisms\n\n#### 1.how to generate scrolling animation\n`Scroller` + `VelocityTracker` + `onDraw(Canvas canvas)`\n\n#### 2.how to correct position automatically when scrolling finished\n`Handler` refresh current position\n\n#### 3.how to generate Gradient effection\nby calculating the current coordinate, get the items which should be shown and the positions of each shown items, comparing the positions and center coordinate of NumberPickerView, get the current color and size of item's text\u003cbr\u003e\n\u003cbr\u003e\n### how to CHANGE NumberPicker to NumberPickerView\n\njust modify `NumberPicker` text into `NumberPickerView` in java code and xml, keep the methods and interfaces called by NumberPicker the same.\u003cbr\u003e\n\n### And something important\u003cbr\u003e\nUI design inspired by Meizu company, a mobile phone Manufacturer in china. \u003cbr\u003e\nA big thanks to google and meizu\u003cbr\u003e\n\n\nenjoy\u003cbr\u003e\n\n## License\n\n    Copyright 2016 Carbs.Wang (NumberPickerView)\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n\n[1]: https://github.com/Carbs0126/Screenshot/blob/master/numberpickerview.gif\n[2]: https://github.com/Carbs0126/Screenshot/blob/master/numberpickerviewall.jpg\n[3]: https://github.com/Carbs0126/Screenshot/blob/master/gregorian_refine.gif\n[4]: https://github.com/Carbs0126/Screenshot/blob/master/numberpickerview_refine1.gif\n[5]: https://github.com/Carbs0126/Screenshot/blob/master/numberpickerview_refine2.gif\n[6]: https://github.com/Carbs0126/NumberPickerView/blob/master/README_ch.md\n","funding_links":[],"categories":["选择器(Picker)"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FCarbs0126%2FNumberPickerView","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FCarbs0126%2FNumberPickerView","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FCarbs0126%2FNumberPickerView/lists"}