Android's RecyclerView Adapter methods not called - android

When I am logging in (with google mail) the LoginFragment is being replaced with the DrinkCategoryFragment which contains a RecyclerView.
The items are fetched from Firebase Database properly, but the layout is not there and I can't figure why.
The RecyclerView is initialized inside DrinkCategoriesViewMvcImpl.java:
public class DrinkCategoriesViewMvcImpl implements DrinkCategoriesViewMvc {
private View rootView;
private RecyclerView recyclerView;
private FloatingActionButton shareButton;
private DrinkCategoriesAdapter adapter;
public DrinkCategoriesViewMvcImpl(LayoutInflater inflater, ViewGroup parent) {
initializeViews(inflater, parent);
}
#Override
public View getRootView() {
return rootView;
}
#Override
public void setOnDrinkCategoryClickListener(OnDrinkCategoryClickListener listener) {
}
#Override
public void bindDrinkCategories(List<DrinkCategory> drinkCategories) {
adapter.addDrinkCategories(drinkCategories);
adapter.notifyDataSetChanged();
}
private void initializeViews(LayoutInflater inflater, ViewGroup parent) {
rootView = inflater.inflate(R.layout.activity_main_list, parent, false);
shareButton = rootView.findViewById(R.id.fab_share);
setupRecyclerView();
}
private void setupRecyclerView() {
recyclerView = rootView.findViewById(R.id.recyclerView);
LinearLayoutManager layoutManager = new LinearLayoutManager(rootView.getContext(),LinearLayoutManager.VERTICAL,false);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setHasFixedSize(true);
adapter = new DrinkCategoriesAdapter(rootView.getContext());
recyclerView.setAdapter(adapter);
}
Here is the adapter class:
public class DrinkCategoriesAdapter extends RecyclerView.Adapter<DrinkCategoriesAdapter.CategoryItemHolder> {
private Context context;
private List<DrinkCategory> drinkCategories;
public DrinkCategoriesAdapter(Context context) {
this.context = context;
}
public void addDrinkCategories(List<DrinkCategory> drinkCategories) {
this.drinkCategories = drinkCategories;
}
#NonNull
#Override
public CategoryItemHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(context).inflate(R.layout.activity_main_list_item, parent, false);
return new CategoryItemHolder(itemView);
}
#Override
public void onBindViewHolder(#NonNull CategoryItemHolder holder, int position) {
if (drinkCategories != null && drinkCategories.size() > 0) {
holder.bindViews(drinkCategories.get(position));
}
}
#Override
public int getItemCount() {
if (drinkCategories != null) {
return drinkCategories.size();
}
return 0;
}
class CategoryItemHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private TextView title, subtitle;
private ImageView_3_2 poster;
public CategoryItemHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
title = itemView.findViewById(R.id.textview_title);
subtitle = itemView.findViewById(R.id.textview_subtitle);
poster = itemView.findViewById(R.id.imageview_background);
}
#Override
public void onClick(View v) {
}
public void bindViews(DrinkCategory drinkCategory) {
title.setText(drinkCategory.getTitle());
// TODO: subtitle will be set from sharedpreferences
}
}
}
Here are also the layout file:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
xmlns:android="http://schemas.android.com/apk/res/android"
tools:background="#color/colorPrimary">
<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/recyclerView"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab_share"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:layout_marginEnd="16dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="16dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:src="#drawable/ic_share_black_24dp"
app:fabSize="normal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1.0" />
</android.support.constraint.ConstraintLayout>
Why is this happening? (project on Github)

You need to check your DrinkCategoryFragment class.
As you do not return the view you want to inflate
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
viewMvc = new DrinkCategoriesViewMvcImpl(inflater, container);
// Not return the view you want to inflate
return super.onCreateView(inflater, container, savedInstanceState);
}
try this it works for you
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
viewMvc = new DrinkCategoriesViewMvcImpl(inflater, container);
return viewMvc.getRootView();
}

Related

Data from the collection in the firestore is not output to the recycler

