android recyclerview first and last item click在双击首次加载后工作

rqmkfv5c  于 2021-07-05  发布在  Java
关注(0)|答案(2)|浏览(289)

我有一个recycerview。在中有项目单击事件 onCreateViewHolder 方法和imageview click事件 onBindViewHolder 方法。令人惊讶的是,当recyclerview首次加载时 first and last 项目点击在第二次点击后工作,如果没有滚动,则在每次点击后工作。再次当我滚动recyclerview时,第一个和最后一个项目也会发生相同的情况,如首次加载。我想不出是什么问题
下面是我的recyclerview布局 @+id/recyclerViewForFilteredCourses 是回收站视图吗

<androidx.coordinatorlayout.widget.CoordinatorLayout 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"
    tools:context=".Activities.CoursesActivity">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <include layout="@layout/toolbar_with_search"
            android:id="@+id/toolbar" />

        <com.github.ybq.android.spinkit.SpinKitView
            xmlns:app="http://schemas.android.com/apk/res-auto"
            android:id="@+id/progressBar"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_centerHorizontal="true"
            app:SpinKit_Color="@color/textColorGrey"
            android:visibility="gone"
            android:elevation="200dp"
            style="@style/SpinKitView.Circle"/>

        <!--This textview and the recycler view is responsible for filtered course section-->
        <TextView
            android:id="@+id/filterResultTitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Showing X Courses"
            android:layout_below="@+id/toolbar"
            style="@style/headerTitleLabel"/>

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recyclerViewForFilteredCourses"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/filterResultTitle"
            android:layout_above="@+id/bottomNavigationView"
            android:paddingHorizontal="14dp"
            android:clipToPadding="false"
            android:layout_marginTop="10dp"
            android:overScrollMode="never"/>

        <!--This is the floating filter button-->
        <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:id="@+id/floatingFilterButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:clickable="true"
            android:layout_alignParentRight="true"
            android:layout_marginRight="25dp"
            android:layout_marginBottom="25dp"
            android:layout_alignParentBottom="true"
            android:backgroundTint="#273647"
            android:elevation="6dp"
            app:fabSize="normal"
            app:borderWidth="0dp"
            android:src="@drawable/filter"
            android:onClick="handleFilterButton" />
    </RelativeLayout>

    <androidx.core.widget.NestedScrollView
        android:id="@+id/bottomSheet"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#FEFFFF"
        app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"
        app:behavior_hideable="true"
        app:behavior_peekHeight = "0dp">
        <include layout="@layout/course_filter_page" />
    </androidx.core.widget.NestedScrollView>

    </androidx.coordinatorlayout.widget.CoordinatorLayout>

下面是我的oncreatevieholder项目

public CoursesAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.course_cell2, parent, false);
        final ViewHolder holder = new ViewHolder(view);
        view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                final Course currentCourse = mCourses.get(holder.getAdapterPosition());
                switchToCourseDetailsActivity(currentCourse);
            }
        });
        return holder;
    }

    private void switchToCourseDetailsActivity(Course currentCourse) {
        Intent intent = new Intent(mContext, CourseDetailsActivity .class);
        intent.putExtra("Course", currentCourse);
        mContext.startActivity(intent);
    }

下面是我完整的onbindviewholder

public class CoursesAdapter extends RecyclerView.Adapter<CoursesAdapter.ViewHolder> {
private static final String TAG = "Courses List Adapter";
private static final String TAG2 = "Checker";

//vars
private Context mContext;
private ArrayList<Course> mCourses = new ArrayList<>();

Matcher matcher;

public CoursesAdapter(Context context, ArrayList<Course> courses) {
    mCourses = courses;
    mContext = context;

}

@NonNull
@Override
public CoursesAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.course_cell2, parent, false);
    final ViewHolder holder = new ViewHolder(view);
    return holder;
     }

 private void switchToCourseDetailsActivity(Course currentCourse) {
    Intent intent = new Intent(mContext, CourseDetailsActivity .class);
    intent.putExtra("Course", currentCourse);
    mContext.startActivity(intent);
}

