自提出问题以来已经过去了八年,因此您可能拥有 +8 年的 Android 经验,并且可能能够自己开发所需的数字选择器 :)
无论如何,我遇到了类似的问题并升级了 Android NumberPicker 以满足我的需求。最初的 NumberPicker 远非完美,我的也是如此,但经过一些调整后它对我有用。
使用示例:
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View = LinearLayout(requireContext()).apply {
isBaselineAligned = false
val divider = ColorDrawable(0xFFDBDBDB.toInt()).apply {
// share drawable, don't mind Callback, invalidation etc
setBounds(0, 0, 0, dp2Px(context, 1)) // 1dp dividers
}
val pad = dp2Px(context, 16)
val selectorWheelPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
typeface = ResourcesCompat.getFont(context, R.font.roboto_light)
textSize = sp(22f)
}
val scaleI = TimeInterpolator { cos(3.1415926535897932384f / 2f * it) }
val alphaI = TimeInterpolator { cos(3.1415926535897932384f / 1.5f * it) }
val cmPicker = FlexibleNumberPicker(context).apply {
minValue = 0
maxValue = 1000 // 10 metres is enough, I hope
value = valueMm / 100
setup(divider, selectorWheelPaint, scaleI, alphaI)
setPadding(0, 0, pad, 0)
val cm = resources.getString(R.string.cm)
setFormatter { cm.format(it.toFloat()) }
wrapSelectorWheel = false
setGravity(Gravity.RIGHT)
}
addView(cmPicker, LinearLayout.LayoutParams(0, WRAP_CONTENT, 1f))
addView(FlexibleNumberPicker(context).apply {
minValue = 0
maxValue = 9
value = valueMm % 100
setup(divider, selectorWheelPaint, scaleI, alphaI)
setPadding(pad, 0, 0, 0)
val mm = resources.getString(R.string.mm)
setFormatter { mm.format(it.toFloat()) }
setOnValueChangedListener(cmPicker.fractionListener)
setGravity(Gravity.LEFT)
}, LinearLayout.LayoutParams(0, WRAP_CONTENT, 1f))
}
private fun FlexibleNumberPicker.setup(
divider: ColorDrawable, paint: Paint,
scaleI: TimeInterpolator, alphaI: TimeInterpolator,
) {
setSelectionDivider(divider)
setSelectorWheelPaint(paint)
setWheelItemCount(5)
setDividerOffset(.33f)
setLineHeight(TypedValue.COMPLEX_UNIT_SP, 27f)
solidColor = Color.WHITE
setScaleInterpolator(scaleI)
setAlphaInterpolator(alphaI)
}
val FlexibleNumberPicker.fractionListener: FlexibleNumberPicker.OnValueChangeListener
get() = FlexibleNumberPicker.OnValueChangeListener { picker, oldVal, newVal ->
val min = picker.minValue
val max = picker.maxValue
when {
oldVal == min && newVal == max -> changeValueByOne(false)
oldVal == max && newVal == min -> changeValueByOne(true)
}
}