Android RecyclerView第一个和最后一个项目点击后双击第一次加载工作



我有一个recycerview。它具有CCD_ 1方法中的项目点击事件和CCD_。令人惊讶的是,当recycleview第一次加载first and last项目时,点击在第二次点击后工作,然后在每次点击后工作(如果不滚动的话(。当我再次滚动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%u200Cu200B2F|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);
}
}
}

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

我终于找到了一个解决方案。我的回收视图布局有嵌套的滚动视图在我的回收视图中添加onCreateViewHolder0解决了我的问题。我不知道为什么,但它解决了我的问题

最新更新