@Override
public void onBindViewHolder(@NonNull final CoursesAdapter.ViewHolder holder, final int position) {
    final Course currentCourse = mCourses.get(position);

    holder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            switchToCourseDetailsActivity(currentCourse);
        }
    });

    holder.name.setText(currentCourse.getTitle());
   // holder.coursePrice.setText(currentCourse.getPrice());
    holder.totalNumberOfRating.setText("( "+currentCourse.getTotalNumberRating()+" )");
    //holder.instructorName.setText("by "+currentCourse.getInstructor()+" "+currentCourse.getBiography());
    holder.starRating.setRating(currentCourse.getRating());
    holder.rating.setText((" "+currentCourse.getRating()+" "));

    if(currentCourse.getIs_bestseller().equals("yes")){
        holder.tvBestseller.setVisibility(View.VISIBLE);
    }else{
        holder.tvBestseller.setVisibility(View.GONE);
    }

    if(currentCourse.getCourseOverviewUrl()!=null && currentCourse.getCourseOverviewProvider()!=null && currentCourse.getCourseOverviewProvider().equals("youtube")){

        //Extract video id from url
        String pattern = "(?<=watch\\?v=|/videos/|embed\\/|youtu.be\\/|\\/v\\/|\\/e\\/|watch\\?v%3D|watch\\?feature=player_embedded&v=|%2Fvideos%2F|embed%\u200C\u200B2F|youtu.be%2F|%2Fv%2F)[^#\\&\\?\\n]*";

        Pattern compiledPattern = Pattern.compile(pattern);
        matcher = compiledPattern.matcher(currentCourse.getCourseOverviewUrl()); //url is youtube url for which you want to extract the id.

        if (matcher.find()) {
                holder.play_video.setVisibility(View.VISIBLE);
                holder.play_video1.setVisibility(View.VISIBLE);

        } else{
            holder.play_video.setVisibility(View.GONE);
            holder.play_video1.setVisibility(View.GONE);
        }

    } else{
        holder.play_video.setVisibility(View.GONE);
        holder.play_video1.setVisibility(View.GONE);
    }

    holder.play_video.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            final BottomSheetDialog dialog3 = new BottomSheetDialog(mContext);
            dialog3.setContentView(R.layout.bottom_videoplay);
            if(!dialog3.isShowing()) {
                dialog3.show();
            }
            dialog3.setCancelable(true);
            final WebView web_view = (WebView) dialog3.findViewById(R.id.youtube_web_view);
            final ProgressBar progressBar2 = (ProgressBar) dialog3.findViewById(R.id.progressBar2);
            final TextView tvTitle2 = (TextView) dialog3.findViewById(R.id.tvTitle2);
            final TextView tvEnroll = (TextView) dialog3.findViewById(R.id.tvEnroll);
            tvTitle2.setText(currentCourse.getTitle());

            tvEnroll.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    switchToCourseDetailsActivity(currentCourse);
                }
            });

            //String myVideoYoutubeId = "Wwy9aibAd54";
            String myVideoYoutubeId;
            WebSettings webSettings = web_view.getSettings();
            webSettings.setJavaScriptEnabled(true);
            webSettings.setLoadWithOverviewMode(true);
            webSettings.setUseWideViewPort(true);

            myVideoYoutubeId=matcher.group();
            web_view.loadUrl("https://www.youtube.com/embed/" + myVideoYoutubeId);

            web_view.setWebViewClient(new WebViewClient() {
                @Override
                public boolean shouldOverrideUrlLoading(WebView view, String url) {
                    return false;
                }
            });

            web_view.setWebViewClient(new WebViewClient() {

                @Override
                public void onPageStarted(WebView view, String url, Bitmap favicon) {
                    super.onPageStarted(view, url, favicon);
                    progressBar2.setVisibility(View.VISIBLE);
                }

                @Override
                public void onPageFinished(WebView view, String url) {
                    super.onPageFinished(view, url);
                    progressBar2.setVisibility(View.GONE);

                    //to enable autoplay ref:https://stackoverflow.com/questions/28039209/android-webview-youtube-embed-video-autoplay-not-working/45655979#45655979
                    long delta = 100;
                    long downTime = SystemClock.uptimeMillis();
                    float x = view.getLeft() + (view.getWidth()/2);
                    float y = view.getTop() + (view.getHeight()/2);

                    MotionEvent tapDownEvent = MotionEvent.obtain(downTime, downTime + delta, MotionEvent.ACTION_DOWN, x, y, 0);
                    tapDownEvent.setSource(InputDevice.SOURCE_CLASS_POINTER);
                    MotionEvent tapUpEvent = MotionEvent.obtain(downTime, downTime + delta + 2, MotionEvent.ACTION_UP, x, y, 0);
                    tapUpEvent.setSource(InputDevice.SOURCE_CLASS_POINTER);

                    view.dispatchTouchEvent(tapDownEvent);
                    view.dispatchTouchEvent(tapUpEvent);

                }

            });

        }
    });

    holder.play_video1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            holder.play_video.performClick();
        }
    });

    if(currentCourse.getIs_mentor()!=null && currentCourse.getIs_mentor().equals("1")){
        holder.instructorName.setVisibility(View.VISIBLE);
        holder.tvMentor.setVisibility(View.GONE);

        if(currentCourse.getBiography()!=null) {
            holder.instructorName.setText("by " + currentCourse.getInstructor() + " " + currentCourse.getBiography());
        }else{
            holder.instructorName.setText("by " + currentCourse.getInstructor());
        }

    } else{
        //holder.tvMentor.setVisibility(View.GONE);
        holder.instructorName.setVisibility(View.GONE);
        holder.tvMentor.setVisibility(View.VISIBLE);

        if(currentCourse.getBiography()!=null) {
            holder.tvMentor.setText("by " + currentCourse.getInstructor() + " " + currentCourse.getBiography());
        } else{
            holder.tvMentor.setText("by " + currentCourse.getInstructor());
        }
    }

  if(currentCourse.getMain_price()!=null && !currentCourse.getPrice().equals("Free")){
        String  c_price = currentCourse.getPrice().substring(0, currentCourse.getPrice().length() - 1);
        Double main_price=Double.parseDouble(currentCourse.getMain_price());
        Double current_price=Double.parseDouble(c_price);

        if(current_price<main_price){
            holder.tvcompare.setVisibility(View.VISIBLE);
            holder.tvDiscountprice.setVisibility(View.VISIBLE);
            holder.tvDiscountprice.setText(Double.toString(main_price)+"Tk");

            Double diff=main_price-current_price;
            Double percent=diff*100/main_price;
            holder.tvcompare.setText(percent+"% OFF");

        }else{
            holder.tvDiscountprice.setVisibility(View.GONE);
            holder.tvcompare.setVisibility(View.GONE);
        }
    } else{
      holder.tvcompare.setVisibility(View.GONE);
      holder.tvDiscountprice.setVisibility(View.GONE);
  }

    if(!currentCourse.getPrice().equals("Free")) {
        String c_price = currentCourse.getPrice().substring(0, currentCourse.getPrice().length() - 1);
        holder.coursePrice.setText(c_price + "Tk");
    } else{
        holder.coursePrice.setText(currentCourse.getPrice());
    }

    if(currentCourse.getCourse_type()!=null){

        if(currentCourse.getCourse_type().equals("Course")){
            holder.tvCategory.setText("Lifetime Access");
            holder.image.setVisibility(View.VISIBLE);
            holder.play_video.setVisibility(View.VISIBLE);
            holder.monthly_couching.setVisibility(View.GONE);

            Glide.with(mContext)
                    .asBitmap()
                    .load(currentCourse.getThumbnail())
                    .into(holder.image);

        }

        if (currentCourse.getCourse_type().equals("MonthlyCouching")){
            holder.tvCategory.setText("Monthly Couching");
            holder.coursePrice.setText(holder.coursePrice.getText()+"/month");
            holder.image.setVisibility(View.GONE);
            holder.play_video.setVisibility(View.GONE);
            holder.monthly_couching.setVisibility(View.VISIBLE);
            Picasso.get().load(currentCourse.getThumbnail()).into(holder.image);
            Picasso.get().load(currentCourse.getThumbnail()).into(holder.image1);

            if(currentCourse.getOnline_classschedule()!=null){
                holder.layout_classschedule.setVisibility(View.VISIBLE);
                holder.tvClass_schedule.setText(currentCourse.getOnline_classschedule());
            } else{
                holder.layout_classschedule.setVisibility(View.GONE);
            }

        }

        if(currentCourse.getCourse_type().equals("FixedTermCouching")){

            holder.image.setVisibility(View.GONE);
            holder.play_video.setVisibility(View.GONE);
            holder.monthly_couching.setVisibility(View.VISIBLE);

            if(currentCourse.getDuration()!=null && currentCourse.getStart_date()!=null){

                long l = Long.parseLong(currentCourse.getStart_date());
                Date date = new Date(l);
                holder.tvCategory.setText(currentCourse.getDuration()+" Couching starting on "+date);
            }

            if(currentCourse.getOnline_classschedule()!=null){
                holder.layout_classschedule.setVisibility(View.VISIBLE);
                holder.tvClass_schedule.setText(currentCourse.getOnline_classschedule());
            } else{
                holder.layout_classschedule.setVisibility(View.GONE);
            }

        }

        if(currentCourse.getCourse_type().equals("Workshop")){

            holder.image.setVisibility(View.VISIBLE);
            holder.play_video.setVisibility(View.VISIBLE);
            holder.monthly_couching.setVisibility(View.GONE);

            if(currentCourse.getDuration()!=null && currentCourse.getStart_date()!=null){

                long l = Long.parseLong(currentCourse.getStart_date());
                Date date = new Date(l);
                holder.tvCategory.setText(currentCourse.getDuration()+" workshop starting on "+date);
            }
        }

    }

    if(currentCourse.getWeekly_class()!=null && currentCourse.getWeekly_class().equals("1")){
        holder.tvweekly_class.setVisibility(View.VISIBLE);

        if(currentCourse.getWeeklyonline_class()!=null && Integer.parseInt(currentCourse.getWeeklyonline_class())>0){
            holder.tvweekly_class.setText(holder.tvweekly_class.getText()+" "+currentCourse.getWeeklyonline_class());
        }

    } else{holder.tvweekly_class.setVisibility(View.GONE);}

    if(currentCourse.getWeekly_exam()!=null && currentCourse.getWeekly_exam().equals("1")){
        holder.tvweekly_exam.setVisibility(View.VISIBLE);

        if(currentCourse.getWeeklyonline_test()!=null && Integer.parseInt(currentCourse.getWeeklyonline_test())>0){
            holder.tvweekly_exam.setText(holder.tvweekly_exam.getText()+" "+currentCourse.getWeeklyonline_test());
        }

    } else{holder.tvweekly_exam.setVisibility(View.GONE);}

    if(currentCourse.getReview_class()!=null && currentCourse.getReview_class().equals("1")){
        holder.tvreview_class.setVisibility(View.VISIBLE);
    } else{holder.tvreview_class.setVisibility(View.GONE);}

    if(currentCourse.getCourse_upload()!=null && currentCourse.getCourse_upload().equals("1")){
        holder.tvcourse_upload.setVisibility(View.VISIBLE);
    } else{holder.tvcourse_upload.setVisibility(View.GONE);}

    if(currentCourse.getRecord_upload()!=null && currentCourse.getRecord_upload().equals("1")){
        holder.tvrecord_upload.setVisibility(View.VISIBLE);
    } else{holder.tvrecord_upload.setVisibility(View.GONE);}

    if(currentCourse.getCourse_type()!=null && currentCourse.getCourse_type().equals("FixedTermCouching") && currentCourse.getLifetime_access()!=null && currentCourse.getLifetime_access().equals("1")){
        holder.tvlifetime_access.setVisibility(View.VISIBLE);
    } else{holder.tvlifetime_access.setVisibility(View.GONE);}

}

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

