繁体   English   中英

RecyclerView项目onClickListener不适用于第一次点击,但适用于第二次点击

[英]RecyclerView item onClickListener doesn't work on a first click, but works on a second one

适配器

public class MoviesAdapter extends 
RecyclerView.Adapter<MoviesAdapter.MoviesViewHolder> {
private static final String baseMovieUrl = "http://image.tmdb.org/t/p/w500";
private ArrayList<Movie> movies;
private Context context;

public MoviesAdapter(ArrayList<Movie> movies, Context context) {
    this.movies = movies;
    this.context = context;
}

@NonNull
@Override
public MoviesViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
    return new MoviesViewHolder(layoutInflater.inflate(R.layout.movie_square, parent, false));
}

@Override
public void onBindViewHolder(@NonNull MoviesViewHolder holder, int position) {
    holder.setData(position);

}


@Override
public int getItemCount() {
    return movies.size();
}


public class MoviesViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
    private ConstraintLayout movieConstraint;
    private TextView movieName;
    private TextView movieRate;
    private ImageView moviePoster;

    public MoviesViewHolder(View itemView) {
        super(itemView);
        movieConstraint = itemView.findViewById(R.id.movie_holder_constraints);
        movieName = itemView.findViewById(R.id.movie_name_tv);
        movieRate = itemView.findViewById(R.id.movie_rating_tv);
        moviePoster = itemView.findViewById(R.id.movie_iv);
        movieConstraint.setOnClickListener(this);

    }

    public void setData(int position) {
        movieConstraint.setTag(position);
        movieName.setText(movies.get(position).getMovieName());
        movieRate.setText(movies.get(position).getMovieRating() + "");
        if (!Objects.equals(movies.get(position).getMovieUrl(), "") && movies.get(position).getMovieUrl() != null) {
            Glide.with(moviePoster).load
                    (baseMovieUrl + movies.get(position).getMovieUrl())
                    .into(moviePoster);
        } else Log.i("No url!", "No url!");
    }

    @Override
    public void onClick(View view) {
        int pos = (int) view.getTag();
        view.setEnabled(false);
        changeActivity(pos);
        view.setEnabled(true);    // TODO Find a way to prevent 2 acctivites to open simultaniously
    }


    private void changeActivity(int pos) {
        Movie movie = movies.get(pos);
        Intent intent = new Intent(context, MovieInfo.class);
        intent.putExtra("movie", movie);
        ActivityOptionsCompat options = ActivityOptionsCompat.
                makeSceneTransitionAnimation((Activity) context, moviePoster, "profile");
        context.startActivity(intent, options.toBundle());
    }
}
}

和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:id="@+id/movie_holder_constraints"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="3dp">

<android.support.v7.widget.CardView
    android:id="@+id/movie_cv"
    android:layout_width="185dp"
    android:layout_height="250dp"
    android:layout_marginBottom="8dp"
    android:layout_marginEnd="8dp"
    android:layout_marginStart="8dp"
    android:layout_marginTop="8dp"
    android:focusable="false"
    android:focusableInTouchMode="false"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent">

    <android.support.constraint.ConstraintLayout
        android:id="@+id/inside_movie_constraints"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:focusable="false"
        android:focusableInTouchMode="false"
        >

        <ImageView
            android:id="@+id/movie_iv"
            android:layout_width="185dp"
            android:layout_height="180dp"
            android:scaleType="fitXY"
            android:focusable="false"
            android:focusableInTouchMode="false"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:srcCompat="@mipmap/ic_launcher" />

        <TextView
            android:id="@+id/movie_rating_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="8dp"
            android:layout_marginEnd="8dp"
            android:layout_marginStart="16dp"
            android:layout_marginTop="2dp"
            android:text="9.5"
            android:textColor="@color/colorAccent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.0"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/movie_name_tv"
            app:layout_constraintVertical_bias="1.0" />

        <TextView
            android:id="@+id/movie_name_tv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginEnd="8dp"
            android:layout_marginStart="8dp"
            android:layout_marginTop="8dp"
            android:text="Guardian's Of The Galaxy"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintHorizontal_weight="1"
            android:gravity="center"
            android:includeFontPadding="false"
            app:layout_constraintTop_toBottomOf="@+id/movie_iv" />
    </android.support.constraint.ConstraintLayout>