I'm creating an application in which I want to show about all guitar chords. To do this, I created a database with the name of the chords (chord_name) and I want to output it as a list (RecyclerView) in a fragment, but it doesn't come out. At the same time, the application works fine and nothing crashes, but the list is not shown
screen my application on phone
сlass FragmentChords
public class FragmentChords extends Fragment {
private FirebaseFirestore db = FirebaseFirestore.getInstance();
private CollectionReference chordsRef = db.collection("chords");
private ChordsAdapter adapter;
#Override
#PropertyName("chord_name")
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_chords, container, false);
RecyclerView recyclerView = view.findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
Query query = chordsRef.orderBy("chord_name", Query.Direction.DESCENDING);
FirestoreRecyclerOptions<Chords> options = new FirestoreRecyclerOptions.Builder<Chords>()
.setQuery(query,Chords.class)
.build();
adapter = new ChordsAdapter(options);
recyclerView.setAdapter(adapter);
return view;
}
#Override
public void onStart() {
super.onStart();
adapter.startListening();
}
#Override
public void onStop() {
super.onStop();
adapter.stopListening();
}
}
class Chords
public class Chords {
public String chord_name;
public Chords() {
}
public Chords(String chord_name) {
this.chord_name = chord_name;
}
#PropertyName("chord_name")
public String getChord_name() {
return chord_name;
}
public void setChord_name(String chord_name) {
this.chord_name = chord_name;
}
}
class ChordsAdapter
public class ChordsAdapter extends FirestoreRecyclerAdapter<Chords, ChordsAdapter.ChordsHolder> {
public ChordsAdapter(#NonNull FirestoreRecyclerOptions<Chords> options) {
super(options);
}
#Override
protected void onBindViewHolder(#NonNull ChordsHolder holder, int position, #NonNull Chords model) {
holder.textViewChordName.setText(model.getChord_name());
}
#NonNull
#Override
public ChordsHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_chords_item,
parent, false);
return new ChordsHolder(v);
}
class ChordsHolder extends RecyclerView.ViewHolder {
TextView textViewChordName;
public ChordsHolder(#NonNull View itemView) {
super(itemView);
textViewChordName = itemView.findViewById(R.id.chords_chord_name);
}
}
}
fragment_chords.xml
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/title_bar_layout_chords"
tools:listitem="#layout/recycler_chords_item" />
recycler_chords_item.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:orientation="vertical"
app:cardBackgroundColor="#color/backgroundApp"
app:cardCornerRadius="8dp"
app:cardElevation="8dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="52dp"
android:layout_marginHorizontal="16dp"
android:orientation="horizontal">
<TextView
android:id="#+id/chords_chord_name"
android:layout_width="200dp"
android:layout_height="52dp"
android:gravity="center_vertical"
android:text="Chord name"
android:textColor="#color/textWhite"
android:textSize="20sp" />
<ImageView
android:id="#+id/chords_image_info"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="#drawable/ic_info"
app:tint="#color/textWhite"
android:contentDescription="TODO" />
</RelativeLayout>
</androidx.cardview.widget.CardView>

How to Call Interface method from Xml using Data Binding?