public class ViewHolder extends RecyclerView.ViewHolder{

    ImageView image,image1,play_video,play_video1;
    TextView name;
    TextView coursePrice;
    TextView instructorName;
    TextView rating;
    TextView totalNumberOfRating;
    RatingBar starRating;
    TextView tvweekly_class,tvweekly_exam,tvreview_class,tvcourse_upload,tvrecord_upload,tvlifetime_access,tvCategory,tvDiscountprice,tvMentor,tvcompare,tvBestseller,tvClass_schedule;
    RelativeLayout monthly_couching;
    LinearLayout layout_classschedule;

    public ViewHolder(View itemView) {
        super(itemView);
        image = itemView.findViewById(R.id.courseThumbnail);
        image1 = itemView.findViewById(R.id.courseThumbnail1);
        name = itemView.findViewById(R.id.courseTitle);
        coursePrice = itemView.findViewById(R.id.tvcoursePrice);
        instructorName = itemView.findViewById(R.id.instructorName);
        rating = itemView.findViewById(R.id.numericRating);
        totalNumberOfRating = itemView.findViewById(R.id.totalNumberOfRatingByUsers);
        starRating = itemView.findViewById(R.id.starRating);
        tvweekly_class=itemView.findViewById(R.id.tvweekly_class);
        tvweekly_exam=itemView.findViewById(R.id.tvweekly_exam);
        tvreview_class=itemView.findViewById(R.id.tvreview_class);
        tvcourse_upload=itemView.findViewById(R.id.tvcourse_upload);
        tvrecord_upload=itemView.findViewById(R.id.tvrecord_upload);
        tvlifetime_access=itemView.findViewById(R.id.tvlifetime_access);
        tvCategory=itemView.findViewById(R.id.tvCategory);
        tvDiscountprice=itemView.findViewById(R.id.tvDiscountprice);
        tvMentor=itemView.findViewById(R.id.tvMentor);
        play_video=itemView.findViewById(R.id.play_video);
        play_video1=itemView.findViewById(R.id.play_video1);
        tvcompare=itemView.findViewById(R.id.tvcompare);
        tvBestseller=itemView.findViewById(R.id.tvBestseller);
        monthly_couching=itemView.findViewById(R.id.monthly_couching);
        tvClass_schedule=itemView.findViewById(R.id.tvClass_schedule);
        layout_classschedule=itemView.findViewById(R.id.layout_classschedule);

    }
}
}
yc0p9oo0

