Я пытаюсь реализовать щелчок по элементу с помощью RecyclerView около 2 дней. Я попытался сделать все, что было предложено stackoverflow по этому вопросу. У меня уже нет никаких идей, что делать дальше. Поэтому я хочу спросить вас.
Это мой код:
class CustomAdapter(var data: List<DataSource>, val clickListener: OnWordItemClickListener):
RecyclerView.Adapter<CustomAdapter.ViewHolder>() {
class ViewHolder(view: View) : RecyclerView.ViewHolder(view)
{
val tv_front: TextView = view.findViewById(R.id.tv_front) as TextView
val tv_back: TextView = view.findViewById(R.id.tv_back) as TextView
// Define the click listener
fun initialize(dataSource: DataSource, action: OnWordItemClickListener)
{
tv_front.text = dataSource._front
tv_back.text = dataSource._back
itemView.setOnClickListener {
action.onItemClick(dataSource, adapterPosition)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.row_item, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
/*val currentItem = data[position]
holder.tv_front.text = currentItem._front
holder.tv_back.text = currentItem._back*/
holder.initialize(data[position], clickListener)
}
override fun getItemCount(): Int = data.size
}
interface OnWordItemClickListener
{
fun onItemClick(dataSource: DataSource, position: Int)
}
И код из MainActivity:
class MainActivity : AppCompatActivity(), OnWordItemClickListener {
val PERMISSION_REQUEST_CODE: Int = 123
private lateinit var linearLayoutManager: LinearLayoutManager
lateinit var rv_allWords: RecyclerView
lateinit var adapter: CustomAdapter
lateinit var databaseHandler: DatabaseHandler
lateinit var dataSource: DataSource
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
permissions()
rv_allWords = findViewById(R.id.rv_allWords) as RecyclerView
linearLayoutManager = LinearLayoutManager(this)
rv_allWords.layoutManager = linearLayoutManager
databaseHandler = DatabaseHandler(this)
val exampleList = databaseHandler.read_from()
adapter = CustomAdapter(exampleList, this)
rv_allWords.adapter = adapter
adapter.notifyDataSetChanged()
}
fun permissions()
{
//var permissionStatus = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) +
ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED)
{
// permission granted
} else {
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE), PERMISSION_REQUEST_CODE)
}
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
when(requestCode)
{
PERMISSION_REQUEST_CODE ->
{
if ((grantResults.isNotEmpty()) && grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED)
{
// permissions is granted. Continue the action or workflow
Toast.makeText(this, "Permissions granted", Toast.LENGTH_SHORT).show()
} else {
// Explain to the user that the feature is unavailable because
// the features requires a permission the the user has denied
val alertDialog: AlertDialog? = this?.let {
val builder = AlertDialog.Builder(it)
builder.apply {
setPositiveButton(R.string.OK, DialogInterface.OnClickListener { dialog, id ->
finish()
System.exit(0)
})
setMessage("The app needs to save some data to external storage.")
}
builder.show()
}
}
return
}
// Add other 'when' line to check for other
// permissions this app might request
else ->
{
// Ignore all other requests
}
}
}
fun generateTestList(size: Int): List<DataSource> {
val list = ArrayList<DataSource>()
for (i in 0 until size)
{
val item = DataSource(i, "Item $i", "$i")
list += item
}
return list
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.menu, menu)
return super.onCreateOptionsMenu(menu)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
var id = item.itemId
if (id == R.id.menu_refresh)
{
}
return super.onOptionsItemSelected(item)
}
override fun onResume() {
super.onResume()
databaseHandler.read_from()
}
override fun onItemClick(dataSource: DataSource, position: Int) {
Toast.makeText(this, dataSource._back, Toast.LENGTH_SHORT).show()
Log.i("onItemClick", dataSource._back)
}
}
Когда я запускаю приложение на устройстве или эмуляторе, ничего не происходит. То есть, когда я пытаюсь щелкнуть любой элемент в RecyclerView, мое сообщение не отображается, и приложение работает без ошибок. Извините за мой английский. Что еще я могу сделать?
Вы видите рябь, когда вы нажимаете на элементы?
@ Tenfour04 да, я знаю. Но я не вижу Toast или Log
@tronku да, я должен сделать то, что ты сказал. Но это не работает :(
Где определяется itemView
? Я могу ошибаться, но вы должны заменить itemView
на view
внутри initialize()
метода.
Попробуйте реализовать View.OnClickListener
с помощью класса ViewHolder
.
class ViewHolder(val view: View) : RecyclerView.ViewHolder(view), View.OnClickListener {
//(...)
fun initialize(dataSource: DataSource, action: OnWordItemClickListener)
{
tv_front.text = dataSource._front
tv_back.text = dataSource._back
view.setOnClickListener{action.onItemClick(dataSource, adapterPosition)}
}
ОБНОВЛЯТЬ: Итак, изучив остальную часть кода, я обнаружил два LinearLayout внутри xml, используемых для макета ViewHolder. Я удалил «родительский», и он начал работать. Вот row_item.xml после изменений.
<?xml version = "1.0" encoding = "utf-8"?>
<LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:gravity = "center_horizontal"
android:orientation = "horizontal"
android:clickable = "true"
android:focusable = "true"
android:background = "?attr/selectableItemBackground">
<TextView
android:id = "@+id/tv_front"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:padding = "3dp"
android:text = "Front"
android:textSize = "32sp"
android:gravity = "left"
android:layout_weight = "1" />
<TextView
android:id = "@+id/tv_back"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:padding = "3dp"
android:text = "Back"
android:textSize = "32sp"
android:gravity = "right"
android:layout_weight = "1" />
</LinearLayout>
Когда я пишу «view.setOnClickListener», я сказал мне, что «представление» — это неразрешенная ссылка.
Я сделал небольшую правку в коде. Сделайте параметр класса view
. Поэтому вместо view: View
напишите val view: View
в качестве параметра класса.
Теперь «это» выделено. Несоответствие типов. Требуется: View.OnClickListener?. Найдено: ViewHolder.
Виноват! Я реализовал его как LongClickListener. Попробуйте с новым редактированием! view.setOnClickListener{action.onItemClick(dataSource, adapterPosition}
был бы признателен, если бы это сработало для вас, пометив это как хороший ответ
К сожалению, это тоже не работает. Ни тосты, ни сообщения журнала не отображались. Я все время пробовал разные решения, но почему-то ничего не работает :(. У вас есть решение, которое вы используете в своих проектах?
Да, у меня есть! Можете ли вы связать меня с вашим проектом, чтобы я мог взглянуть или описать вашу проблему дальше :)
Когда приложение запущено, необходимо добавить некоторые записи в базу данных через инспектор базы данных. Затем закройте приложение и снова запустите его. В противном случае список будет пуст.
Итак, я думаю, что нашел проблему. Мои изменения должны работать для вас только после того, как вы удалите один дополнительный LinearLayout (тот, который является родителем). После того, как я удалил его и оставил «дочерний», он начал работать. Изменения кода в обновлении :)
Спасибо 1000 раз! Можете ли вы кратко объяснить мне, почему это произошло? Как LinearLayout предотвратил это? :)
Ну объяснить - другое дело. Я хотел бы изучить эту проблему, но это займет некоторое время;) так что будьте готовы услышать от меня, как только я узнаю, почему. Не могли бы вы отметить мой ответ как принятый? спасибо и рад, что смог помочь
Вы пытались сделать интерфейс внутренним интерфейсом recyclerview?