Here's my Fragment:
public class Fragment_Cities extends Fragment implements Adapter_Cities.CitiesListener {
private Adapter_Cities adapterCities;
private FragmentCitiesBinding binding;
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
binding = FragmentCitiesBinding.inflate(inflater, container, false);
return binding.getRoot();
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
binding.recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
adapterCities = new Adapter_Cities(this);
binding.recyclerView.setAdapter(adapterCities);
ViewModel_Cities viewModelCities = new ViewModelProvider(this).get(ViewModel_Cities.class);
viewModelCities.getLiveDataCities().observe(getViewLifecycleOwner(), model_cities ->
adapterCities.setAdapterData(model_cities));
}
#Override
public void onCitySelected(Model_Cities city) {
if (!alertDialog.isShowing()) alertDialog.show();
new DialogFragment_Map().newInstance(city.getName(), city.getLatLon(), this).
show(requireActivity().getSupportFragmentManager(), null);
}
}
**
Here's my Adapter:
**
public class Adapter_Cities extends RecyclerView.Adapter<Adapter_Cities.MyViewHolder> implements Filterable {
private List<Model_Cities> cityList, cityListFiltered;
public CitiesListener citiesListener;
public class MyViewHolder extends RecyclerView.ViewHolder {
private final RowCityBinding rowCityBinding;
public MyViewHolder(View itemView) {
super(itemView);
rowCityBinding = RowCityBinding.bind(itemView);
// itemView.setOnClickListener(v -> recyclerViewItemClickListener.onCitySelected(cityListFiltered.get(getBindingAdapterPosition())));
}
}
public Adapter_Cities(CitiesListener citiesListener) {
this.citiesListener = citiesListener;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_city, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(Adapter_Cities.MyViewHolder holder, int position) {
holder.rowCityBinding.setModel(cityListFiltered.get(position));
holder.rowCityBinding.executePendingBindings();
}
public void setAdapterData(List<Model_Cities> cityList) {
this.cityList = cityList;
this.cityListFiltered = cityList;
notifyDataSetChanged();
}
#Override
public int getItemCount() {
return cityListFiltered == null ? 0 : cityListFiltered.size();
}
public interface CitiesListener {
void onCitySelected(Model_Cities city);
}
}
**
Here's my XML Layout:
**
<data>
<variable
name="callback"
type="com.base.assignment.adapters.Adapter_Cities.CitiesListener" />
<variable
name="model"
type="com.base.assignment.models.Model_Cities" />
</data>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="15dp"
android:background="#color/white"
android:onClick="#{()->callback.onCitySelected(model)}">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{model.title}"
android:textColor="#color/black"
android:textSize="15sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{model.subTitle}"
android:textColor="#color/black"
android:textSize="12sp" />
</LinearLayout>
</androidx.cardview.widget.CardView>
**
Here's the result i got:
**
My actual requirement is when user clicks on RecyclerView Item, the app must show a DialogFragment which should be called by a Fragment. So, I'm trying to trigger onClick of RecyclerView layout through XML, and the action that should happen on clicking is -> The information of clicked item should be sent to Fragment with Model Object as it's parameter.
Whereas When I clicked on Recyclerview Item no action is been happening. No crashes, no information in logcat, no updates in App UI.
As DataBinding shows the Compile time errors, i am seeing the below errors:
And right to it, i see the code details of the issue (as attached below):
For that set your listener interface for layout within onBindViewHolder().
#Override
public void onBindViewHolder(Adapter_Cities.MyViewHolder holder, int position) {
holder.rowCityBinding.setCallback(citiesListener);
holder.rowCityBinding.setModel(cityListFiltered.get(position));
holder.rowCityBinding.executePendingBindings();
}

RecyclerView with GridLayoutManager in ViewPAger2 shows nothing in first 3 page

I want to create a custom calendarView with ViewPager2 and RecyclerView . When I run the app its showing nothing in 3 first page! But when I scroll it other pages are fine ! This problem happening in android 7.0.0 and below and for android 7.1.1 and above is ok and works good. I created a custom calendar before in same way but now its not working !
Adapter for ViewPager :
public class SmartCalendarViewAdapter extends FragmentStateAdapter {
public SmartCalendarViewAdapter(#NonNull FragmentActivity fragmentActivity) {
super(fragmentActivity);
}
public SmartCalendarViewAdapter(#NonNull Fragment fragment) {
super(fragment);
}
#NonNull
#Override
public Fragment createFragment(int pos) {
return SmartCalendarFragment.getInstance(pos);
}
#Override
public int getItemCount() {
return Integer.MAX_VALUE;
}
}
Calendar Fragment :
public class SmartCalendarFragment extends Fragment {
private RecyclerView mCalendarRecyclerView;
private TextView txtPos;
private int mPosition;
public static SmartCalendarFragment getInstance(int position) {
SmartCalendarFragment smartCalendarFragment = new SmartCalendarFragment();
Bundle bundle = new Bundle();
bundle.putInt("mPosition", position);
smartCalendarFragment.setArguments(bundle);
return smartCalendarFragment;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle bundle = getArguments();
if (bundle != null) {
mPosition = bundle.getInt("mPosition");
}
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.smart_calendar_fragment_layout, container, false);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
findViews(view);
ArrayList<Integer> models = new ArrayList<>();
for (int i = 1; i <= 42; i++) {
models.add(i);
}
mCalendarRecyclerView.setLayoutManager(new GridLayoutManager(getContext(), 7));
CalendarCellAdapter adapter = new CalendarCellAdapter(models);
mCalendarRecyclerView.setAdapter(adapter);
txtPos.setText(String.valueOf(mPosition));
}
private void findViews(View view) {
mCalendarRecyclerView = view.findViewById(R.id.smart_calendar_recyclerView);
txtPos = view.findViewById(R.id.txtPos);
}
}
Inner RecyclerView Adapter :
public class CalendarCellAdapter extends RecyclerView.Adapter<CalendarCellAdapter.CellViewHolder> {
private List<Integer> mSmartCalendarCellModels;
public CalendarCellAdapter(List<Integer> smartCalendarCellModels) {
mSmartCalendarCellModels = smartCalendarCellModels;
}
#NonNull
#Override
public CellViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int i) {
View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.item_attendance_calendar_cell_layout,parent,false);
return new CellViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull CellViewHolder cellViewHolder, int i) {
cellViewHolder.bindView(mSmartCalendarCellModels.get(i));
}
#Override
public int getItemCount() {
return mSmartCalendarCellModels.size();
}
class CellViewHolder extends RecyclerView.ViewHolder {
TextView mTextView;
public CellViewHolder(#NonNull View itemView) {
super(itemView);
mTextView=itemView.findViewById(R.id.item_attendance_cell_txtDate);
}
void bindView(Integer model){
mTextView.setText(String.valueOf(model));
}
}
}
MainActivity :
public class MainActivity extends AppCompatActivity {
ViewPager2 mViewPager2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mViewPager2=findViewById(R.id.viewPager2);
SmartCalendarViewAdapter adapter=new SmartCalendarViewAdapter(this);
mViewPager2.setOffscreenPageLimit(1);
mViewPager2.setAdapter(adapter);
mViewPager2.setCurrentItem(Integer.MAX_VALUE/2,false);
}
}
Fragment layout file :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/smart_calendar_fragment_root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layoutDirection="rtl"
android:orientation="vertical">
<TextView
android:id="#+id/txtPos"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/smart_calendar_recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:overScrollMode="never" />
</LinearLayout>
Cell Layout file :
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/item_attendance_cell_root"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<TextView
android:id="#+id/item_attendance_cell_txtDate"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="w,1:1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:padding="4dp"
android:layout_marginTop="4dp"
android:layout_marginBottom="4dp"
tools:text="1" />
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity Layout file :
<androidx.constraintlayout.widget.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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.viewpager2.widget.ViewPager2
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/viewPager2"
android:background="#ADABF3"
app:layout_constraintTop_toTopOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
Changing the width of the TextView in your cell layout file to wrap_content fixes the issue.
Not sure why it only affects the preloaded pages, and why only on Android 7 and lower... but setting the TextView to have 1:1 ratio has no visible effect anyway, cos the parent is stretched to fill the space to allow for 7 cells across the screen width.