yc0p9oo01#

我终于找到了解决办法。我的recyclerview布局有一个nestedscrollview android:nestedScrollingEnabled="false" 我的回收站解决了我的问题。我不知道为什么,但它解决了我的问题

eblbsuwk

eblbsuwk2#

RecyclerView 重用视图持有者以提高性能。你也可以说它回收了视图持有者——这就是它的名字来源。 RecyclerView 适配器将不会创建超过其所需数量的视图持有者。视图持有者的数量大致可以等于:

// consider it pseudocode
viewHoldersCount = recyclerView.height / viewHolder.height + 1

因此,它将生成填充屏幕的视图持有者数量+1个从屏幕中抽出的项目(例如,在回收器视图的底部),以平滑滚动动画并消除任何问题。
在此之后: onCreateViewHolder 仅用于创建视图持有者!永远不要将任何数据绑定到 onCreateViewHolder .
如果适配器中有100个要显示的项目,但设备的屏幕只能显示10个,那么滚动列表时将有11个视图保持器可重复使用。 onBindViewHolder 每次显示项目时都会调用-这是将数据附加到视图持有者的位置。

public CoursesAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.course_cell2, parent, false);
    return new ViewHolder(view);
}

public void onBindViewHolder(@NonNull final CoursesAdapter.ViewHolder holder, final int position) {
    final Course currentCourse = mCourses.get(position);

    holder.play_video.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
           // ...
        }
    }

    holder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            switchToCourseDetailsActivity(currentCourse);
        }
    });
}

相关问题