如何使位置值仅在用户单击某些布局时可选?

How can I make the position value only selectable when user click certain layout?

提问人:Carl Johnson 提问时间:11/8/2023 更新时间:11/8/2023 访问量:20

问:

背景 - 下面是场景,我的应用是 IOT 应用。在我的应用程序中,有设备计划部分,用户可以通过该部分更改其设备的计划时间。现在,在某些设备计划布局中,我必须创建一个按钮,通过单击该按钮,用户可以删除该计划或在计划布局中编辑他们的计划。当我创建该按钮时,单击它后将出现一个对话框,其中包含“编辑”和“删除”选项。现在,当用户单击“编辑”按钮时,将出现该特定计划的新屏幕或片段屏幕,其中包含该特定计划的更新计划,用户可以从中修改计划时间和设备。

问题 - 现在问题是我上面提到的,为了更好地解释它,这里有代码:

class ScheduleFragment : BaseFragment<FragmentScheduleBinding>() {

    private var schedules = ArrayList<Schedule>()
    private val logUtils = LogUtils(LevelLogger.SCHEDULE_DEVICES)

    override fun setLayoutResource(): Int {
        return R.layout.fragment_schedule
    }

    override fun onViewReady() {
        showProgressDialog(title(R.string.please_wait))

        baseBinding.buttonCreateSchedule.setOnClickListener {
            goCreateSchedule()
        }
    }

    private fun goCreateSchedule() {
        val dashboardScreenObserver = DashboardScreenObserver()
        dashboardScreenObserver.dashboardScreens = DashboardScreens.CREATE_SCHEDULE
        dashboardScreenModuleObserver.dashboardScreenObserver.value =
            dashboardScreenObserver
    }

    private fun initializeRemoveSchedule(position: Int) {
        val schedule = schedules[position]
        val nodeIdList: MutableSet<String> = HashSet()
        val actions: ArrayList<Action> = schedule.actions
        val operation = AppConstants.KEY_OPERATION_REMOVE

        for (i in actions.indices) {
            val nodeId = actions[i].nodeId
            val deviceName = actions[i].device.deviceName
            if (!nodeIdList.contains(nodeId)) {
                nodeIdList.add(nodeId)
                val scheduleJson = JsonObject()
                scheduleJson.addProperty(AppConstants.KEY_ID, schedule.id)
                scheduleJson.addProperty(AppConstants.KEY_OPERATION, operation)
                val schArr = JsonArray()
                schArr.add(scheduleJson)
                val finalBody = JsonObject()
                finalBody.add(AppConstants.KEY_SCHEDULES, schArr)
                val body = JsonObject()
                body.add(AppConstants.KEY_SCHEDULE, finalBody)

                showProgressDialog(title(R.string.progress_update_schedule))

                val apiManager: ApiManager = ApiManager.getInstance(baseContext)
                apiManager.updateParamValue(nodeId, body, object : ApiResponseListener {
                    override fun onSuccess(data: Bundle?) {
                        logUtils.log(
                            LogUtils.line(),
                            "Schedule remove request sent successfully."
                        )

                        baseContext.runOnUiThread {
                            showProgressDialog(title(R.string.please_wait))
                            refreshStateDiscover()
                        }
                    }

                    override fun onResponseFailure(exception: Exception) {
                        errorFound(exception)
                    }

                    override fun onNetworkFailure(exception: Exception) {
                        errorFound(exception)
                    }

                    fun errorFound(exception: Exception) {
                        logUtils.log(
                            LogUtils.line(),
                            "Schedule remove failed. $exception"
                        )
                        if (exception is CloudException) {
                            alertErrorManagement(
                                exception.message!!,
                                "",
                                ErrorObject.EXCEPTION,
                                R.drawable.ic_error_background
                            )
                        } else {
                            val errMsg =
                                getString(R.string.error_schedule_remove) + "\n" + deviceName
                            alertErrorManagement(
                                errMsg,
                                "",
                                ErrorObject.EXCEPTION,
                                R.drawable.ic_error_background
                            )
                        }

                        hideProgressDialog()

                    }
                })
            }
        }
    }

