单击RecyclerView

时间:2017-09-19 16:00:04

标签: android listview android-recyclerview kotlin

我有一个由2个主要项目组成的活动:RecyclerView和ListView。 RecyclerView充当过滤器,选择/取消选择项目将影响ListView的内容。一切顺利,直到我尝试在RecyclerView上实现onClickListener,并意识到这不是一个选项。

我尝试过在ViewHolder中设置OnClickListener的路线,但它需要调用main活动中的一个函数并刷新它的listView。任何此类交互都会触发以下错误:

java.lang.NullPointerException
    at android.support.v7.app.AppCompatDelegateImplBase.<init>(AppCompatDelegateImplBase.java:117)
    at android.support.v7.app.AppCompatDelegateImplV9.<init>(AppCompatDelegateImplV9.java:149)
    at android.support.v7.app.AppCompatDelegateImplV11.<init>(AppCompatDelegateImplV11.java:29)
    at android.support.v7.app.AppCompatDelegateImplV14.<init>(AppCompatDelegateImplV14.java:54)
    at android.support.v7.app.AppCompatDelegate.create(AppCompatDelegate.java:202)
    at android.support.v7.app.AppCompatDelegate.create(AppCompatDelegate.java:183)
    at android.support.v7.app.AppCompatActivity.getDelegate(AppCompatActivity.java:519)
    at android.support.v7.app.AppCompatActivity.findViewById(AppCompatActivity.java:190)
    at .newsScreen._$_findCachedViewById(newsScreen.kt)
    at .newsScreen.filterNews(newsScreen.kt:71)
    at Cells.NewsFeedList$NewsSource$1.onClick(News Lists.kt:84)

假设它有意义,因为我试图从它的外部访问UI,但我找不到它的替代品。

RecyclerView适配器:

class NewsFeedList() : RecyclerView.Adapter<NewsFeedList.NewsSource>() {
    private var source: List<NewsFeed> = ArrayList()

    constructor(s: ArrayList<NewsFeed>) : this() {
        source = s
    }

    class NewsSource : RecyclerView.ViewHolder {

        private var mTextView: TextView? = null

        constructor(v: View): super(v) {
            mTextView = v.title
        }

        fun bindInfo(news: NewsFeed, view: View, int: Int) {
            mTextView!!.text = news.title
            view.tag = int
            view.setOnClickListener { newsScreen().filterNews(view.tag.toString().toInt()) }
            if (news.selected) view.background = ColorDrawable(Color.parseColor(news.color))
            else view.background = ColorDrawable(Color.parseColor(design.backgroundColor))
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): NewsFeedList.NewsSource {
        val view = LayoutInflater.from(parent!!.context).inflate(R.layout.newsfeed_list, parent, false)
        return NewsSource(view)
    }

    override fun onBindViewHolder(holder: NewsFeedList.NewsSource, position: Int) {
        holder.bindInfo(source[position], holder.itemView, position)
    }

    override fun getItemCount(): Int {
        return source.count()
    }

}

然后,在我的newsScreen类中,我需要使用新数据访问RecyclerView适配器

fun filterNews(i: Int) {

    newsFeed[i].selected = !newsFeed[i].selected
    filter.adapter = NewsFeedList(newsFeed)

}

如果删除对filter(RecyclerView)的任何引用,一切都很好,但onClickListener的目的是刷新Activities内容。

有没有办法实现这一点,还是应该将RecyclerView更改为其他UI元素?

修改 我尝试将一个OnClickListener添加到RecyclerView但它似乎没有被触发。的代码:

filter.adapter = NewsFeedList(newsFeed)
filter.layoutManager = LinearLayoutManager(this@newsScreen, LinearLayoutManager.HORIZONTAL, false)
filter.setOnClickListener { v: View? ->
       filterNews(v!!.tag.toString().toInt())
}

3 个答案:

答案 0 :(得分:1)

对于您的Adapter类,您将拥有一个ViewHolder类(可能作为内部类),它在此代码中实现OnClickListener:

class ViewHolder extends RecyclerView.ViewHolder implements OnClickListener {

    TextView textView;
    ImageView imageView;

    ViewHolder(View itemView) {
        super(itemView);
        textView = (TextView) itemView.findViewById(R.id.text_view);
        imageView = (ImageView) itemView.findViewById(R.id.image_view);
    }

    @Override
    void onClick(View v) {

    }
}

假设您的适配器不是您的Activity类的内部类,如果您愿意使用onClick()来访问您的Activity类&#39;方法/变量你必须有参考。

最好的方法是通过适配器的构造函数传递Context引用,因为ViewHolder是适配器的内部类:

class MyAdapter extends extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    Context context;

    MyAdapter(Context context) {
        this.context = context;
    }

    class ViewHolder extends RecyclerView.ViewHolder implements OnClickListener {

        TextView textView;
        ImageView imageView;

        ViewHolder(View itemView) {
            super(itemView);
            textView = (TextView) itemView.findViewById(R.id.text_view);
            imageView = (ImageView) itemView.findViewById(R.id.image_view);
        }

        @Override
        void onClick(View v) {
            // Here we gain access to non-private methods/variables 
            // of the Activity, which Context reference we are holding.
            ((MyActivity) context).someMethod();
        }
    }
}

希望,这有帮助。

答案 1 :(得分:1)

好的,这是您可以尝试的另一种解决方案:

将此界面添加到您的应用中:

interface ClickListener {
    void onItemClicked(int position);
}

在MainActivity(或任何有按钮的活动)中实现它。

在Adapter构造函数中传递接口的引用:     ArrayList mList;     ClickListener监听器;

public MyAdapter(ArrayList<NewsFeed> mList, ClickListener listener) {
    this.listener = listener;
}

@Override
public MyAdapter.NavViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.someL, parent, false);
    return new ViewHolder(v, listener);

}

public void getItemClicked(int position){
    mList.get(position);
}

最后,在你的ViewHolder类中:

class ViewHolder extends RecyclerView.ViewHolder implements OnClickListener {

    TextView textView;
    ImageView imageView;
    ClickListener listener;

    ViewHolder(View itemView, ClickListener listener) {
        super(itemView);
        this.listener = listener;
        textView = (TextView) itemView.findViewById(R.id.text_view);
        imageView = (ImageView) itemView.findViewById(R.id.image_view);
        textView.setOnClickListener(this)
    }

    @Override
    void onClick(View v) {
      listener.onItemClicked(getAdapterPosition());
    }

最后在您的Activity(实现ClickListener接口)中,您必须覆盖void onItemClicked(int position);,您将在其中执行操作。

P.S。:这个答案是在用户的主要帮助下编写的:https://stackoverflow.com/users/2667883/chaynik

答案 2 :(得分:0)

  1. 创建一个函数reload()并重新加载所有视图
  2. 使用.this将您的活动上下文传递给适配器
  3. 在适配器中,将上下文传递给类对象,如

    MyActivity activity = (MyActivity)context
    

并调用以下方法:

activity.reload();