ListView не активируется (пользовательский адаптер) - PullRequest
0 голосов
/ 23 апреля 2019

Я пытаюсь создать простую программу чтения RSS с Римом.

Моя базовая реализация использует ListView и мой пользовательский Adapter, чтобы заполнить его feed_stub.xml. Нажатие на элемент ListView запустит другое действие.

Пока у меня есть две проблемы:

  1. Мои элементы ListView недоступны для клика - мой setOnItemClickListener не срабатывает.

  2. Если я нажимаю на некоторые элементы много раз, мое приложение вылетает из-за исключительной ситуации. Это означает, что мой адаптер, вероятно, имеет ошибки.

ListView от activity_main.xml

<ListView
            android:layout_width="0dp"
            android:layout_height="0dp" android:layout_marginTop="8dp"
            app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent"
            android:layout_marginStart="8dp"
            android:layout_marginBottom="8dp" app:layout_constraintBottom_toBottomOf="parent"
            android:id="@+id/rssListView" app:layout_constraintEnd_toEndOf="parent" android:layout_marginEnd="8dp"
            android:clickable="true" app:layout_constraintHorizontal_bias="0.0"
            app:layout_constraintVertical_bias="0.0"/>

Мой MainActivity

import android.content.Intent
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import cz.cvut.lenguduy.rss.Downloader
import cz.cvut.lenguduy.view.ViewHolder
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {
    private val TAG = "MainActivity"

    private val downloader by lazy { Downloader(this, rssListView) }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        rssListView.setOnItemClickListener { parent, _, position, _ ->
            Log.d(TAG, "rssListView: item @pos $position clicked")
            val intent = Intent(this, SecondActivity::class.java)
            val item = parent.getItemAtPosition(position) as ViewHolder

            Toast.makeText(this, "clicked", Toast.LENGTH_LONG).show()

            intent.putExtra("title", item.tvName.text)
            intent.putExtra("text", item.tvSummary.text)
            this.startActivity(intent)
        }

        downloader.execute("http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/topfreeapplications/limit=25/xml")
    }

    override fun onDestroy() {
        super.onDestroy()
        downloader.cancel(true)
    }
}

ViewHolder просто:

class ViewHolder(view: View) {
    val tvName: TextView = view.findViewById(R.id.tvName)
    val tvSummary: TextView = view.findViewById(R.id.tvSummary)
}

My ListView использует feed_stub.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
                                             xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
                                             android:layout_height="match_parent">

    <TextView
            android:text="TextView"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:id="@+id/tvName" android:layout_marginTop="8dp"
            app:layout_constraintTop_toTopOf="parent" app:layout_constraintEnd_toEndOf="parent"
            android:layout_marginEnd="16dp" app:layout_constraintStart_toStartOf="parent"
            android:layout_marginStart="16dp" android:textSize="20sp" android:textStyle="bold" android:maxLines="2"
            android:clickable="true"/>
    <TextView
            android:text="TextView"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:id="@+id/tvSummary"
            app:layout_constraintTop_toBottomOf="@+id/tvName" app:layout_constraintEnd_toEndOf="parent"
            android:layout_marginEnd="16dp" app:layout_constraintStart_toStartOf="parent"
            android:layout_marginStart="16dp" android:maxLines="3" android:clickable="true"/>
</android.support.constraint.ConstraintLayout>

И, наконец, мой FeedAdapter:

class FeedAdapter(context: Context,
                  private val resource: Int, private val feed: MutableList<Any?>)
    : ArrayAdapter<Article>(context, resource) {

    private val inflater = LayoutInflater.from(context)

    override fun getCount(): Int {
        return feed.size
    }

    override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
        val view: View
        val viewHolder: ViewHolder
        if(convertView == null) {
            view = inflater.inflate(resource, parent, false)
            viewHolder = ViewHolder(view)
            view.tag = viewHolder
        } else {
            view = convertView
            viewHolder = view.tag as ViewHolder
        }

        val currentEntry = feed[position] as SyndEntry

        viewHolder.tvName.text = currentEntry.title
        viewHolder.tvSummary.text = currentEntry.description.value

        return view
    }

    override fun isEnabled(position: Int): Boolean {
        return true
    }
}

Большинство операций выполняется моим псевдоконтроллером:

class Downloader(context: Context, listView: ListView): AsyncTask<String, Void, String>() {
    private val TAG = "Downloader"

    private var propContext: Context by Delegates.notNull()
    private var propListView: ListView by Delegates.notNull()

    init {
        propContext = context
        propListView = listView
    }

    private lateinit var list: MutableList<Any?>

    override fun doInBackground(vararg url: String?): String {
        val input = SyndFeedInput()
        val feed = input.build(XmlReader(URL(url[0])))

        list = feed.entries

        return feed.toString()
    }

    override fun onPostExecute(result: String?) {
        super.onPostExecute(result)

        val feedAdapter = FeedAdapter(propContext, R.layout.feed_stub, list)
        propListView.adapter = feedAdapter
    }
}

Так почему мои ListView предметы не кликабельны?

А почему мое приложение вылетает после нескольких кликов с java.lang.IndexOutOfBoundsException: Invalid index 10, size is 0?

РЕДАКТИРОВАТЬ: В FeedAdapter с getView() Я добавил это на ClickListener:

convertView?.setOnClickListener() { v ->
            Log.d(TAG, "getView(): item clicked")

            val intent = Intent(context, SecondActivity::class.java)
            intent.putExtra("title", currentEntry.title)
            intent.putExtra("summary", currentEntry.description.value)

            context.startActivity(intent)
        }

Теперь я могу щелкнуть по нему ИНОГДА. Я абсолютно не знаю, почему это так, но если я нажму достаточно случайно, я получу предполагаемое поведение при переходе к другому виду деятельности.

1 Ответ

0 голосов
/ 23 апреля 2019

это потому, что вы не реализовали onClickListener для класса viewHolder. Вы реализовали для ListView onItemClick Listener, который просто не будет работать для пользовательских адаптеров. для пользовательских адаптеров вам нужно реализовать onClickListener внутри вашего метода getView.

override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
        val view: View
        val viewHolder: ViewHolder
        if(convertView == null) {
            view = inflater.inflate(resource, parent, false)
            viewHolder = ViewHolder(view)
            view.tag = viewHolder
        } else {
            view = convertView
            viewHolder = view.tag as ViewHolder
        }

        val currentEntry = feed[position] as SyndEntry

        viewHolder.tvName.text = currentEntry.title
        viewHolder.tvSummary.text = currentEntry.description.value

        // set onClickListener for your ConvertView...
        convertView.setOnClickListener(context);    

        return view
    }

// now implement your on Click 
@Overriden
void onClick(View view){

}
...