    private fun loadTimeGadgets(
        llTimeGadgets: LinearLayoutCompat,
        tvDeviceStatus: AppCompatTextView,
        schedule: Schedule
    ) {
        llTimeGadgets.removeAllViews()

        val days = schedule.triggers[AppConstants.KEY_DAYS]!!
        if (days == 0) {
            tvDeviceStatus.visibility = View.VISIBLE
            tvDeviceStatus.text = title(R.string.schedule_once)
        } else {
            val rvTimeGadgets = RecyclerView(baseContext)
            rvTimeGadgets.layoutManager = LinearLayoutManager(baseContext, LinearLayoutManager.HORIZONTAL, false)
            llTimeGadgets.addView(rvTimeGadgets)

            tvDeviceStatus.visibility = View.GONE

            val scheduleDays = ArrayList<ScheduleDay>()

            val daysValue = Integer.toBinaryString(days).reversed()

            val daysNames = baseContext.resources.getStringArray(R.array.day)
            for (index in daysValue.indices) {
                if (daysValue[index].toString() == "1") {
                    val scheduleDay = ScheduleDay()
                    scheduleDay.dayName = daysNames[index]
                    scheduleDays.add(scheduleDay)
                }
            }

            val adapter = object : GenericTypeAdapter<ScheduleDay, ScheduleDeviceObserver>(object :
                ScheduleDeviceObserver {
                override fun load(scheduleDay: ScheduleDay) {
                    logUtils.log(
                        levelLogger,
                        LogUtils.line(), "schedules :: ${
                            GsonBuilder().setPrettyPrinting().create().toJson(scheduleDay)
                        }"
                    )

                }

                override fun menu(it: View, schedule: Schedule) {
                    onScheduleMenuOption(it, schedule)
                }

            }) {
                override fun loadHolder(
                    parent: ViewGroup,
                    viewType: Int
                ): GenericViewHolder<ScheduleDay, ScheduleDeviceObserver> {
                    val binding = LayoutDaysBadgeBinding.inflate(
                        LayoutInflater.from(parent.context),
                        parent,
                        false
                    )

                    return object :
                        GenericViewHolder<ScheduleDay, ScheduleDeviceObserver>(binding.root) {

                        override fun loadItems(
                            position: Int,
                            model: ScheduleDay,
                            models: ArrayList<ScheduleDay>,
                            listener: ScheduleDeviceObserver
                        ) {
                            binding.tvBadge.text = model.dayName
                            binding.tvBadge.setStrokeWidth(2f)
                            binding.tvBadge.strokeColor(R.color.white)
                            binding.tvBadge.solidColor(R.color.orange1)


                        }

                    }
                }

            }

            adapter.addRecord(scheduleDays)
            rvTimeGadgets.adapter = adapter
            rvTimeGadgets.post {
                val measureHeight = -(rvTimeGadgets.measuredHeight) / 3
                rvTimeGadgets.addItemDecoration(OverlapItemDecorator(measureHeight))
            }
        }
    }

    override fun onStart() {
        super.onStart()
        if (!EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().register(this)
        }

        refreshStateDiscover()
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onEvent(event: UpdateEvent) {
        logUtils.log(
            LogUtils.line(),
            "Update Event Received : " + event.eventType
        )
        applicationModuleObserver.isManagerInitialize.value = ""
        hideProgressDialog()
        when (event.eventType) {
            AppConstants.UpdateEventType.EVENT_DEVICE_ADDED,
            AppConstants.UpdateEventType.EVENT_DEVICE_REMOVED -> {

            }

            AppConstants.UpdateEventType.EVENT_STATE_CHANGE_UPDATE -> {
                loadSchedules()
            }
            AppConstants.UpdateEventType.EVENT_LOCAL_DEVICE_UPDATE,
            AppConstants.UpdateEventType.EVENT_DEVICE_STATUS_UPDATE -> {
                loadSchedules()
            }
            else -> {

            }
        }
    }

    private fun loadSchedules() {

        schedules.clear()

        for ((key, schedule) in meshApplication.scheduleMap) {
            if (schedule != null) {
                schedules.add(schedule)
            }
        }

        if (schedules.size == 0) {
            var isScheduleDevicesAvailable = false
            for ((key, node) in meshApplication.localEspNode.entries) {
                val services: ArrayList<Service> = node.services
                if (node != null) {
                    for (i in services.indices) {
                        val s: Service = services[i]
                        if (!TextUtils.isEmpty(s.type) && s.type
                                .equals(AppConstants.SERVICE_TYPE_SCHEDULE)
                        ) {
                            isScheduleDevicesAvailable = true
                            break
                        }
                    }
                }
            }

        }

        val adapter = object :
            GenericTypeAdapter<Schedule, ScheduleDeviceObserver>(object : ScheduleDeviceObserver {
                override fun load(scheduleDay: ScheduleDay) {

                }

                override fun menu(it: View, schedule: Schedule) {
                    onScheduleMenuOption(it, schedule)
                }

            }) {
            override fun loadHolder(
                parent: ViewGroup,
                viewType: Int
            ): GenericViewHolder<Schedule, ScheduleDeviceObserver> {
                val binding = LayoutScheduleBinding.inflate(
                    LayoutInflater.from(parent.context),
                    parent,
                    false
                )

                return object : GenericViewHolder<Schedule, ScheduleDeviceObserver>(binding.root) {

                    override fun loadItems(
                        position: Int,
                        schedule: Schedule,
                        models: ArrayList<Schedule>,
                        listener: ScheduleDeviceObserver
                    ) {
                        binding.tvGadgetsGroupName.text = schedule.name
                        binding.ivOnlineDeviceGadgets.isSelected = schedule.isEnabled

                        val days = schedule.triggers[AppConstants.KEY_DAYS]!!
                        val time = time(schedule)
                        logUtils.log(
                            LogUtils.line(),
                            "***********",
                            time,
                            "***********",
                            GsonBuilder().setPrettyPrinting().create().toJson(schedule),
                            "***********",
                            getDaysText(days)
                        )

                        // Display action devices
                        val deviceNames = StringBuilder()
                        val actions: ArrayList<Action> = schedule.actions

                        if (actions.size > 0) {
                            for (i in actions.indices) {
                                val deviceName: String = actions[i].device.userVisibleName
                                if (deviceNames.isNotEmpty()) {
                                    deviceNames.append(", ")
                                }
                                deviceNames.append(deviceName)
                            }
                        }
                        binding.tvOnTimeGadgets.text = deviceNames
                        binding.tvOffTimeGadgets.text = time

                        loadTimeGadgets(binding.llTimeGadgets, binding.tvDeviceStatus, schedule)

                        binding.clMenuDevice.setOnClickListener {
                            listener.menu(it, models[adapterPosition])
                        }

                    }

                    private fun time(schedule: Schedule): String {
                        // Display days and time of schedule
                        val scheduleTimeText = StringBuilder()

                        val triggers = schedule.triggers
                        val allMinutes = triggers[AppConstants.KEY_MINUTES]!!
                        var hour = allMinutes / 60
                        val minutes = allMinutes % 60

                        if (hour < 12) {
                            if (hour == 0) {
                                hour = 12
                            }
                            if (hour < 10) {
                                scheduleTimeText.append("0$hour:")
                            } else {
                                scheduleTimeText.append("$hour:")
                            }
                            if (minutes < 10) {
                                scheduleTimeText.append("0$minutes AM")
                            } else {
                                scheduleTimeText.append("$minutes AM")
                            }
                        } else if (hour == 12) {
                            scheduleTimeText.append("$hour:")
                            if (minutes < 10) {
                                scheduleTimeText.append("0$minutes PM")
                            } else {
                                scheduleTimeText.append("$minutes PM")
                            }
                        } else {
                            hour -= 12
                            if (hour < 10) {
                                scheduleTimeText.append("0$hour:")
                            } else {
                                scheduleTimeText.append("$hour:")
                            }
                            if (minutes < 10) {
                                scheduleTimeText.append("0$minutes PM")
                            } else {
                                scheduleTimeText.append("$minutes PM")
                            }
                        }
                        return scheduleTimeText.toString()
                    }

                    private fun getDaysText(days: Int): String {
                        val daysText = StringBuilder()
                        if (days == 0) {
                            daysText.append(title(R.string.schedule_once))
                        } else {
                            val daysStr = StringBuilder("00000000")
                            val daysValue = Integer.toBinaryString(days)
                            val daysCharValue = daysValue.toCharArray()
                            var j = 7
                            for (i in daysCharValue.size - 1 downTo 0) {
                                daysStr.setCharAt(j, daysCharValue[i])
                                j--
                            }
                            val daysStrValue = daysStr.toString()
                            if (daysStrValue == "01111111" || daysStrValue == "11111111") {
                                daysText.append(title(R.string.schedule_daily))
                            } else if (daysStrValue == "01100000" || daysStrValue == "11100000") {
                                daysText.append(title(R.string.schedule_weekends))
                            } else if (daysStrValue == "00011111" || daysStrValue == "10011111") {
                                daysText.append(title(R.string.schedule_weekdays))
                            } else {
                                val daysNames = baseContext.resources.getStringArray(R.array.days)
                                val chars = daysStrValue.toCharArray()
                                for (i in chars.size - 1 downTo 1) {
                                    if (chars[i] == '1') {
                                        val day = daysNames[i - 1]
                                        if (daysText.isEmpty()) {
                                            daysText.append(title(R.string.schedule_on_day))
                                            daysText.append(" ")
                                            daysText.append(day)
                                        } else {
                                            daysText.append(", $day")
                                        }
                                    }
                                }
                            }
                        }
                        return daysText.toString()
                    }

                }
            }

        }
        adapter.addRecord(schedules)

        baseBinding.flScheduleDevice.removeAllViews()

        if (schedules.size == 0) {
            baseBinding.buttonCreateSchedule.visibility = View.GONE

            val layoutEmpty = LayoutEmptyBinding.inflate(
                LayoutInflater.from(baseContext),
                baseBinding.flScheduleDevice,
                false
            )
            layoutEmpty.btnAdd.text = "Create Schedule"
            layoutEmpty.btnAdd.setOnClickListener {
                goCreateSchedule()
            }

            baseBinding.flScheduleDevice.addView(layoutEmpty.root)

        } else {
            baseBinding.buttonCreateSchedule.visibility = View.VISIBLE

            val rvScheduleDevice = RecyclerView(baseContext)
            rvScheduleDevice.layoutManager = LinearLayoutManager(baseContext)
            rvScheduleDevice.adapter = adapter
            baseBinding.flScheduleDevice.addView(rvScheduleDevice)

            rvScheduleDevice.addItemDecoration(
                dividerItemDecoration(
                    R.color.transparent,
                    RecyclerView.VERTICAL,
                    1,
                    20
                )
            )

        }

    }

    private fun onScheduleMenuOption(it: View, schedule: Schedule) {
        val scheduleOperationFragment = ScheduleOperationFragment(object :
            ScheduleOperationObserver {
                override fun operate(
                    view: View,
                    scheduleOperationOperate: ScheduleOperationOperate,
                    dialogFragment: DialogFragment
                ) {
                    if (scheduleOperationOperate == ScheduleOperationOperate.EDIT) {

                        val schedule = schedules[position]

                        val navOptions = NavOptions.Builder()
                        val bundle = Bundle()
                        bundle.putString(
                            AppConstants.KEY_SCHEDULE,
                            Gson().toJson(schedule)
                        )

                        Navigation.findNavController(
                            baseContext,
                            R.id.childDashboardNavHostFragment
                        ).navigate(
                            R.id.updateScheduleFragment,
                            bundle,
                            navOptions.build()
                        )
                    }

                    if (scheduleOperationOperate == ScheduleOperationOperate.REMOVE) {
                        AlertOperationFragment.showAlertDialog(baseContext,
                            getString(R.string.dialog_title_delete_user),
                            getString(R.string.dialog_msg_confirmation),
                            buttonPositive,
                            buttonNegative,
                            true,
                            object : AlertOperationFragment.AlertObserver {
                                override fun success(dialog: Dialog) {
                                    initializeRemoveSchedule(position)
                                    dialog.dismiss()
                                }

                                override fun close(dialog: Dialog) {
                                    dialog.dismiss()
                                }

                            })
                    }

                }
            }
        )

        scheduleOperationFragment.apply {
            setStyle(DialogFragment.STYLE_NORMAL, R.style.OperateDialog)
        }
        scheduleOperationFragment.show(childFragmentManager, scheduleOperationFragment.tag)

    }

    override fun onPause() {
        super.onPause()
        EventBus.getDefault().unregister(this)
    }

    interface ScheduleOperationObserver {
        fun operate(
            view: View,
            scheduleOperationOperate: ScheduleOperationOperate,
            dialogFragment: DialogFragment
        )
    }

    interface ScheduleDeviceObserver {
        fun load(scheduleDay: ScheduleDay)

        fun menu (it: View, schedule: Schedule)
    }
}

