在ListAdapter的长时间单击时显示对话框



我有一个活动,其中包含以下List适配器,用于显示有关github存储库的一些信息。现在我需要实现的是,当长按列表项时,显示一个对话框,询问是否应该转到存储库html_url或所有者html_url,然后在浏览器中打开。

实现这一点的最佳方式是什么?逻辑应该在活动中还是在ListAdapater/ViewHolder中?

存储库列表适配器

class RepositoryListAdapter : ListAdapter<Repo, RepositoryListAdapter.RepositoryViewHolder>(
RepositoryDiffCallback()
) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
RepositoryViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.item_repository,
parent,
false
)
)
override fun onBindViewHolder(holder: RepositoryViewHolder, position: Int) {
holder.bind(getItem(position))
}
class RepositoryViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
fun bind(repository: Repo) = with(itemView) {
repositoryName.text = repository.name
repositoryDescription.text = repository.description
ownerLogin.text = repository.owner.login
Glide.with(context)
.load(repository.owner.avatarUrl)
.into(imageView)
if (repository.forksCount > 0) {
itemView.setBackgroundColor(ContextCompat.getColor(context, R.color.light_green))
} else {
itemView.setBackgroundColor(ContextCompat.getColor(context, android.R.color.white))
}
}
}
}
class RepositoryDiffCallback : DiffUtil.ItemCallback<Repo>() {
override fun areItemsTheSame(oldItem: Repo, newItem: Repo): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: Repo, newItem: Repo): Boolean {
return oldItem == newItem
}
}

让"活动"将一个侦听器传递给适配器来执行此操作。

在适配器中,创建一个侦听器接口:

class RepositoryListAdapter(val onItemLongClickListener: OnItemLongClickListener) : ListAdapter<Repo, RepositoryListAdapter.RepositoryViewHolder>(
RepositoryDiffCallback()
) {

interface OnItemLongClickListener {
fun onItemLongClick(item: Repo, position: Int)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
RepositoryViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.item_repository,
parent,
false
)
).also { vh ->
vh.itemView.setOnLongClickListener { 
val position = vh.adapterPosition
if (position != RecyclerView.NO_POSITION) {
onItemLongClickListener.onItemLongClick(getItem(position), position)
}
true
}
}
}

然后在创建适配器的活动中,传递侦听器:

class YourActivity : Activity {
private lateinit var adapter: RepositoryListAdapter
override fun onCreate(savedInstanceState: Bundle?) {
...
adapter = RepositoryListAdapter(object : OnItemLongClickListener {
override fun onItemLongClick(item: Repo, position) {
// Your logic to show the dialog
}
})
...    
}
}

最好的方法是处理适配器中的长点击弹出,并在用户点击后消耗操作以分割/活动

class RepositoryListAdapter : ListAdapter<Repo, RepositoryListAdapter.RepositoryViewHolder>(
RepositoryDiffCallback()
) {


adapter.setPopupListener(object : OnPopupClick {
override fun goToRepository() {
//Consume action
}

override fun goToOwner(){
//Consume action
}
})


override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
RepositoryViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.item_repository,
parent,
false
)
)

override fun onBindViewHolder(holder: RepositoryViewHolder, position: Int) {
holder.bind(getItem(position))
}

//WeakReference to prevent un-wanted gc clean of listener
private var popupListener: WeakReference<OnPopupClick>? = null

fun setPopupListener(listener: OnPopupClick) {
popupListener = WeakReference(listener)
}

interface OnPopupClick {
fun goToRepository()
fun goToOwner()
}

class RepositoryViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
fun bind(repository: Repo) = with(itemView) {
repositoryName.text = repository.name
repositoryDescription.text = repository.description
ownerLogin.text = repository.owner.login
Glide.with(context)
.load(repository.owner.avatarUrl)
.into(imageView)


itemView.setOnLongClickListener{
onLongClick()
}

if (repository.forksCount > 0) {
itemView.setBackgroundColor(ContextCompat.getColor(context, R.color.light_green))
} else {
itemView.setBackgroundColor(ContextCompat.getColor(context, android.R.color.white))
}
}

fun onLongClick(){

//MenuAnchor must be added to your item view
val popup = PopupMenu(view.context, menuAnchor)

popup.inflate(R.menu.yourMenu)  //Customize for user

popup.setOnMenuItemClickListener(object : PopupMenu.OnMenuItemClickListener {
override fun onMenuItemClick(item: MenuItem?): Boolean {
when (item?.itemId) {
R.id.owner -> {
popupListener?.get()?.goToOwner()
return true
}
R.id.repo ->{
popupListener?.get()?.goToRepository()
return true
}
}
return true
}
})

popup.show()

}
}
}

class RepositoryDiffCallback : DiffUtil.ItemCallback<Repo>() {
override fun areItemsTheSame(oldItem: Repo, newItem: Repo): Boolean {
return oldItem.id == newItem.id
}

override fun areContentsTheSame(oldItem: Repo, newItem: Repo): Boolean {
return oldItem == newItem
}
}

之后添加到您的活动/片段:

adapter.setPopupListener(object : OnPopupClick {
override fun goToRepository() {
//Consume action
}
override fun goToOwner(){
//Consume action
}
})

这就是我最后的做法,以防有人觉得它有用。

存储库列表适配器

class RepositoryListAdapter(private val interaction: Interaction? = null) : ListAdapter<Repo, RepositoryListAdapter.RepositoryViewHolder>(
RepositoryDiffCallback()
) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
RepositoryViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.item_repository,
parent,
false
),
interaction
)
override fun onBindViewHolder(holder: RepositoryViewHolder, position: Int) {
holder.bind(getItem(position))
}
class RepositoryViewHolder(itemView: View, private val interaction: Interaction?)
: RecyclerView.ViewHolder(itemView){
fun bind(repository: Repo) = with(itemView) {
repositoryName.text = repository.name
repositoryDescription.text = repository.description
ownerLogin.text = repository.owner.login
Glide.with(context)
.load(repository.owner.avatarUrl)
.into(imageView)
if (repository.forksCount > 0) {
itemView.setBackgroundColor(ContextCompat.getColor(context, R.color.light_green))
} else {
itemView.setBackgroundColor(ContextCompat.getColor(context, android.R.color.white))
}
setOnLongClickListener {
interaction?.onItemLongClick(repository)
true
}
}
}
interface Interaction {
fun onItemLongClick(item: Repo)
}
}

实际

class MainActivity : AppCompatActivity(), RepositoryListAdapter.Interaction {
...
private fun setupListAdapter() {
repositoryListAdapter = RepositoryListAdapter(this)
...
}
private fun showDialog(repo: Repo) {
dialog = AlertDialog.Builder(this)
.setItems(arrayOf("Repository url", "Owner url")) { _, which ->
when (which) {
0 -> openUrl(repo.htmlUrl)
1 -> openUrl(repo.owner.htmlUrl)
}
}.show()
}
private fun openUrl(url: String?) {
url?.let {
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url)))
}
}
override fun onItemLongClick(item: Repo) {
showDialog(item)
}
...
}

最新更新