</android.support.v7.widget.CardView>

在recyclerView中单击该项目时,它不会打开该活动或调用OnClickListener,在另一次单击该函数之后。 滚动还可以使我也单击这些项目。

我听说将fuucsable更改为false可能会解决此问题,但是正如您在xml中看到的那样,它没有解决。

编辑适配器:我将onClick更改为onBindViewHolder,尽管我不觉得这样做的正确方法,但可以解决此问题。 你说什么?

package com.example.galzaid.movies;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.support.annotation.NonNull;
import android.support.constraint.ConstraintLayout;
import android.support.v4.app.ActivityOptionsCompat;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.bumptech.glide.Glide;

import java.util.ArrayList;
import java.util.Objects;

public class MoviesAdapter extends 
RecyclerView.Adapter<MoviesAdapter.MoviesViewHolder> implements 
View.OnClickListener {
private static final String baseMovieUrl = "http://image.tmdb.org/t/p/w500";
private ArrayList<Movie> movies;
private Context context;

public MoviesAdapter(ArrayList<Movie> movies, Context context) {
    this.movies = movies;
    this.context = context;
}

@NonNull
@Override
public MoviesViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
    return new MoviesViewHolder(layoutInflater.inflate(R.layout.movie_square, parent, false));
}

@Override
public void onBindViewHolder(@NonNull MoviesViewHolder holder, int position) {
    holder.setData(position);
    holder.itemView.setOnClickListener(this);
    holder.getAdapterPosition();
}


@Override
public int getItemCount() {
    return movies.size();
}

@Override
public void onClick(View view) {
    ImageView moviePoster = view.findViewById(R.id.movie_iv);
    changeActivity((int) view.getTag(), moviePoster);
}

private void changeActivity(int pos, ImageView moviePoster) {
    Movie movie = movies.get(pos);
    Intent intent = new Intent(context, MovieInfo.class);
    intent.putExtra("movie", movie);
    ActivityOptionsCompat options = ActivityOptionsCompat.
            makeSceneTransitionAnimation((Activity) context, moviePoster, "profile");
    context.startActivity(intent, options.toBundle());
}


public class MoviesViewHolder extends RecyclerView.ViewHolder {
    private ConstraintLayout movieConstraint;
    private TextView movieName;
    private TextView movieRate;
    private ImageView moviePoster;

    public MoviesViewHolder(View itemView) {
        super(itemView);
        movieConstraint = itemView.findViewById(R.id.movie_holder_constraints);
        movieName = itemView.findViewById(R.id.movie_name_tv);
        movieRate = itemView.findViewById(R.id.movie_rating_tv);
        moviePoster = itemView.findViewById(R.id.movie_iv);

    }

    public void setData(int position) {
        movieConstraint.setTag(position);
        movieName.setText(movies.get(position).getMovieName());
        movieRate.setText(movies.get(position).getMovieRating() + "");
        if (!Objects.equals(movies.get(position).getMovieUrl(), "") && movies.get(position).getMovieUrl() != null) {
            Glide.with(moviePoster).load
                    (baseMovieUrl + movies.get(position).getMovieUrl())
                    .into(moviePoster);
        } else Log.i("No url!", "No url!");
    }
}
}

在绑定方法中设置OnClickListener,在您的情况下为public void setData(int position)

顾名思义,RecyclerView正在重用其创建的视图,因此对于每个项目,您都应该从一开始就设置所有信息,包括onClick侦听器

这应该可以解决您的问题,并且您将可以退出使用setTag来区分视图的方式

避免在ViewHolder构造函数中设置onClick侦听器。

我相信您的问题在于

movieConstraint.setOnClickListener(this);

您不应该将其设置为ConstraintLayout ,将上面的行更改为此

itemView.setOnClickListener(this);

并没有什么错在你的设置onClickListenerViewHolder构造。

编辑:

为了在onClick获得位置,您可以使用getAdapterPosition()方法。

暂无
暂无

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

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