Я разрабатываю приложение, которое отображает список аудио -клипов. Я использую Recyclerview с списком. Я реализовал функцию режима выбора, где пользователи могут выбрать несколько элементов. Тем не менее, я сталкиваюсь с основной проблемой в режиме выбора, каждый элемент в переработке должен отображать флажок (определенный в clip_item.xml), чтобы разрешить выбор. Тем не менее, флажок остается невидимым, несмотря на то, что он устанавливает его видимость для просмотра. Видимо в ClipAdapter, когда IsseLectionMode является TRUE.
Я попробовал обновить Recyclerview с помощью notifyDatasetchAnted () и uppertist () , но проблема сохраняется. Функция устанавливает isselectionmode true и попытки отобразить inding.customsearchView, установив его видимость для просмотра. Visible < /code>.
Несмотря на это, CustomSearchView (edittext) не появляется на экране. Проблема: флажок не появляется
in clipadapter, когда IsseLectionMode True, я скрываю ImageView MotionOptions и показываю SelectionCheckbox. < /P>
Я попытался придумать обновление, позвонив по спискам () < /код>, когда IsseLectionMode изменился, но это не помогло. clip_item.xml
Я разрабатываю приложение, которое отображает список аудио -клипов. Я использую Recyclerview с списком. Я реализовал функцию режима выбора, где пользователи могут выбрать несколько элементов. Тем не менее, я сталкиваюсь с основной проблемой в режиме выбора, каждый элемент в переработке должен отображать флажок (определенный в clip_item.xml), чтобы разрешить выбор. Тем не менее, флажок остается невидимым, несмотря на то, что он устанавливает его видимость для просмотра. Видимо в ClipAdapter, когда IsseLectionMode является TRUE. Я попробовал обновить Recyclerview с помощью notifyDatasetchAnted () и uppertist () , но проблема сохраняется. Функция устанавливает isselectionmode true и попытки отобразить inding.customsearchView, установив его видимость для просмотра. Visible < /code>. Несмотря на это, CustomSearchView (edittext) не появляется на экране. Проблема: флажок не появляется in clipadapter, когда IsseLectionMode True, я скрываю ImageView MotionOptions и показываю SelectionCheckbox. < /P> Я попытался придумать обновление, позвонив по спискам () < /код>, когда IsseLectionMode изменился, но это не помогло. [b] clip_item.xml [/b] [code]
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ClipViewHolder { val binding = ClipItemBinding.inflate(LayoutInflater.from(parent.context), parent, false) return ClipViewHolder(binding) }
override fun onBindViewHolder(holder: ClipViewHolder, position: Int) { val clip = getItem(position) Log.d("ClipAdapter", "Binding item at position $position: ${clip.title}") holder.bind(clip) }
inner class ClipViewHolder( private val binding: ClipItemBinding ): RecyclerView.ViewHolder(binding.root) {
companion object { val ClipDiffCallback = object : DiffUtil.ItemCallback() { override fun areItemsTheSame(oldItem: Clip, newItem: Clip): Boolean { val result = oldItem.id == newItem.id Log.d( "ClipDiffCallback", "areItemsTheSame: oldItem.id=${oldItem.id}, newItem.id=${newItem.id}, result=$result" ) return result }
override fun areContentsTheSame(oldItem: Clip, newItem: Clip): Boolean { val result = oldItem.title == newItem.title && oldItem.artist == newItem.artist && oldItem.artUri == newItem.artUri && oldItem.isSelected == newItem.isSelected Log.d( "ClipDiffCallback", "areContentsTheSame: oldItem=$oldItem, newItem=$newItem, result=$result" ) return result } } }
}
[/code] [b] HomeFragment [/b] Этот фрагмент управляет режимом переработки и выбора [code]interface OnItemSelectionListener { fun onItemSelectionChanged(position: Int, isSelected: Boolean) }
@AndroidEntryPoint class HomeFragment : Fragment(), MenuProvider, OnItemSelectionListener {
private var _binding: FragmentHomeBinding? = null private val binding get() = _binding!!
private lateinit var requestPermissionLauncher: ActivityResultLauncher private val clipViewModel by viewModels() private val selectedPositions: MutableSet = mutableSetOf() private var clipAdapter: ClipAdapter? = null private var mMainActivityUiController: MainActivityUiController? = null private var actionMode: ActionMode? = null private var originalClips: List = emptyList() private var clipPosition: Int = 0 private var menu: Menu? = null
private var isSelectionMode: Boolean = false set(value) { field = value clipAdapter?.isSelectionMode = value if (!value) { selectedPositions.clear() val newList = clipAdapter?.currentList?.map { it.copy(isSelected = false) } binding.clipsRV.post { clipAdapter?.submitList(newList) } } }
private var menuHost: MenuHost? = null
fun hideMenu() { isSelectionMode = true menu?.setGroupVisible(0, false)
}
fun showMenu() { isSelectionMode = false
menu?.setGroupVisible(0, true) (requireActivity() as MainActivity).getToolbar().visibility = View.VISIBLE
private fun setupSearchView(menu: Menu) { val searchManager = requireActivity().getSystemService(SEARCH_SERVICE) as SearchManager val searchView = menu.findItem(R.id.app_bar_search).actionView as SearchView searchView.setSearchableInfo(searchManager.getSearchableInfo(requireActivity().componentName)) searchView.queryHint = getString(R.string.library_search)
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { override fun onQueryTextSubmit(keyword: String): Boolean { if (keyword.isEmpty()) { Snackbar.make( binding.root, "please enter keyword to search", Snackbar.LENGTH_SHORT ).show() return false } filterClips(keyword) return false }
override fun onQueryTextChange(newText: String): Boolean {
return true } }) }
private fun filterClips(keyword: String) { val filteredList = if (keyword.isEmpty()) { originalClips } else { originalClips.filter { it.title.contains(keyword, ignoreCase = true) } } clipAdapter?.submitList(filteredList) }
private fun filterSelectedClips(keyword: String) { val filteredList = if (keyword.isEmpty()) { originalClips } else { originalClips.filter { it.title.contains(keyword, ignoreCase = true) } } clipAdapter?.submitList(filteredList) }
private fun startSelectionMode() { isSelectionMode = true
private fun showPermissionRationaleDialog(permission: String) { AlertDialog.Builder(requireContext()) .setTitle("Permission Required") .setMessage("This app needs access to your music files to display and play them. Please grant the permission to continue.") .setPositiveButton("Grant") { _, _ -> requestPermissionLauncher.launch(permission) } .setNegativeButton("Deny") { _, _ -> Toast.makeText( requireContext(), "Permission denied. Cannot access music files.", Toast.LENGTH_SHORT ).show() } .show() }
private fun observeClips() { lifecycleScope.launch { viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { clipViewModel.clipList.collect { resource -> when (resource) { is Resource.Loading -> { binding.progressBar.visibility = View.VISIBLE }
is Resource.Success -> { binding.progressBar.visibility = View.GONE originalClips = resource.data ?: emptyList() Log.d(TAG, "Clips loaded, size: ${originalClips.size}") clipAdapter?.submitList(originalClips) { Log.d(TAG, "Submitted original clips to clipAdapter") } }
override fun onDestroyView() { super.onDestroyView() Log.d(TAG, "Removing MenuProvider for HomeFragment") clipAdapter = null menuHost?.removeMenuProvider(this) binding.clipsRV.removeItemClickSupport() _binding = null }
} [/code] и я обрабатываю щелчки и флажки с этим классом [b] itemclicksupport.kt [/b] [code]class ItemClickSupport private constructor(private val recyclerView: RecyclerView) {
private var onItemClickListener: OnRecyclerViewItemClickListener? = null private var onItemLongClickListener: OnRecyclerViewItemLongClickListener? = null private var onItemCheckChangeListener: OnRecyclerViewItemCheckChangeListener? = null
private val attachListener: RecyclerView.OnChildAttachStateChangeListener = object : RecyclerView.OnChildAttachStateChangeListener { override fun onChildViewAttachedToWindow(view: View) { val holder = this@ItemClickSupport.recyclerView.getChildViewHolder(view)
val isClickable = (holder as? ItemClickSupportViewHolder)?.isClickable ?: true val isLongClickable = (holder as? ItemClickSupportViewHolder)?.isLongClickable ?: true
if (onItemClickListener != null && isClickable) { view.setOnClickListener(onClickListener) }
if (onItemLongClickListener != null && isLongClickable) { view.setOnLongClickListener(onLongClickListener) }
val checkBox = view.findViewById(R.id.selectionCheckBox) if (checkBox != null && onItemCheckChangeListener != null) { checkBox.setOnCheckedChangeListener { _, isChecked -> val position = holder.getAdapterPosition() if (position != RecyclerView.NO_POSITION) { onItemCheckChangeListener?.invoke(recyclerView, position, isChecked) } } } }
override fun onChildViewDetachedFromWindow(view: View) { val checkBox = view.findViewById(R.id.selectionCheckBox) checkBox?.setOnCheckedChangeListener(null) } }
companion object { fun addTo(view: RecyclerView): ItemClickSupport { var support: ItemClickSupport? = view.getTag(R.id.item_click_support) as? ItemClickSupport if (support == null) { support = ItemClickSupport(view) } return support }
fun removeFrom(view: RecyclerView): ItemClickSupport? { val support = view.getTag(R.id.item_click_support) as? ItemClickSupport support?.detach(view) return support } }
private val onClickListener = View.OnClickListener { v -> val listener = onItemClickListener ?: return@OnClickListener val holder = this.recyclerView.getChildViewHolder(v) val position = holder.getAdapterPosition() if (position != RecyclerView.NO_POSITION) { listener.invoke(this.recyclerView, position, v) } }
private val onLongClickListener = View.OnLongClickListener { v -> val listener = onItemLongClickListener ?: return@OnLongClickListener false val holder = this.recyclerView.getChildViewHolder(v) val position = holder.getAdapterPosition() if (position != RecyclerView.NO_POSITION) { return@OnLongClickListener listener.invoke(this.recyclerView, position, v) } return@OnLongClickListener false }
private fun detach(view: RecyclerView) { view.removeOnChildAttachStateChangeListener(attachListener) view.setTag(R.id.item_click_support, null) }
fun onItemClick(listener: OnRecyclerViewItemClickListener?): ItemClickSupport { onItemClickListener = listener return this }
fun onItemLongClick(listener: OnRecyclerViewItemLongClickListener?): ItemClickSupport { onItemLongClickListener = listener return this }
fun onItemCheckChange(listener: OnRecyclerViewItemCheckChangeListener?): ItemClickSupport { onItemCheckChangeListener = listener return this } }
interface ItemClickSupportViewHolder { val isClickable: Boolean get() = true val isLongClickable: Boolean get() = true }
fun RecyclerView.addItemClickSupport(configuration: ItemClickSupport.() -> Unit = {}) = ItemClickSupport.addTo(this).apply(configuration)
fun RecyclerView.removeItemClickSupport() = ItemClickSupport.removeFrom(this)
fun RecyclerView.onItemClick(onClick: OnRecyclerViewItemClickListener) { addItemClickSupport { onItemClick(onClick) } }
fun RecyclerView.onItemLongClick(onLongClick: OnRecyclerViewItemLongClickListener) { addItemClickSupport { onItemLongClick(onLongClick) } }
fun RecyclerView.onItemCheckChange(onCheckChange: OnRecyclerViewItemCheckChangeListener) { addItemClickSupport { onItemCheckChange(onCheckChange) } } [/code] Это изображение показывает проблему, когда я ввожу режим выбора и изменяю все три точки с флажками