时间选择器PopupWindow
preview
Crazy Coding
implementation
basepopup : 'com.github.razerdp:BasePopup:2.2.20',
PopupWindow
/**
* @ClassName GlobalPopupWindow
* @Description TODO
* @Author Kolin Zhao / Mozhimen
* @Date 2021/12/30 13:54
* @Version 1.0
*/
class PopupWindowTime(context: Context, val onTimeSure: (String) -> Unit) : BasePopupWindow(context) {
private lateinit var btnSure: Button
private lateinit var btnCancel: Button
private lateinit var pickerHour: NumberPicker
private lateinit var pickerMinute: NumberPicker
override fun onCreateContentView(): View {
return createPopupById(R.layout.popup_time)
}
override fun onViewCreated(contentView: View) {
super.onViewCreated(contentView)
pickerHour = findViewById(R.id.popup_time_hour)
pickerMinute = findViewById(R.id.popup_time_minute)
btnSure = findViewById(R.id.popup_time_sure)
btnCancel = findViewById(R.id.popup_time_cancel)
initTimePicker()
btnCancel.setOnClickListener {
this.dismiss()
}
btnSure.setOnClickListener {
val time = convertDiscreteTimeToString(pickerHour.value, pickerMinute.value * 5)
onTimeSure(time)//00:00->hh:mm
this.dismiss()
}
}
private fun initTimePicker() {
val step5Minutes = arrayOf("00", "05", "10", "15", "20", "25", "30", "35", "40", "45", "50", "55")
val formatter = NumberPicker.Formatter { String.format("%02d", it) }
pickerHour.setFormatter(formatter)
pickerMinute.setFormatter(formatter)
pickerHour.minValue = 0
pickerHour.maxValue = 23
pickerMinute.displayedValues = step5Minutes
pickerMinute.minValue = 0
pickerMinute.maxValue = step5Minutes.size - 1
val currentTime = DateUtil.formatDateToString(Date(), DateUtil.format_hhmm)!!.split(":")
Log.d("TAG", "initTimePicker: ${currentTime[0]} ${currentTime[1]}")
val currentHour = currentTime[0].toInt()
val currentMinute = currentTime[1].toInt()
pickerHour.value = currentHour
pickerMinute.value = (currentMinute / 5f).roundToInt()
pickerHour.descendantFocusability = DatePicker.FOCUS_BLOCK_DESCENDANTS
pickerMinute.descendantFocusability = DatePicker.FOCUS_BLOCK_DESCENDANTS
pickerHour.wrapSelectorWheel = false
pickerMinute.wrapSelectorWheel = true
}
private fun convertDiscreteTimeToString(hour: Int, minute: Int): String {
val hourStr = String.format("%02d", hour)
val minuteStr = String.format("%02d", minute)
return "$hourStr:$minuteStr"
}
fun show() {
setPopupAnimationStyle(R.style.PopWindowAnimStyle)
showPopupWindow()
}
}
layout
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:id="@+id/popup_view"
android:layout_width="match_parent"
android:layout_height="480dp"
android:layout_gravity="bottom"
android:background="@drawable/popup_bottom">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="时间选择器"
android:textColor="@color/blue_theme"
android:textSize="@dimen/global_title"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.07"
tools:ignore="HardcodedText" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<NumberPicker
android:id="@+id/popup_time_hour"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/margin_bottom_inner"
android:theme="@style/TimePicker" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/margin_bottom_inner"
android:text=":"
android:textColor="@color/blue_theme"
android:textSize="@dimen/global_title"
android:textStyle="bold"
tools:ignore="HardcodedText" />
<NumberPicker
android:id="@+id/popup_time_minute"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/margin_bottom_inner"
android:theme="@style/TimePicker" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.95">
<Button
android:id="@+id/popup_time_cancel"
style="@style/CancelButton"
android:layout_width="@dimen/btn_width"
android:layout_height="@dimen/btn_height"
android:layout_marginEnd="@dimen/margin_end"
android:text="@string/btn_cancel" />
<Button
android:id="@+id/popup_time_sure"
style="@style/SubmitButton"
android:layout_width="@dimen/btn_width"
android:layout_height="@dimen/btn_height"
android:text="@string/text_sure" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
drawable
- cancel
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke
android:width="2dp"
android:color="@color/gray_theme" />
<corners android:radius="@dimen/btn_corner" />
</shape>
- submit
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="@dimen/btn_corner" />
<solid android:color="@color/blue_theme" />
</shape>
anim
- show
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:duration="500"
android:fillAfter="true"
android:fromAlpha="0"
android:toAlpha="1.0" />
</set>
- exit
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:duration="500"
android:fillAfter="true"
android:fromAlpha="1.0"
android:toAlpha="0.0" />
</set>
dimen
<dimen name="global_title">28sp</dimen>
<dimen name="margin_bottom_inner">20dp</dimen>
<dimen name="btn_width">200dp</dimen>
<dimen name="btn_height">64dp</dimen>
<dimen name="margin_end">16dp</dimen>
<dimen name="btn_text">24sp</dimen>
string
<string name="btn_cancel">取消</string>
<string name="text_sure">确定</string>
color
<color name="blue_theme">#4785EF</color>
style
<!--时间选择器-->
<style name="TimePicker" parent="@android:style/Widget.Material.TimePicker">
<item name="android:textColorPrimary">@color/blue_theme</item>
<item name="colorControlNormal">@color/blue_theme</item>
<item name="android:textSize">22sp</item>
<item name="android:textColor">@color/white</item>
<item name="android:textStyle">bold</item>
<item name="android:scaleX">1.2</item>
<item name="android:scaleY">1.2</item>
</style>
<style name="SubmitButton">
<item name="android:background">@drawable/btn_submit</item>
<item name="android:elevation">2dp</item>
<item name="android:textColor">@color/white</item>
<item name="android:textSize">@dimen/btn_text</item>
</style>
<style name="CancelButton">
<item name="android:background">@drawable/btn_cancel</item>
<item name="android:elevation">2dp</item>
<item name="android:textColor">@color/black</item>
<item name="android:textSize">@dimen/btn_text</item>
</style>
<style name="PopWindowAnimStyle" parent="android:Animation">
<item name="android:windowEnterAnimation">@anim/anim_popup_show</item>
<item name="android:windowExitAnimation">@anim/anim_popup_exit</item>
</style>
How to use
private var popupWindowTime: PopupWindowTime? = null
private fun operateChooseTime(view: View) {
popupWindowTime?.dismiss()
popupWindowTime = PopupWindowTime(requireActivity()) {
//your logic exam:(view as TextView).text = it
}
popupWindowTime!!.show()
}