提问人:Carl Johnson 提问时间:11/8/2023 更新时间:11/8/2023 访问量:20
如何使位置值仅在用户单击某些布局时可选?
How can I make the position value only selectable when user click certain layout?
问:
背景 - 下面是场景,我的应用是 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 的新手,所以我不太清楚在哪里可以看到其他东西。
答: 暂无答案
评论