Why these random marks are appearing in every recyclerview and viewpager items?

I have 2 recycler views and a view pager in a fragment.
Everything else works fine but both recycler view items are showing a random mark on the upper left corner of every items. And same thing is happening for the view pager items.
This fragment is in a fragment activity and view pager is using pager adapter. And I am using Picasso library to load images on the items and also using network policy to cache the images in disk.
recycler view items appearing like this
view pager items appearing like this
Recycler View adapter
public class CourseListAdapter extends RecyclerView.Adapter<CourseListAdapter.CourseListViewHolder> {
public static final int HOME_PAGE = 1;
public static final int DISPLAY_COURSE = 2;
private Picasso mPicasso;
private List<DisplayCourse> courseList;
private static final String TAG = "CourseListAdapter";
private OnItemClickListener mListener;
public interface OnItemClickListener {
void onItemClick(int position, View view);
}
private String mSender;
public void setOnItemClickListener(OnItemClickListener listener) {
mListener = listener;
}
public CourseListAdapter(List<DisplayCourse> courseList, String sender) {
this.courseList = courseList;
this.mSender = sender;
mPicasso = Picasso.get();
}
#NonNull
#Override
public CourseListViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
switch (viewType) {
case 1:
View view1 = inflater.inflate(R.layout.recom_course_home_layout, parent, false);
return new CourseListViewHolder(view1, mListener);
case 2:
View view2 = inflater.inflate(R.layout.display_course_layout, parent, false);
return new CourseListViewHolder(view2, mListener);
default:
View view3 = inflater.inflate(R.layout.section_video_item_layout, parent, false);
return new CourseListViewHolder(view3, mListener);
}
}
#Override
public void onBindViewHolder(#NonNull CourseListViewHolder holder, int position) {
holder.title.setText(courseList.get(position).getCourseTitle());
mPicasso.load(courseList.get(position).getThumbnailURL())
.networkPolicy(NetworkPolicy.OFFLINE)
.into(holder.thumbnail, new Callback() {
#Override
public void onSuccess() {
}
#Override
public void onError(Exception e) {
mPicasso.load(courseList.get(position).getThumbnailURL())
.error(R.drawable.ofklogo)
.into(holder.thumbnail, new Callback() {
#Override
public void onSuccess() {
}
#Override
public void onError(Exception e) {
}
});
}
});
}
#Override
public int getItemCount() {
return courseList.size();
}
public static class CourseListViewHolder extends RecyclerView.ViewHolder {
ImageView thumbnail;
TextView title;
public CourseListViewHolder(#NonNull View itemView, final OnItemClickListener listener) {
super(itemView);
title = itemView.findViewById(R.id.courseTitle);
thumbnail = itemView.findViewById(R.id.courseThumbNailImageView);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int position = getAdapterPosition();
if (listener != null) {
if (position != RecyclerView.NO_POSITION) {
listener.onItemClick(position, view);
}
}
}
});
}
}
#Override
public int getItemViewType(int position) {
if (mSender.equals("home_page")) {
return HOME_PAGE;
} else if (mSender.equals("displayCourse")) {
return DISPLAY_COURSE;
}
return -1;
}
}
View pager adapter
public class VideoSliderAdapter extends PagerAdapter {
private boolean doNotifyDataSetChangedOnce = false;
private static final String TAG = "VideoSliderAdapter";
private YouTubePlayerView youTubePlayerView;
private View gradientView;
private ImageView thumbNail;
private LinearLayout layout;
private Picasso picasso;
private List<Video> videoList;
private Context mContext;
private Lifecycle mLifeCycle;
public VideoSliderAdapter(List<Video> videoList, Context context, Lifecycle lifecycle) {
this.videoList = videoList;
this.mContext = context;
this.mLifeCycle = lifecycle;
doNotifyDataSetChangedOnce = true;
picasso = Picasso.get();
}
#Override
public int getCount() {
if (doNotifyDataSetChangedOnce) {
doNotifyDataSetChangedOnce = false;
notifyDataSetChanged();
}
return videoList.size();
}
#Override
public int getItemPosition(#NonNull Object object) {
return POSITION_NONE;
}
#Override
public boolean isViewFromObject(#NonNull View view, #NonNull Object object) {
return (view == (CardView) object);
}
#NonNull
#Override
public Object instantiateItem(#NonNull ViewGroup container, int position) {
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.video_paly_layout, container, false);
TextView title = view.findViewById(R.id.videoTitle);
title.setText(videoList.get(position).getVideoTitle());
gradientView = view.findViewById(R.id.gradientView);
thumbNail = view.findViewById(R.id.videoThumbNail);
picasso.load(videoList.get(position).getVideoThumbNail())
.networkPolicy(NetworkPolicy.OFFLINE)
.into(thumbNail, new Callback() {
#Override
public void onSuccess() {
}
#Override
public void onError(Exception e) {
picasso.load(videoList.get(position).getVideoThumbNail())
.error(R.drawable.ofklogo)
.into(thumbNail, new Callback() {
#Override
public void onSuccess() {
}
#Override
public void onError(Exception e) {
}
});
}
});
layout = view.findViewById(R.id.videoPlayLayout);
youTubePlayerView = view.findViewById(R.id.youtube_player_view);
mLifeCycle.addObserver(youTubePlayerView);
new AddListener(youTubePlayerView, position).execute();
container.addView(view);
return view;
}
#Override
public void destroyItem(#NonNull ViewGroup container, int position, #NonNull Object object) {
container.removeView((CardView) object);
}
Recycler view holder layout
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="150dp"
android:layout_height="200dp"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:clickable="true"
android:focusable="true"
android:foreground="?android:attr/selectableItemBackground"
app:cardCornerRadius="8dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/courseThumbNailImageView"
android:layout_width="match_parent"
android:layout_height="130dp"
android:layout_alignParentTop="true"
android:scaleType="fitXY"
android:src="#drawable/art_thumb" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/courseThumbNailImageView">
<TextView
android:id="#+id/courseTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:maxLines="2"
android:text="Course title"
android:textAlignment="center"
android:textColor="#android:color/black"
android:textStyle="bold" />
</RelativeLayout>
</RelativeLayout>
</androidx.cardview.widget.CardView>
view pager layout
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="200dp"
app:cardCornerRadius="8dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.pierfrancescosoffritti.androidyoutubeplayer.core.player.views.YouTubePlayerView
android:id="#+id/youtube_player_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:autoPlay="false" />
<ImageView
android:id="#+id/videoThumbNail"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY" />
<View
android:id="#+id/gradientView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/gradient_drawable" />
<LinearLayout
android:id="#+id/videoPlayLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="16dp">
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="8dp"
android:src="#drawable/play_button" />
<TextView
android:id="#+id/videoTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="2"
android:text="Course title"
android:textColor="#android:color/white"
android:textStyle="bold" />
</LinearLayout>
</RelativeLayout>
</androidx.cardview.widget.CardView>
When loading image using Picasso use: setIndicatorsEnabled(false)
picasso.load(videoList.get(position).getVideoThumbNail())
.networkPolicy(NetworkPolicy.OFFLINE)
.setIndicatorsEnabled(false)
.into(...);
The colors indicate this:
Green: Image is fetched from memory
Blue: Image is fetched from disk
Red: Image is fetched from network

