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(R.id.tv_title) val tvMessage = view.findViewById(R.id.tv_message) val etInput = view.findViewById(R.id.et_input) val btnNegative = view.findViewById(R.id.btn_negative) val btnPositive = view.findViewById(R.id.btn_positive) val dividerCenter = view.findViewById(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) } }