Files
SecurityDefenseDevice/app/src/main/java/com/example/defenseapplication/view/DialogFragment.kt
2026-05-08 16:39:15 +08:00

255 lines
9.9 KiB
Kotlin

package com.example.defenseapplication.view
import android.app.Dialog
import android.os.Bundle
import android.text.InputType
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import android.widget.LinearLayout
import android.widget.EditText
import android.widget.TextView
import androidx.core.os.bundleOf
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.FragmentManager
import com.example.defenseapplication.R
class CustomDialogFragment : androidx.fragment.app.DialogFragment() {
data class Config(
val title: String,
val message: String = "",
val positiveText: String = "确定",
val negativeText: String? = "取消",
val cancelOnTouchOutside: Boolean = true,
val showInput: Boolean = false,
val inputHint: String = "",
val inputText: String = "",
val inputType: Int = InputType.TYPE_CLASS_TEXT
)
private var onPositiveClick: ((String) -> Unit)? = null
private var onNegativeClick: (() -> Unit)? = null
private lateinit var config: Config
fun setOnPositiveClick(block: (String) -> Unit): CustomDialogFragment = apply {
onPositiveClick = block
}
fun setOnNegativeClick(block: () -> Unit): CustomDialogFragment = apply {
onNegativeClick = block
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
config = Config(
title = requireArguments().getString(ARG_TITLE).orEmpty(),
message = requireArguments().getString(ARG_MESSAGE).orEmpty(),
positiveText = requireArguments().getString(ARG_POSITIVE_TEXT).orEmpty(),
negativeText = requireArguments().getString(ARG_NEGATIVE_TEXT),
cancelOnTouchOutside = requireArguments().getBoolean(ARG_CANCEL_ON_TOUCH_OUTSIDE),
showInput = requireArguments().getBoolean(ARG_SHOW_INPUT),
inputHint = requireArguments().getString(ARG_INPUT_HINT).orEmpty(),
inputText = requireArguments().getString(ARG_INPUT_TEXT).orEmpty(),
inputType = requireArguments().getInt(ARG_INPUT_TYPE)
)
isCancelable = config.cancelOnTouchOutside
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return super.onCreateDialog(savedInstanceState).apply {
setCanceledOnTouchOutside(config.cancelOnTouchOutside)
}
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
return inflater.inflate(R.layout.dialog_custom, container, false)
}
override fun onStart() {
super.onStart()
dialog?.window?.let { window ->
window.setLayout(
(resources.displayMetrics.widthPixels * 0.88f).toInt(),
WindowManager.LayoutParams.WRAP_CONTENT
)
window.setBackgroundDrawableResource(android.R.color.transparent)
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val tvTitle = view.findViewById<TextView>(R.id.tv_title)
val tvMessage = view.findViewById<TextView>(R.id.tv_message)
val etInput = view.findViewById<EditText>(R.id.et_input)
val btnNegative = view.findViewById<TextView>(R.id.btn_negative)
val btnPositive = view.findViewById<TextView>(R.id.btn_positive)
val dividerCenter = view.findViewById<View>(R.id.v_divider_center)
tvTitle.text = config.title
tvMessage.text = config.message
tvMessage.visibility = if (config.message.isBlank()) View.GONE else View.VISIBLE
etInput.visibility = if (config.showInput) View.VISIBLE else View.GONE
etInput.hint = config.inputHint
etInput.setText(config.inputText)
etInput.inputType = config.inputType
btnPositive.text = config.positiveText
val hasNegative = !config.negativeText.isNullOrBlank()
btnNegative.visibility = if (hasNegative) View.VISIBLE else View.GONE
dividerCenter.visibility = if (hasNegative) View.VISIBLE else View.GONE
if (hasNegative) {
btnNegative.text = config.negativeText
} else {
btnPositive.layoutParams = LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
}
btnNegative.setOnClickListener {
onNegativeClick?.invoke()
dismissAllowingStateLoss()
}
btnPositive.setOnClickListener {
onPositiveClick?.invoke(etInput.text?.toString().orEmpty())
dismissAllowingStateLoss()
}
}
companion object {
private const val ARG_TITLE = "arg_title"
private const val ARG_MESSAGE = "arg_message"
private const val ARG_POSITIVE_TEXT = "arg_positive_text"
private const val ARG_NEGATIVE_TEXT = "arg_negative_text"
private const val ARG_CANCEL_ON_TOUCH_OUTSIDE = "arg_cancel_on_touch_outside"
private const val ARG_SHOW_INPUT = "arg_show_input"
private const val ARG_INPUT_HINT = "arg_input_hint"
private const val ARG_INPUT_TEXT = "arg_input_text"
private const val ARG_INPUT_TYPE = "arg_input_type"
fun newInstance(config: Config): CustomDialogFragment {
return CustomDialogFragment().apply {
arguments = bundleOf(
ARG_TITLE to config.title,
ARG_MESSAGE to config.message,
ARG_POSITIVE_TEXT to config.positiveText,
ARG_NEGATIVE_TEXT to config.negativeText,
ARG_CANCEL_ON_TOUCH_OUTSIDE to config.cancelOnTouchOutside,
ARG_SHOW_INPUT to config.showInput,
ARG_INPUT_HINT to config.inputHint,
ARG_INPUT_TEXT to config.inputText,
ARG_INPUT_TYPE to config.inputType
)
}
}
}
}
object DefenseDialogs {
private const val DEFAULT_TAG = "custom_dialog_fragment"
fun showDialog(
activity: FragmentActivity,
config: CustomDialogFragment.Config,
tag: String = DEFAULT_TAG,
onPositiveClick: (String) -> Unit = {},
onNegativeClick: () -> Unit = {}
): CustomDialogFragment {
return CustomDialogFragment.newInstance(config)
.setOnPositiveClick(onPositiveClick)
.setOnNegativeClick(onNegativeClick)
.also { it.show(activity.supportFragmentManager, tag) }
}
fun showDialog(
fragment: Fragment,
config: CustomDialogFragment.Config,
tag: String = DEFAULT_TAG,
onPositiveClick: (String) -> Unit = {},
onNegativeClick: () -> Unit = {}
): CustomDialogFragment {
return CustomDialogFragment.newInstance(config)
.setOnPositiveClick(onPositiveClick)
.setOnNegativeClick(onNegativeClick)
.also { it.show(fragment.parentFragmentManager, tag) }
}
fun intrusionAlertConfig(ctx: android.content.Context, deviceName: String, timeText: String): CustomDialogFragment.Config {
return CustomDialogFragment.Config(
title = ctx.getString(R.string.intrusion_alarm),
message = "${timeText}${ctx.getString(R.string.someone_invaded)}\n${deviceName}",
positiveText = ctx.getString(R.string.go_check),
negativeText = ctx.getString(R.string.cancel)
)
}
fun warmPromptConfig(ctx: android.content.Context, deviceName: String, runDays: Int): CustomDialogFragment.Config {
return CustomDialogFragment.Config(
title = ctx.getString(R.string.notice),
message = "${deviceName}${ctx.getString(R.string.device_running_days, runDays)}",
positiveText = ctx.getString(R.string.got_it),
negativeText = null
)
}
fun deviceOfflineConfig(ctx: android.content.Context): CustomDialogFragment.Config {
return CustomDialogFragment.Config(
title = ctx.getString(R.string.device_offline),
message = ctx.getString(R.string.device_offline_message),
positiveText = ctx.getString(R.string.got_it),
negativeText = null
)
}
fun strikeDistanceConfig(ctx: android.content.Context, defaultDistance: String): CustomDialogFragment.Config {
return CustomDialogFragment.Config(
title = ctx.getString(R.string.strike_distance),
message = "",
positiveText = ctx.getString(R.string.confirm),
negativeText = ctx.getString(R.string.cancel),
showInput = true,
inputHint = ctx.getString(R.string.enter_strike_distance),
inputText = defaultDistance,
inputType = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_DECIMAL
)
}
}
fun FragmentActivity.showDefenseDialog(
config: CustomDialogFragment.Config,
tag: String = "custom_dialog_fragment",
onPositiveClick: (String) -> Unit = {},
onNegativeClick: () -> Unit = {}
): CustomDialogFragment {
return DefenseDialogs.showDialog(this, config, tag, onPositiveClick, onNegativeClick)
}
fun Fragment.showDefenseDialog(
config: CustomDialogFragment.Config,
tag: String = "custom_dialog_fragment",
onPositiveClick: (String) -> Unit = {},
onNegativeClick: () -> Unit = {}
): CustomDialogFragment {
return DefenseDialogs.showDialog(this, config, tag, onPositiveClick, onNegativeClick)
}
fun FragmentManager.showDefenseDialog(
config: CustomDialogFragment.Config,
tag: String = "custom_dialog_fragment",
onPositiveClick: (String) -> Unit = {},
onNegativeClick: () -> Unit = {}
): CustomDialogFragment {
return CustomDialogFragment.newInstance(config)
.setOnPositiveClick(onPositiveClick)
.setOnNegativeClick(onNegativeClick)
.also { it.show(this, tag) }
}