├── .gitignore ├── .idea ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── compiler.xml ├── gradle.xml ├── jarRepositories.xml ├── misc.xml └── vcs.xml ├── .jitpack.yml ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── demo │ │ └── simple │ │ └── picker │ │ ├── BaseActivity.kt │ │ ├── DatePickerActivity.kt │ │ ├── KTX.kt │ │ ├── LogLinearLayoutManager.kt │ │ ├── MainActivity.kt │ │ └── TextPickerActivity.kt │ └── res │ ├── drawable-v24 │ └── ic_launcher_foreground.xml │ ├── drawable │ └── ic_launcher_background.xml │ ├── layout │ ├── activity_date_picker.xml │ ├── activity_main.xml │ ├── activity_text_picker.xml │ ├── dialog_setting.xml │ ├── dialog_to_position.xml │ ├── item_horizontal_picker.xml │ └── item_vertical_picker.xml │ ├── menu │ └── menu_main.xml │ ├── mipmap-anydpi-v26 │ ├── ic_launcher.xml │ └── ic_launcher_round.xml │ ├── mipmap-hdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-mdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ └── values │ ├── colors.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── files ├── gif_date_time_picker.gif ├── gif_picker.gif └── gif_text_picker.gif ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── picker_layoutmanager ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── me │ │ └── simple │ │ └── picker │ │ ├── PickerItemDecoration.kt │ │ ├── PickerLayoutManager.kt │ │ ├── PickerRecyclerView.kt │ │ ├── datepicker │ │ ├── DatePickerView.kt │ │ ├── DayPickerView.kt │ │ ├── MonthPickerView.kt │ │ └── YearPickerView.kt │ │ ├── timepicker │ │ ├── HourPickerView.kt │ │ ├── MinutePickerView.kt │ │ ├── SecondPickerView.kt │ │ └── TimePickerView.kt │ │ ├── utils │ │ ├── CenterHelperLineItemDecoration.kt │ │ └── PickerUtils.kt │ │ └── widget │ │ ├── TextPickerLinearLayout.kt │ │ └── TextPickerView.kt │ └── res │ ├── layout │ └── item_text_picker.xml │ └── values │ └── attrs.xml └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 123 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 19 | 20 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | 29 | 30 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | 13 | 14 | 15 | 16 | 18 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.jitpack.yml: -------------------------------------------------------------------------------- 1 | jdk: 2 | - openjdk11 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Peng Chen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PickerLayoutManager 2 | 3 | [![](https://jitpack.io/v/simplepeng/PickerLayoutManager.svg)](https://jitpack.io/#simplepeng/PickerLayoutManager) 4 | 5 | 一个基于自定义LayoutManager的PickerView,扩展自由度极高。 6 | 7 | ![gif_picker.gif](https://i.loli.net/2020/09/07/RBNdOF64fsCuj5U.gif) 8 | 9 | ## 导入依赖 10 | 11 | ```groovy 12 | maven { url 'https://www.jitpack.io' } 13 | ``` 14 | 15 | ```groovy 16 | implementation 'com.github.simplepeng:PickerLayoutManager:v1.0.4' 17 | ``` 18 | 19 | ## 如何使用 20 | 21 | 直接将`PickerLayoutManager`设置给`RecyclerView`即可,`Adapter`完全自定义化。 22 | 23 | ```kotlin 24 | val pickerLayoutManager = PickerLayoutManager(PickerLayoutManager.VERTICAL) 25 | recyclerView.layoutManager = pickerLayoutManager 26 | recyclerView.adapter = Adapter() 27 | ``` 28 | 29 | `PickerLayoutManager`支持的构造参数属性 30 | 31 | * orientation:摆放子View的方向,默认为VERTICAL 32 | * visibleCount:显示多少个子View,默认为3,切只支持设置奇数 33 | * isLoop:是否支持无限滚动,默认为false 34 | * scaleX:x轴缩放的比例,默认为1.0f 35 | * scaleY:y轴缩放的比例,默认为1.0f 36 | * alpha:未选中item的透明度,默认为1.0f 37 | 38 | ## 监听选中 39 | 40 | ```kotlin 41 | pickerLayoutManager.addOnItemSelectedListener { position -> 42 | toast(position.toString()) 43 | } 44 | ``` 45 | 46 | ## 监听选中和取消选中时itemView被填充的回调 47 | 48 | ```kotlin 49 | pickerLayoutManager.addOnItemFillListener(object : PickerLayoutManager.OnItemFillListener { 50 | override fun onItemSelected(itemView: View, position: Int) { 51 | val tvItem = itemView.findViewById(R.id.tv_item) 52 | tvItem.setTextColor(Color.RED) 53 | } 54 | 55 | override fun onItemUnSelected(itemView: View, position: Int) { 56 | val tvItem = itemView.findViewById(R.id.tv_item) 57 | tvItem.setTextColor(Color.BLUE) 58 | } 59 | }) 60 | ``` 61 | 62 | 这个方法超级有用,可以实现选中和取消选中itemView的自定义化,下面的几个扩展View都使用到了这个方法回调。 63 | 64 | ## 设置分割线 65 | 66 | 分割线基于`ItemDecoration`实现,给RecyclerView添加`PickerItemDecoration`即可。 67 | 68 | ```kotlin 69 | recyclerView.addItemDecoration(PickerItemDecoration()) 70 | ``` 71 | 72 | `PickerItemDecoration`支持`color`,`size`,`margin`等构造参数。 73 | 74 | ## 基于PickerLayoutManager实现的扩展View 75 | 76 | ### TextPickerView 77 | 78 | ![gif_text_picker.gif](https://i.loli.net/2020/09/07/pUMW5o4TKBGlY9R.gif) 79 | 80 | 这个实现相对简单,就自定义了一个item layout为TextView的Adapter而已,再做了一点自定义属性的封装。 81 | 82 | #### 支持的属性和方法 83 | 84 | **`注意:`在调用自定义属性的方法后,必须重新调用`resetLayoutManager()`方法才会起作用。** 85 | 86 | | 属性 | 方法 | 注释 | 87 | | ------------------- | ------------- | ---- | 88 | | visibleCount | setVisibleCount | 显示多少个子View | 89 | | isLoop | setIsLoop | 是否支持无限滚动 | 90 | | scaleX | setItemScaleX | x轴缩放的比例 | 91 | | scaleY | setItemScaleY | y轴缩放的比例 | 92 | | alpha | setItemAlpha | 未选中item的透明度 | 93 | | dividerVisible | setDividerVisible | 分割线是否可见 | 94 | | dividerColor | setDividerColor | 分割线的颜色 | 95 | | dividerSize | setDividerSize | 分割线的大小 | 96 | | dividerMargin | setDividerMargin | 分割线的边距 | 97 | | selectedTextColor | setSelectedTextColor | 文字选中的颜色 | 98 | | unSelectedTextColor | setUnSelectedTextColor | 文字未选中的颜色 | 99 | | selectedTextSize | setSelectedTextSize | 文字选中的大小 | 100 | | unSelectedTextSize | setUnSelectedTextSize | 文字未必选中的大小 | 101 | | selectedIsBold | setSelectedIsBold | 文字选中是否加粗 | 102 | | ~~scrollToEnd~~ | scrollToEnd() | 是否滚动到底部 | 103 | 104 | #### 如何使用 105 | 106 | 在布局中添加TextPickerView 107 | 108 | ```xml 109 | 116 | ``` 117 | 118 | 设置数据源 119 | 120 | ```kotlin 121 | val items = mutableListOf() 122 | for (index in 0 until 100) { 123 | items.add(index.toString()) 124 | } 125 | 126 | textPickerView.setData(items) 127 | ``` 128 | 129 | ### DataPickerView和TimePickerView 130 | 131 | ![gif_date_time_picker.gif](https://i.loli.net/2020/09/07/vREh2qdQi1HpgYj.gif) 132 | 133 | #### 支持的属性和方法 134 | 135 | 同上面的`TextPickerView` 136 | 137 | #### 如何使用 138 | 139 | ```xml 140 | 148 | 149 | 156 | ``` 157 | 158 | #### 设置数据源 159 | 160 | ```kotlin 161 | //默认从1949-1-1到当前这天 162 | datePickerView.setDateInterval() 163 | //滚动到当前日期,不可与`scrollToEnd`同时使用 164 | datePickerView.scrollToCurrentDate() 165 | datePickerView.selectedTodayItem() 166 | 167 | //默认从0点到24点 168 | timerPickerView.setTimeInterval() 169 | ``` 170 | 171 | #### 监听选中 172 | 173 | ```kotlin 174 | datePickerView.setOnDateSelectedListener { year, month, day -> 175 | tvDate.text = "$year-$month-$day" 176 | } 177 | 178 | timePickerView.setOnTimeSelectedListener { hour, minute -> 179 | tvTime.text = "$hour:$minute" 180 | } 181 | ``` 182 | 183 | ## 版本迭代 184 | 185 | * v1.0.5:fix:`getScale`方法 186 | * v1.0.4:解决`visibleCount = 1`不能滑动的问题 187 | * v1.0.3:解决`TextPickerView`设置`isBold`频繁requestLayout的问题 188 | * v1.0.2:`DatePickerView`增加`scrollTodayItem`,`scrollEndItem`等方法,丰富api调用 189 | * v1.0.1:修复`itemCount=1`且`isLoop=true`闪退的bug,`DatePickerView`增加`scrollToCurrentDate`的方法。 190 | * v1.0.0:首次上传 -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.application' 3 | id 'kotlin-android' 4 | } 5 | 6 | android { 7 | compileSdk 30 8 | 9 | defaultConfig { 10 | applicationId "demo.simple.pickerlayoutmanager" 11 | minSdk 16 12 | targetSdk 30 13 | versionCode 1 14 | versionName "1.0" 15 | 16 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 17 | 18 | viewBinding { 19 | enabled = true 20 | } 21 | } 22 | 23 | buildTypes { 24 | release { 25 | minifyEnabled false 26 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 27 | } 28 | } 29 | 30 | compileOptions { 31 | sourceCompatibility JavaVersion.VERSION_1_8 32 | targetCompatibility JavaVersion.VERSION_1_8 33 | } 34 | 35 | kotlinOptions { 36 | jvmTarget = '1.8' 37 | } 38 | } 39 | 40 | dependencies { 41 | implementation 'androidx.core:core-ktx:1.3.2' 42 | implementation 'androidx.appcompat:appcompat:1.2.0' 43 | implementation 'com.google.android.material:material:1.3.0' 44 | implementation 'androidx.constraintlayout:constraintlayout:2.0.4' 45 | testImplementation 'junit:junit:4.+' 46 | androidTestImplementation 'androidx.test.ext:junit:1.1.2' 47 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' 48 | 49 | // implementation project(path: ':picker_layoutmanager') 50 | implementation 'com.github.simplepeng:PickerLayoutManager:v1.0.5' 51 | } 52 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/java/demo/simple/picker/BaseActivity.kt: -------------------------------------------------------------------------------- 1 | package demo.simple.picker 2 | 3 | import android.widget.Toast 4 | import androidx.appcompat.app.AppCompatActivity 5 | 6 | open class BaseActivity : AppCompatActivity() { 7 | 8 | 9 | fun toast(text:String?){ 10 | Toast.makeText(this,text,Toast.LENGTH_SHORT).show() 11 | } 12 | } -------------------------------------------------------------------------------- /app/src/main/java/demo/simple/picker/DatePickerActivity.kt: -------------------------------------------------------------------------------- 1 | package demo.simple.picker 2 | 3 | import android.graphics.Color 4 | import android.graphics.Typeface 5 | import android.os.Bundle 6 | import android.util.Log 7 | import android.view.View 8 | import android.widget.TextView 9 | import demo.simple.picker.databinding.ActivityDatePickerBinding 10 | import me.simple.picker.PickerLayoutManager 11 | import me.simple.picker.widget.TextPickerLinearLayout 12 | import java.text.SimpleDateFormat 13 | import java.util.* 14 | 15 | class DatePickerActivity : BaseActivity(), PickerLayoutManager.OnItemFillListener { 16 | 17 | private val binding by lazy { ActivityDatePickerBinding.inflate(this.layoutInflater) } 18 | 19 | val TAG = "DatePickerActivity" 20 | val dfDate = SimpleDateFormat("yyyy-MM-dd_HH:mm:ss", Locale.getDefault()) 21 | 22 | override fun onCreate(savedInstanceState: Bundle?) { 23 | super.onCreate(savedInstanceState) 24 | setContentView(binding.root) 25 | 26 | // initPickerViewStyle(datePickerView) 27 | // initPickerViewStyle(timePickerView) 28 | 29 | initDatePicker() 30 | initTimePicker() 31 | initListener() 32 | } 33 | 34 | private fun initDatePicker() { 35 | binding.datePickerView.setOnDateSelectedListener { year, month, day -> 36 | Log.d(TAG, "date = $year-$month-$day") 37 | binding.tvDate.text = "$year-$month-$day" 38 | } 39 | binding.datePickerView.setOnDateSelectedListener { calendar -> 40 | val format = dfDate.format(calendar.time) 41 | Log.d(TAG, "calendar = $format") 42 | } 43 | 44 | // datePickerView.setDateInterval( 45 | // 1949, 1, 1, 46 | // 2030, 1, 1 47 | // ) 48 | // datePickerView.selectedEndItem() 49 | binding.datePickerView.selectedTodayItem() 50 | 51 | binding.btnDatePickerScrollTo.setOnClickListener { 52 | val year = 2020 53 | val month = 2 54 | val day = 15 55 | 56 | val calendar = Calendar.getInstance().apply { 57 | set(year, month - 1, day) 58 | } 59 | 60 | binding.datePickerView.selectedTodayItem() 61 | // datePickerView.setSelectedItem(calendar) 62 | // datePickerView.setSelectedItem(year, month, day) 63 | } 64 | 65 | binding.btnSelectedEndItem.setOnClickListener { 66 | binding.datePickerView.selectedEndItem() 67 | } 68 | } 69 | 70 | private fun initTimePicker() { 71 | binding.timePickerView.setOnTimeSelectedListener { hour, minute -> 72 | binding.tvTime.text = "$hour:$minute" 73 | Log.d(TAG, "time = $hour:$minute") 74 | } 75 | binding.timePickerView.setOnTimeSelectedListener { calendar -> 76 | val format = dfDate.format(calendar.time) 77 | Log.d(TAG, "calendar = $format") 78 | } 79 | } 80 | 81 | private fun initListener() { 82 | binding.btnGetDate.setOnClickListener { 83 | 84 | val dateArr = binding.datePickerView.getYearMonthDay() 85 | val timeArr = binding.timePickerView.getTime() 86 | 87 | val year = dateArr[0] 88 | val month = dateArr[1] 89 | val day = dateArr[2] 90 | 91 | val hour = timeArr[0] 92 | val minute = timeArr[1] 93 | 94 | val date = "$year-$month-$day" 95 | val time = "$hour:$minute" 96 | 97 | binding.tvDate.text = date 98 | binding.tvTime.text = time 99 | 100 | toast("$date $time") 101 | } 102 | } 103 | 104 | private fun initPickerViewStyle(pickerView: TextPickerLinearLayout) { 105 | pickerView.run { 106 | setVisibleCount(5) 107 | setIsLoop(true) 108 | setItemScaleX(0.75f) 109 | setItemScaleY(0.75f) 110 | setItemAlpha(0.75f) 111 | 112 | setSelectedTextColor(Color.RED) 113 | setUnSelectedTextColor(Color.GREEN) 114 | setSelectedTextSize(16f.dp) 115 | setUnSelectedTextSize(12f.dp) 116 | setSelectedIsBold(true) 117 | 118 | setDividerVisible(true) 119 | setDividerSize(2f.dp) 120 | setDividerColor(Color.RED) 121 | setDividerMargin(10f.dp) 122 | 123 | resetLayoutManager() 124 | } 125 | pickerView.addOnItemFillListener(this) 126 | } 127 | 128 | override fun onItemSelected(child: View, position: Int) { 129 | val tv = child as TextView 130 | tv.setTextColor(Color.RED) 131 | tv.textSize = 15f 132 | tv.typeface = Typeface.DEFAULT_BOLD 133 | } 134 | 135 | override fun onItemUnSelected(child: View, position: Int) { 136 | val tv = child as TextView 137 | tv.setTextColor(Color.BLUE) 138 | tv.textSize = 11f 139 | tv.typeface = Typeface.DEFAULT 140 | } 141 | } -------------------------------------------------------------------------------- /app/src/main/java/demo/simple/picker/KTX.kt: -------------------------------------------------------------------------------- 1 | package demo.simple.picker 2 | 3 | import android.content.res.Resources 4 | 5 | val Float.dp: Float 6 | get() = Resources.getSystem().displayMetrics.density * this + 0.5f -------------------------------------------------------------------------------- /app/src/main/java/demo/simple/picker/LogLinearLayoutManager.kt: -------------------------------------------------------------------------------- 1 | package demo.simple.picker 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import android.util.Log 6 | import androidx.recyclerview.widget.LinearLayoutManager 7 | import androidx.recyclerview.widget.RecyclerView 8 | 9 | class LogLinearLayoutManager : LinearLayoutManager { 10 | 11 | private val TAG = "LogLinearLayoutManager" 12 | 13 | constructor(context: Context?) : super(context) 14 | constructor(context: Context?, orientation: Int, reverseLayout: Boolean) : super( 15 | context, 16 | orientation, 17 | reverseLayout 18 | ) 19 | 20 | constructor( 21 | context: Context?, 22 | attrs: AttributeSet?, 23 | defStyleAttr: Int, 24 | defStyleRes: Int 25 | ) : super(context, attrs, defStyleAttr, defStyleRes) 26 | 27 | override fun onLayoutChildren(recycler: RecyclerView.Recycler?, state: RecyclerView.State?) { 28 | super.onLayoutChildren(recycler, state) 29 | 30 | Log.d(TAG, "onLayoutChildren") 31 | } 32 | 33 | override fun isAutoMeasureEnabled(): Boolean { 34 | // return false 35 | return super.isAutoMeasureEnabled() 36 | } 37 | } -------------------------------------------------------------------------------- /app/src/main/java/demo/simple/picker/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package demo.simple.picker 2 | 3 | import android.annotation.SuppressLint 4 | import android.content.Intent 5 | import android.os.Bundle 6 | import android.view.* 7 | import android.widget.CheckBox 8 | import android.widget.EditText 9 | import android.widget.RadioGroup 10 | import android.widget.TextView 11 | import androidx.appcompat.app.AlertDialog 12 | import androidx.recyclerview.widget.RecyclerView 13 | import demo.simple.picker.databinding.ActivityMainBinding 14 | import me.simple.picker.PickerItemDecoration 15 | import me.simple.picker.PickerLayoutManager 16 | 17 | @SuppressLint("NotifyDataSetChanged") 18 | class MainActivity : BaseActivity() { 19 | 20 | private val binding by lazy { ActivityMainBinding.inflate(this.layoutInflater) } 21 | 22 | private val mItems = mutableListOf() 23 | 24 | override fun onCreate(savedInstanceState: Bundle?) { 25 | super.onCreate(savedInstanceState) 26 | setContentView(binding.root) 27 | 28 | // startActivity(Intent(this, DatePickerActivity::class.java)) 29 | // startActivity(Intent(this, TextPickerActivity::class.java)) 30 | 31 | for (i in 0..29) { 32 | mItems.add(i.toString()) 33 | } 34 | 35 | initLinearPicker() 36 | 37 | binding.btnNotify.setOnClickListener { 38 | for (i in 0..10) { 39 | mItems.removeAt(mItems.size - 1) 40 | } 41 | binding.recyclerView.adapter?.notifyDataSetChanged() 42 | } 43 | } 44 | 45 | private fun initLinearPicker() { 46 | val pickerLayoutManager = PickerLayoutManager( 47 | PickerLayoutManager.VERTICAL, visibleCount = 7, isLoop = false, 48 | scaleX = 0.9f, scaleY = 0.9f 49 | ) 50 | // val pickerLayoutManager = LinearLayoutManager( 51 | // this@MainActivity, 52 | // LinearLayoutManager.VERTICAL, 53 | // false 54 | // ) 55 | setListener(pickerLayoutManager) 56 | binding.recyclerView.run { 57 | layoutManager = pickerLayoutManager 58 | adapter = PickerAdapter(pickerLayoutManager.orientation) 59 | } 60 | binding.recyclerView.addItemDecoration(PickerItemDecoration()) 61 | } 62 | 63 | private fun setListener(pickerLayoutManager: PickerLayoutManager) { 64 | pickerLayoutManager.addOnItemSelectedListener { position -> 65 | toast(position.toString()) 66 | } 67 | // pickerLayoutManager.addOnItemFillListener(object : PickerLayoutManager.OnItemFillListener { 68 | // override fun onItemSelected(itemView: View, position: Int) { 69 | // val tvItem = itemView.findViewById(R.id.tv_item) 70 | // tvItem.setTextColor(Color.RED) 71 | // } 72 | // 73 | // override fun onItemUnSelected(itemView: View, position: Int) { 74 | // val tvItem = itemView.findViewById(R.id.tv_item) 75 | // tvItem.setTextColor(Color.BLUE) 76 | // } 77 | // }) 78 | } 79 | 80 | inner class PickerAdapter(private val orientation: Int) : 81 | RecyclerView.Adapter() { 82 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) 83 | : PickerViewHolder { 84 | val layoutId = if (orientation == PickerLayoutManager.HORIZONTAL) { 85 | R.layout.item_horizontal_picker 86 | } else { 87 | R.layout.item_vertical_picker 88 | } 89 | return PickerViewHolder( 90 | LayoutInflater.from(this@MainActivity) 91 | .inflate(layoutId, parent, false) 92 | ) 93 | } 94 | 95 | override fun getItemCount(): Int { 96 | return mItems.size 97 | } 98 | 99 | override fun onBindViewHolder(holder: PickerViewHolder, position: Int) { 100 | holder.tvItem.text = mItems[position] 101 | } 102 | 103 | } 104 | 105 | inner class PickerViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { 106 | val tvItem = itemView.findViewById(R.id.tv_item)!! 107 | } 108 | 109 | override fun onCreateOptionsMenu(menu: Menu): Boolean { 110 | menuInflater.inflate(R.menu.menu_main, menu) 111 | return true 112 | } 113 | 114 | override fun onOptionsItemSelected(item: MenuItem): Boolean { 115 | when (item.itemId) { 116 | // R.id.menu_setting -> { 117 | // showSettingDialog() 118 | // } 119 | R.id.menu_scroll_to -> { 120 | showToPositionDialog() 121 | } 122 | R.id.menu_date_picker -> { 123 | startActivity(Intent(this, DatePickerActivity::class.java)) 124 | } 125 | R.id.menu_text_picker -> { 126 | startActivity(Intent(this, TextPickerActivity::class.java)) 127 | } 128 | else -> { 129 | } 130 | } 131 | return true 132 | } 133 | 134 | private fun showSettingDialog() { 135 | val dialog = AlertDialog.Builder(this) 136 | .setView(R.layout.dialog_setting) 137 | .show() 138 | 139 | val rgOrientation = dialog.findViewById(R.id.rgOrientation)!! 140 | val etVisibleCount = dialog.findViewById(R.id.etVisibleCount)!! 141 | val cbIsLoop = dialog.findViewById(R.id.cbIsLoop)!! 142 | dialog.findViewById(R.id.btnOk)!!.setOnClickListener { 143 | dialog.dismiss() 144 | 145 | } 146 | } 147 | 148 | private fun showToPositionDialog() { 149 | val dialog = AlertDialog.Builder(this) 150 | .setView(R.layout.dialog_to_position) 151 | .show() 152 | val etPosition = dialog.findViewById(R.id.etToPosition)!! 153 | 154 | dialog.findViewById(R.id.btnToPosition)!!.setOnClickListener { 155 | dialog.dismiss() 156 | val position = etPosition.text.toString().toInt() 157 | binding.recyclerView.scrollToPosition(position) 158 | } 159 | dialog.findViewById(R.id.btnSmoothToPosition)!!.setOnClickListener { 160 | dialog.dismiss() 161 | val position = etPosition.text.toString().toInt() 162 | binding.recyclerView.smoothScrollToPosition(position) 163 | } 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /app/src/main/java/demo/simple/picker/TextPickerActivity.kt: -------------------------------------------------------------------------------- 1 | package demo.simple.picker 2 | 3 | import android.os.Bundle 4 | import demo.simple.picker.databinding.ActivityTextPickerBinding 5 | 6 | class TextPickerActivity : BaseActivity() { 7 | 8 | private val binding by lazy { ActivityTextPickerBinding.inflate(this.layoutInflater) } 9 | 10 | override fun onCreate(savedInstanceState: Bundle?) { 11 | super.onCreate(savedInstanceState) 12 | setContentView(binding.root) 13 | 14 | val items = mutableListOf() 15 | for (index in 0 until 100) { 16 | items.add(index.toString()) 17 | } 18 | 19 | binding.textPickerView.setData(items) 20 | 21 | // textPickerView.run { 22 | // setVisibleCount(5) 23 | // setIsLoop(true) 24 | // setSelectedIsBold(true) 25 | // setSelectedTextColor(Color.RED) 26 | // 27 | // resetLayoutManager() 28 | // } 29 | } 30 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_date_picker.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 16 | 17 | 25 | 26 |