我有一个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);
}
}
}
2条答案
按热度按时间yc0p9oo01#
我终于找到了解决办法。我的recyclerview布局有一个nestedscrollview
android:nestedScrollingEnabled="false"
我的回收站解决了我的问题。我不知道为什么,但它解决了我的问题eblbsuwk2#
RecyclerView
重用视图持有者以提高性能。你也可以说它回收了视图持有者——这就是它的名字来源。RecyclerView
适配器将不会创建超过其所需数量的视图持有者。视图持有者的数量大致可以等于:因此,它将生成填充屏幕的视图持有者数量+1个从屏幕中抽出的项目(例如,在回收器视图的底部),以平滑滚动动画并消除任何问题。
在此之后:
onCreateViewHolder
仅用于创建视图持有者!永远不要将任何数据绑定到onCreateViewHolder
.如果适配器中有100个要显示的项目,但设备的屏幕只能显示10个,那么滚动列表时将有11个视图保持器可重复使用。
onBindViewHolder
每次显示项目时都会调用-这是将数据附加到视图持有者的位置。