简体   繁体   English

ListView不可点击(自定义适配器)

[英]ListView is not clickable (custom Adapter)

I'm trying to create a simple RSS reader with Rome. 我正在尝试用罗马创建一个简单的RSS阅读器。

My barebones implementation uses ListView and my custom Adapter to fill it with feed_stub.xml . 我的准系统实现使用ListView和我的自定义Adapterfeed_stub.xml填充它。 Clicking on a ListView item will start another activity. 单击ListView项将启动另一个活动。

So far I have two problems: 到目前为止,我有两个问题:

  1. My ListView items are not clickable - my setOnItemClickListener isn't triggered. 我的ListView项目无法点击 - 我的setOnItemClickListener未被触发。

  2. If I click on some items many times, my app crashes with out of bound exception. 如果我多次点击某些项目,我的应用程序会因超出异常而崩溃。 Which means my Adapter probably has errors. 这意味着我的适配器可能有错误。

ListView from activity_main.xml 来自activity_main.xml ListView

<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"/>

My MainActivity 我的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 is simple: ViewHolder很简单:

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

My ListView uses feed_stub.xml : 我的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>

And finally my FeedAdapter : 最后我的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
    }
}

Most operations are performed by my pseudo-controller: 大多数操作都是由我的伪控制器执行的:

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
    }
}

So why are my ListView items not clickable? 那么为什么我的ListView项目不可点击?

And why does my app crash after multiple clicks with java.lang.IndexOutOfBoundsException: Invalid index 10, size is 0 ? 为什么我的应用程序在使用java.lang.IndexOutOfBoundsException: Invalid index 10, size is 0多次单击后崩溃java.lang.IndexOutOfBoundsException: Invalid index 10, size is 0

EDIT: In FeedAdapter s getView() I added this onClickListener: 编辑:FeedAdaptergetView()我添加了这个onClickListener:

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)
        }

Now I'm able to click on it SOMETIMES. 现在我可以点击它有时候。 I have absolutely no idea why that is but if I click randomly enough, I will get the intended behavior of going to another activity. 我完全不知道为什么会这样,但如果我随机点击,我将获得去另一个活动的预期行为。

this is because you haven't implemented onClickListener for viewHolder class. 这是因为您尚未为viewHolder类实现onClickListener。 you have implemented for listview onItemClick Listener which simply won't work for custom adapters. 你已经实现了listView onItemClick Listener,它不适用于自定义适配器。 for custom adapters you need to implement onClickListener inside your getView Method. 对于自定义适配器,您需要在getView方法中实现onClickListener。

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){

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM