Merge DialogBuilderFactory with new code style

This commit is contained in:
2022-06-07 16:56:24 +08:00
parent 1a73613cd1
commit 5747fa91ca
7 changed files with 80 additions and 79 deletions

View File

@@ -81,9 +81,9 @@ class ConfigureActivity : BaseActivity<ActivityConfigBinding>() {
} }
/** 设置过滤按钮点击事件 */ /** 设置过滤按钮点击事件 */
binding.configTitleFilter.setOnClickListener { binding.configTitleFilter.setOnClickListener {
showDialog { showDialog<DiaIconFilterBinding> {
title = "按条件过滤" title = "按条件过滤"
val editText = bind<DiaIconFilterBinding>().diaIconFilterInputEdit.apply { binding.iconFiltersEdit.apply {
requestFocus() requestFocus()
invalidate() invalidate()
if (filterText.isNotBlank()) { if (filterText.isNotBlank()) {
@@ -92,8 +92,8 @@ class ConfigureActivity : BaseActivity<ActivityConfigBinding>() {
} }
} }
confirmButton { confirmButton {
if (editText.text.toString().isNotBlank()) { if (binding.iconFiltersEdit.text.toString().isNotBlank()) {
filterText = editText.text.toString().trim() filterText = binding.iconFiltersEdit.text.toString().trim()
refreshAdapterResult() refreshAdapterResult()
} else { } else {
toast(msg = "条件不能为空") toast(msg = "条件不能为空")

View File

@@ -289,7 +289,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
"模块无需保持在后台运行,到达同步时间后会自动启动,如果到达时间后模块正在运行则会自动取消本次计划任务。" "模块无需保持在后台运行,到达同步时间后会自动启动,如果到达时间后模块正在运行则会自动取消本次计划任务。"
confirmButton(text = "保存设置") { confirmButton(text = "保存设置") {
notifyIconAutoSyncTime = it notifyIconAutoSyncTime = it
binding.notifyIconAutoSyncText.text = it this@MainActivity.binding.notifyIconAutoSyncText.text = it
modulePrefs.put(DataConst.NOTIFY_ICON_FIX_AUTO_TIME, it) modulePrefs.put(DataConst.NOTIFY_ICON_FIX_AUTO_TIME, it)
SystemUITool.refreshSystemUI(context, isRefreshCacheOnly = true) SystemUITool.refreshSystemUI(context, isRefreshCacheOnly = true)
} }

View File

@@ -43,14 +43,6 @@ import com.highcapable.yukihookapi.annotation.CauseProblemsApi
import com.highcapable.yukihookapi.hook.factory.method import com.highcapable.yukihookapi.hook.factory.method
import com.highcapable.yukihookapi.hook.type.android.LayoutInflaterClass import com.highcapable.yukihookapi.hook.type.android.LayoutInflaterClass
/**
* 构造对话框
* @param isUseBlackTheme 是否使用深色主题
* @param initiate 对话框方法体
*/
fun Context.showDialog(isUseBlackTheme: Boolean = false, initiate: DialogBuilder.() -> Unit) =
DialogBuilder(context = this, isUseBlackTheme).apply(initiate).show()
/** /**
* 显示时间选择对话框 * 显示时间选择对话框
* @param timeSet 当前时间 - 不写将使用当前时间格式HH:mm * @param timeSet 当前时间 - 不写将使用当前时间格式HH:mm
@@ -59,20 +51,45 @@ fun Context.showDialog(isUseBlackTheme: Boolean = false, initiate: DialogBuilder
fun Context.showTimePicker(timeSet: String = "", result: (String) -> Unit) = fun Context.showTimePicker(timeSet: String = "", result: (String) -> Unit) =
TimePickerDialog(this, { _, h, m -> result("${h.autoZero}:${m.autoZero}") }, timeSet.hour, timeSet.minute, true).show() TimePickerDialog(this, { _, h, m -> result("${h.autoZero}:${m.autoZero}") }, timeSet.hour, timeSet.minute, true).show()
/**
* 构造 [VB] 自定义 View 对话框
* @param initiate 对话框方法体
*/
@JvmName(name = "showDialog-VB")
inline fun <reified VB : ViewBinding> Context.showDialog(initiate: DialogBuilder<VB>.() -> Unit) =
DialogBuilder<VB>(context = this, VB::class.java).apply(initiate).show()
/**
* 构造对话框
* @param initiate 对话框方法体
*/
inline fun Context.showDialog(initiate: DialogBuilder<*>.() -> Unit) = DialogBuilder<ViewBinding>(context = this).apply(initiate).show()
/** /**
* 对话框构造器 * 对话框构造器
* @param context 实例 * @param context 实例
* @param isUseBlackTheme 是否使用深色主题 - 对 AndroidX 风格无效 * @param bindingClass [ViewBinding] 的 [Class] 实例 or null
*/ */
class DialogBuilder(val context: Context, private val isUseBlackTheme: Boolean) { class DialogBuilder<VB : ViewBinding>(val context: Context, private val bindingClass: Class<*>? = null) {
private var instanceAndroidX: androidx.appcompat.app.AlertDialog.Builder? = null // 实例对象 private var instanceAndroidX: androidx.appcompat.app.AlertDialog.Builder? = null // 实例对象
private var instanceAndroid: android.app.AlertDialog.Builder? = null // 实例对象 private var instanceAndroid: android.app.AlertDialog.Builder? = null // 实例对象
private var dialogInstance: Dialog? = null // 对话框实例 private var dialogInstance: Dialog? = null // 对话框实例
private var customLayoutView: View? = null // 自定义布局
@CauseProblemsApi /**
var customLayoutView: View? = null // 自定义布局 * 获取 [DialogBuilder] 绑定布局对象
* @return [VB]
*/
val binding by lazy {
bindingClass?.method {
name = "inflate"
param(LayoutInflaterClass)
}?.get()?.invoke<VB>(LayoutInflater.from(context))?.apply {
customLayoutView = root
} ?: error("This dialog maybe not a custom view dialog")
}
/** /**
* 是否需要使用 AndroidX 风格对话框 * 是否需要使用 AndroidX 风格对话框
@@ -83,12 +100,7 @@ class DialogBuilder(val context: Context, private val isUseBlackTheme: Boolean)
init { init {
if (isUsingAndroidX) if (isUsingAndroidX)
runInSafe { instanceAndroidX = MaterialAlertDialogBuilder(context) } runInSafe { instanceAndroidX = MaterialAlertDialogBuilder(context) }
else runInSafe { else runInSafe { instanceAndroid = android.app.AlertDialog.Builder(context, android.R.style.Theme_Material_Light_Dialog) }
instanceAndroid = android.app.AlertDialog.Builder(
context,
if (isUseBlackTheme) android.R.style.Theme_Material_Dialog else android.R.style.Theme_Material_Light_Dialog
)
}
} }
/** 设置对话框不可关闭 */ /** 设置对话框不可关闭 */
@@ -135,18 +147,6 @@ class DialogBuilder(val context: Context, private val isUseBlackTheme: Boolean)
else customLayoutView?.findViewWithTag<TextView>("progressContent")?.text = value else customLayoutView?.findViewWithTag<TextView>("progressContent")?.text = value
} }
/**
* 设置对话框自定义布局
* @return [ViewBinding]
*/
inline fun <reified T : ViewBinding> bind() =
T::class.java.method {
name = "inflate"
param(LayoutInflaterClass)
}.get().invoke<T>(LayoutInflater.from(context))?.apply {
customLayoutView = root
} ?: error("binding failed")
/** /**
* 设置对话框确定按钮 * 设置对话框确定按钮
* @param text 按钮文本内容 * @param text 按钮文本内容
@@ -184,7 +184,10 @@ class DialogBuilder(val context: Context, private val isUseBlackTheme: Boolean)
fun cancel() = dialogInstance?.cancel() fun cancel() = dialogInstance?.cancel()
/** 显示对话框 */ /** 显示对话框 */
internal fun show() = @CauseProblemsApi
fun show() {
/** 若当前自定义 View 的对话框没有调用 [binding] 将会对其手动调用一次以确保显示布局 */
if (bindingClass != null) binding
if (isUsingAndroidX) runInSafe { if (isUsingAndroidX) runInSafe {
instanceAndroidX?.create()?.apply { instanceAndroidX?.create()?.apply {
customLayoutView?.let { setView(it) } customLayoutView?.let { setView(it) }
@@ -196,8 +199,7 @@ class DialogBuilder(val context: Context, private val isUseBlackTheme: Boolean)
window?.setBackgroundDrawable( window?.setBackgroundDrawable(
GradientDrawable( GradientDrawable(
GradientDrawable.Orientation.TOP_BOTTOM, GradientDrawable.Orientation.TOP_BOTTOM,
if (isUseBlackTheme) intArrayOf(0xFF2D2D2D.toInt(), 0xFF2D2D2D.toInt()) intArrayOf(Color.WHITE, Color.WHITE)
else intArrayOf(Color.WHITE, Color.WHITE)
).apply { ).apply {
shape = GradientDrawable.RECTANGLE shape = GradientDrawable.RECTANGLE
gradientType = GradientDrawable.LINEAR_GRADIENT gradientType = GradientDrawable.LINEAR_GRADIENT
@@ -206,4 +208,5 @@ class DialogBuilder(val context: Context, private val isUseBlackTheme: Boolean)
dialogInstance = this dialogInstance = this
}?.show() }?.show()
} }
}
} }

View File

@@ -78,40 +78,38 @@ object IconRuleManagerTool {
* @param callback 成功后回调 * @param callback 成功后回调
*/ */
fun syncByHand(context: Context, callback: () -> Unit) = fun syncByHand(context: Context, callback: () -> Unit) =
context.showDialog { context.showDialog<DiaSourceFromBinding> {
title = "同步列表" title = "同步列表"
var sourceType = context.modulePrefs.get(DataConst.SOURCE_SYNC_WAY) var sourceType = context.modulePrefs.get(DataConst.SOURCE_SYNC_WAY)
var customUrl = context.modulePrefs.get(DataConst.SOURCE_SYNC_WAY_CUSTOM_URL) var customUrl = context.modulePrefs.get(DataConst.SOURCE_SYNC_WAY_CUSTOM_URL)
bind<DiaSourceFromBinding>().apply { binding.sourceUrlEdit.apply {
diaSfText.apply { if (customUrl.isNotBlank()) {
if (customUrl.isNotBlank()) { setText(customUrl)
setText(customUrl) setSelection(customUrl.length)
setSelection(customUrl.length)
}
doOnTextChanged { text, _, _, _ -> customUrl = text.toString() }
}
diaSfTextLin.isVisible = sourceType == TYPE_SOURCE_SYNC_WAY_3
diaSfRd1.isChecked = sourceType == TYPE_SOURCE_SYNC_WAY_1
diaSfRd2.isChecked = sourceType == TYPE_SOURCE_SYNC_WAY_2
diaSfRd3.isChecked = sourceType == TYPE_SOURCE_SYNC_WAY_3
diaSfRd1.setOnClickListener {
diaSfRd2.isChecked = false
diaSfRd3.isChecked = false
diaSfTextLin.isVisible = false
sourceType = TYPE_SOURCE_SYNC_WAY_1
}
diaSfRd2.setOnClickListener {
diaSfRd1.isChecked = false
diaSfRd3.isChecked = false
diaSfTextLin.isVisible = false
sourceType = TYPE_SOURCE_SYNC_WAY_2
}
diaSfRd3.setOnClickListener {
diaSfRd1.isChecked = false
diaSfRd2.isChecked = false
diaSfTextLin.isVisible = true
sourceType = TYPE_SOURCE_SYNC_WAY_3
} }
doOnTextChanged { text, _, _, _ -> customUrl = text.toString() }
}
binding.sourceFromTextLin.isVisible = sourceType == TYPE_SOURCE_SYNC_WAY_3
binding.sourceRadio1.isChecked = sourceType == TYPE_SOURCE_SYNC_WAY_1
binding.sourceRadio2.isChecked = sourceType == TYPE_SOURCE_SYNC_WAY_2
binding.sourceRadio3.isChecked = sourceType == TYPE_SOURCE_SYNC_WAY_3
binding.sourceRadio1.setOnClickListener {
binding.sourceRadio2.isChecked = false
binding.sourceRadio3.isChecked = false
binding.sourceFromTextLin.isVisible = false
sourceType = TYPE_SOURCE_SYNC_WAY_1
}
binding.sourceRadio2.setOnClickListener {
binding.sourceRadio1.isChecked = false
binding.sourceRadio3.isChecked = false
binding.sourceFromTextLin.isVisible = false
sourceType = TYPE_SOURCE_SYNC_WAY_2
}
binding.sourceRadio3.setOnClickListener {
binding.sourceRadio1.isChecked = false
binding.sourceRadio2.isChecked = false
binding.sourceFromTextLin.isVisible = true
sourceType = TYPE_SOURCE_SYNC_WAY_3
} }
confirmButton { confirmButton {
context.modulePrefs.put(DataConst.SOURCE_SYNC_WAY, sourceType) context.modulePrefs.put(DataConst.SOURCE_SYNC_WAY, sourceType)
@@ -120,15 +118,15 @@ object IconRuleManagerTool {
} }
cancelButton() cancelButton()
neutralButton(text = "自定义规则") { neutralButton(text = "自定义规则") {
context.showDialog { context.showDialog<DiaSourceFromStringBinding> {
title = "自定义规则(调试)" title = "自定义规则(调试)"
val editText = bind<DiaSourceFromStringBinding>().diaSfsInputEdit.apply { binding.jsonRuleEdit.apply {
requestFocus() requestFocus()
invalidate() invalidate()
} }
IconPackParams(context).also { params -> IconPackParams(context).also { params ->
confirmButton(text = "合并") { confirmButton(text = "合并") {
editText.text.toString().also { jsonString -> binding.jsonRuleEdit.text.toString().also { jsonString ->
when { when {
jsonString.isNotBlank() && params.isNotVaildJson(jsonString) -> context.snake(msg = "不是有效的 JSON 数据") jsonString.isNotBlank() && params.isNotVaildJson(jsonString) -> context.snake(msg = "不是有效的 JSON 数据")
jsonString.isNotBlank() -> { jsonString.isNotBlank() -> {
@@ -146,7 +144,7 @@ object IconRuleManagerTool {
} }
} }
cancelButton(text = "覆盖") { cancelButton(text = "覆盖") {
editText.text.toString().also { jsonString -> binding.jsonRuleEdit.text.toString().also { jsonString ->
when { when {
jsonString.isNotBlank() && params.isNotVaildJson(jsonString) -> context.snake(msg = "不是有效的 JSON 数据") jsonString.isNotBlank() && params.isNotVaildJson(jsonString) -> context.snake(msg = "不是有效的 JSON 数据")
jsonString.isNotBlank() -> { jsonString.isNotBlank() -> {

View File

@@ -14,7 +14,7 @@
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<com.google.android.material.textfield.TextInputEditText <com.google.android.material.textfield.TextInputEditText
android:id="@+id/dia_icon_filter_input_edit" android:id="@+id/icon_filters_edit"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:ellipsize="end" android:ellipsize="end"

View File

@@ -20,31 +20,31 @@
android:textSize="14sp" /> android:textSize="14sp" />
<com.google.android.material.radiobutton.MaterialRadioButton <com.google.android.material.radiobutton.MaterialRadioButton
android:id="@+id/dia_sf_rd1" android:id="@+id/source_radio_1"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="从 FastGit 获取" /> android:text="从 FastGit 获取" />
<com.google.android.material.radiobutton.MaterialRadioButton <com.google.android.material.radiobutton.MaterialRadioButton
android:id="@+id/dia_sf_rd2" android:id="@+id/source_radio_2"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="从 Github Raw 获取" /> android:text="从 Github Raw 获取" />
<com.google.android.material.radiobutton.MaterialRadioButton <com.google.android.material.radiobutton.MaterialRadioButton
android:id="@+id/dia_sf_rd3" android:id="@+id/source_radio_3"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="从自定义地址获取" /> android:text="从自定义地址获取" />
<com.google.android.material.textfield.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:id="@+id/dia_sf_text_lin" android:id="@+id/source_from_text_lin"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:visibility="gone"> android:visibility="gone">
<com.google.android.material.textfield.TextInputEditText <com.google.android.material.textfield.TextInputEditText
android:id="@+id/dia_sf_text" android:id="@+id/source_url_edit"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:ellipsize="end" android:ellipsize="end"

View File

@@ -25,7 +25,7 @@
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<com.google.android.material.textfield.TextInputEditText <com.google.android.material.textfield.TextInputEditText
android:id="@+id/dia_sfs_input_edit" android:id="@+id/json_rule_edit"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="150dp" android:layout_height="150dp"
android:ellipsize="end" android:ellipsize="end"