RecyclerView items inside BottomSheetDialogFragment need double touch after fast scrolling

I have a RecyclerView inside BottomSheetDialogFragment. The RecyclerView items touch working normally when it's scrolling slowly.
But when the RecyclerView is scrolled fast and after the list stops (without touching), than touching on any item doesn't work on fast touch. It needs double touching.
See in the below example gif, when touching on Andhra Pradesh it's working fine. After slow scrolling, touching on Haryana also works fine. Then doing a fast scroll and touching on Punjab doesn't work on the first touch. Touching again it works.
Following is the code:
OperatorListDialogFragment.java
package com.*;
import *;
public class OperatorListDialogFragment extends BottomSheetDialogFragment{
private static final String ARG_NAME = "item_name";
private static final String ARG_LOGO = "item_logo";
private Listener mListener;
private String header;
private Context mContext;
public static OperatorListDialogFragment newInstance(String[] name, int[] logo, String header) {
final OperatorListDialogFragment fragment = new OperatorListDialogFragment();
final Bundle args = new Bundle();
args.putStringArray(ARG_NAME, name);
args.putIntArray(ARG_LOGO, logo);
args.putString("header", header);
fragment.setArguments(args);
return fragment;
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_operator_list_dialog_list_dialog, container, false);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
TextView headerTV = view.findViewById(R.id.title);
headerTV.setText(getArguments().getString("header"));
final RecyclerView recyclerView = view.findViewById(R.id.list);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.setAdapter(new OperatorAdapter(getArguments().getStringArray(ARG_NAME), getArguments().getIntArray(ARG_LOGO)));
view.findViewById(R.id.dismiss).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dismiss();
}
});
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
mContext = context;
final Fragment parent = getParentFragment();
if (parent != null) {
mListener = (Listener) parent;
} else {
mListener = (Listener) context;
}
}
#Override
public void onDetach() {
mListener = null;
super.onDetach();
}
public interface Listener {
void onFilterSelected(String selected, String selectedQuery);
}
private class ViewHolder extends RecyclerView.ViewHolder {
final TextView text;
ImageView logo;
ViewHolder(LayoutInflater inflater, ViewGroup parent) {
// TODO: Customize the item layout
super(inflater.inflate(R.layout.fragment_operator_list_dialog_list_dialog_item, parent, false));
text = itemView.findViewById(R.id.tv_operator_name);
logo = itemView.findViewById(R.id.iv_recharge_provider_icon);
}
}
private class OperatorAdapter extends RecyclerView.Adapter<ViewHolder> {
private String[] mNames;
private int[] mLogos;
OperatorAdapter(String[] name, int[] logo) {
mNames = name;
mLogos = logo;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new ViewHolder(LayoutInflater.from(parent.getContext()), parent);
}
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
holder.text.setText(mNames[position]);
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.e("clicked", "" + position);
}
});
}
#Override
public int getItemCount() {
return mNames.length;
}
}
}
dialog.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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:layout_height="match_parent"
android:layout_width="match_parent"
>
<ImageView
android:focusable="true"
android:clickable="true"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="Close"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
android:id="#+id/dismiss"
android:padding="14dp"
android:src="#drawable/ic_close_black_24dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="#+id/title"
app:layout_constraintTop_toTopOf="#id/dismiss"
app:layout_constraintBottom_toBottomOf="#id/dismiss"
app:layout_constraintLeft_toRightOf="#id/dismiss"
android:padding="14dp"
android:textAppearance="#style/TextAppearance.AppCompat.Medium"
tools:text="Select operator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<View
app:layout_constraintTop_toBottomOf="#id/dismiss"
android:background="#969696"
android:layout_width="match_parent"
android:layout_height="0.5dp"/>
<androidx.recyclerview.widget.RecyclerView
app:layout_constraintTop_toBottomOf="#id/dismiss"
app:layout_constraintBottom_toBottomOf="parent"
android:id="#+id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
app:layout_constrainedHeight="true"
android:paddingTop="#dimen/list_item_spacing_half"
android:paddingBottom="#dimen/list_item_spacing_half"
tools:context=".fragments.OperatorListDialogFragment"
tools:listitem="#layout/fragment_operator_list_dialog_list_dialog_item" />
</androidx.constraintlayout.widget.ConstraintLayout>
recycler_item.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:gravity="center_vertical"
android:orientation="horizontal"
android:id="#+id/ll_operator_list_wrapper"
android:background="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:visibility="gone"
android:layout_marginLeft="16dp"
android:id="#+id/iv_recharge_provider_icon"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginVertical="16dp"
android:layout_centerVertical="true"
android:src="#drawable/ic_bsnl_logo"
tools:visibility="visible"/>
<TextView
android:padding="16dp"
android:textColor="#212121"
android:textSize="14sp"
android:ellipsize="end"
android:id="#+id/tv_operator_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="false"
android:text="BSNL"
android:layout_toRightOf="#+id/iv_recharge_provider_icon"
android:layout_centerInParent="true"/>
<View
android:layout_below="#id/iv_recharge_provider_icon"
android:id="#+id/divider0"
android:background="#eeeeee"
android:visibility="visible"
android:layout_width="wrap_content"
android:layout_height="1dp"
android:layout_marginLeft="16dp"
android:layout_toRightOf="#+id/iv_recharge_provider_icon"
/>
</RelativeLayout>
add android:nestedScrollingEnabled="false" in RecyclerView

Categories

Resources