在此代码中,有一个变量位置,用于告诉 schedule 数组中 schedule 的索引值或位置。position 变量在两个函数中使用,initializeRemoveSchedule 和 onScheduleMenuOption。现在我想要的是,当用户单击任何计划布局时,它将特别针对更新的计划布局打开,而不是另一个计划布局。因为如果我创建一个全局变量位置并将其值固定为 0,那么它将仅显示第一个计划布局的更新计划布局,这意味着如果计划数组中有 10 个计划并且用户选择第 5 个计划并尝试编辑它,它将显示第一个设备的更新布局。

我试图查看其他两个文件,例如

ScheduleOperation.kt (英语)

data class ScheduleOperation(
    var title: String,
    var scheduleOperationOperate: ScheduleOperationOperate = ScheduleOperationOperate.REMOVE
)

enum class ScheduleOperationOperate {
    REMOVE,
    EDIT
}

ScheduleOperationFragment.kt

class ScheduleOperationFragment(private var scheduleOperationObserver: ScheduleFragment.ScheduleOperationObserver) : BaseDialogFragment<FragmentScheduleOperationBinding>() {


    private lateinit var mScheduleOperation: ArrayList<ScheduleOperation>

    override fun setLayoutResource(): Int {
        return R.layout.fragment_schedule_operation
    }

    override fun onViewReady() {
        mScheduleOperation = ArrayList()
        mScheduleOperation.add(ScheduleOperation("Edit", ScheduleOperationOperate.EDIT))
        mScheduleOperation.add(ScheduleOperation("Remove", ScheduleOperationOperate.REMOVE))

        val scheduleOperationAdapter = object : GenericTypeAdapter<ScheduleOperation, ScheduleOperationDialogObserver>(
            object : ScheduleOperationDialogObserver {
                override fun operate(
                    view: View,
                    scheduleOperationOperate: ScheduleOperationOperate,
                    dialogFragment: DialogFragment
                ) {
                    scheduleOperationObserver.operate(view, scheduleOperationOperate, dialogFragment)
                }

            }) {
            override fun loadHolder(
                parent: ViewGroup,
                viewType: Int
            ): GenericViewHolder<ScheduleOperation, ScheduleOperationDialogObserver> {
                val layoutScheduleOperation = LayoutScheduleOperationBinding.inflate(
                    LayoutInflater.from(parent.context),
                    parent,
                    false
                )

                return object : GenericViewHolder<ScheduleOperation, ScheduleOperationDialogObserver>(layoutScheduleOperation.root) {
                    override fun loadItems(
                        position: Int,
                        model: ScheduleOperation,
                        models: ArrayList<ScheduleOperation>,
                        listener: ScheduleOperationDialogObserver
                    ) {
                        layoutScheduleOperation.title.text = mScheduleOperation[adapterPosition].title

                        itemView.setOnClickListener {
                            listener.operate(it, mScheduleOperation[adapterPosition].scheduleOperationOperate, this@ScheduleOperationFragment)
                        }
                    }

                }
            }

        }
        scheduleOperationAdapter.addRecord(mScheduleOperation)
        baseDialogBinding.rvScheduleOperation.adapter = scheduleOperationAdapter

        val drawable = ContextCompat.getDrawable(baseContext, R.drawable.ic_vertical_divider)

        val dividerItemDecoration =
            DividerItemDecorator(drawable!!)
        baseDialogBinding.rvScheduleOperation.addItemDecoration(dividerItemDecoration)

    }

    interface ScheduleOperationDialogObserver {
        fun operate(view: View, scheduleOperationOperate: ScheduleOperationOperate, dialogFragment: DialogFragment)
    }

但我在这里没有发现任何错误。我是 Android 的新手,所以我不太清楚在哪里可以看到其他东西。

Kotlin Android-布局 移动开发

评论


答: 暂无答案