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.
Related
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>
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();
}
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
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();
}
I had an activity with a Listview containing text and green squares. I finally changed my mind and modified my code to use a fragment instead of an activity. But then my text color changed and I can't see the green squares anymore. I didn't changed anything in my list code or the color of the text so I don't understand what's happening.
Thank you for your help.
MainActivity is only used as a fragment container :
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentManager fm = getSupportFragmentManager();
Fragment fragment = fm.findFragmentById(R.id.ll_container);
if (fragment == null) {
fragment = new PollutionLevelsFragment();
fm.beginTransaction()
.add(R.id.ll_container, fragment)
.commit();
}
}
}
MainActivity layout
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/ll_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
The fragment class
public class PollutionLevelsFragment extends Fragment implements PollutionLevelsFragmentMVP.View {
private PollutionLevelAdapter plAdapter;
#BindString(R.string.city)
String city;
#BindString(R.string.aqicn_token)
String authToken;
#BindView(R.id.lv_pollution_levels)
ListView lvPollutionLevels;
#Inject
PollutionLevelsFragmentMVP.Presenter presenter;
private ViewModel pollutionData;
private ArrayList<String> testbidon;
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_pollution_levels, container, false);
ButterKnife.bind(this,view);
// Construct the data source
ArrayList<PollutionLevel> arrayOfPollutionLevel = new ArrayList<>();
// Create the adapter to convert the array to views
plAdapter = new PollutionLevelAdapter(getActivity().getApplicationContext(), arrayOfPollutionLevel);
lvPollutionLevels.setAdapter(plAdapter);
return view;
}
#Override
public void onStart() {
super.onStart();
presenter.setView(this);
presenter.loadData(city, authToken);
}
#Override
public void onStop() {
super.onStop();
presenter.rxUnsubscribe();
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
((App) getActivity().getApplication()).getComponent().inject(this);
}
#Override
public void updateData(ViewModel viewModel) {
this.pollutionData = viewModel;
ArrayList<PollutionLevel> pollutionLevels = viewModel.getAllPolluants();
for(PollutionLevel pl : pollutionLevels) {
plAdapter.add(pl);
}
}
}
The fragment layout
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView android:id="#+id/lv_pollution_levels"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
The ArrayAdapter for the ListView
public class PollutionLevelAdapter extends ArrayAdapter<PollutionLevel> {
#BindView(R.id.tv_name)
TextView tvName;
#BindView(R.id.tv_value)
TextView tvValue;
public PollutionLevelAdapter(Context context, ArrayList<PollutionLevel> pollutionLevels) {
super(context,0,pollutionLevels);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.list_item_pollution, parent, false);
}
View view = convertView;
ButterKnife.bind(this,view);
PollutionLevel pollutionLevel = getItem(position);
tvName.setText(pollutionLevel.getName());
tvValue.setText(pollutionLevel.getValue());
return view;
}
}
My list item
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/iv_warning"
android:layout_width="20dp"
android:layout_height="20dp"
app:srcCompat="#drawable/rectangle"/>
<TextView
android:id="#+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:gravity="center_vertical"
android:text="TextView"/>
<TextView
android:id="#+id/tv_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:gravity="center_vertical"
android:text="TextView"/>
This is the code of the layout the Activity class that rendered the Listview correctly (so before I switched from an activity to a fragment). I didn't put the code of the Listview adapter here since it didn't change :
Activity
public class PollutionLevelsActivity extends AppCompatActivity implements PollutionLevelsActivityMVP.View {
private PollutionLevelAdapter plAdapter;
#BindString(R.string.city)
String city;
#BindString(R.string.aqicn_token)
String authToken;
#BindView(R.id.lv_pollution_levels)
ListView lvPollutionLevels;
#Inject
PollutionLevelsActivityMVP.Presenter presenter;
private ViewModel pollutionData;
private ArrayList<String> testbidon;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
((App) getApplication()).getComponent().inject(this);
ButterKnife.bind(this);
// Construct the data source
ArrayList<PollutionLevel> arrayOfPollutionLevel = new ArrayList<>();
// Create the adapter to convert the array to views
plAdapter = new PollutionLevelAdapter(this, arrayOfPollutionLevel);
lvPollutionLevels.setAdapter(plAdapter);
}
#Override
protected void onStart() {
super.onStart();
presenter.setView(this);
presenter.loadData(city, authToken);
}
#Override
protected void onDestroy() {
super.onDestroy();
presenter.rxUnsubscribe();
}
#Override
public void updateData(ViewModel viewModel) {
this.pollutionData = viewModel;
ArrayList<PollutionLevel> pollutionLevels = viewModel.getAllPolluants();
for(PollutionLevel pl : pollutionLevels) {
plAdapter.add(pl);
}
}
}
Layout
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.livos.citypollution.pollutionlevels.PollutionLevelsActivity">
<ListView
android:id="#+id/lv_pollution_levels"
android:layout_width="368dp"
android:layout_height="495dp"
tools:layout_editor_absoluteX="8dp"
tools:layout_editor_absoluteY="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</android.support.constraint.ConstraintLayout>
To change Text Color add this
android:textColor="Your Color Code"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/iv_warning"
android:layout_width="20dp"
android:layout_height="20dp"
**app:src="#drawable/rectangle"**/>
<TextView
android:id="#+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:gravity="center_vertical"
android:text="TextView"
android:textColor="Your Color Code"/>
<TextView
android:id="#+id/tv_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:gravity="center_vertical"
android:text="TextView"
android:textColor="Your Color Code"/>
As i am getting. You give an adapter like:
public class PollutionLevelAdapter extends ArrayAdapter<PollutionLevel> {
#BindView(R.id.tv_name)
TextView tvName;
#BindView(R.id.tv_value)
TextView tvValue;
public PollutionLevelAdapter(Context context, ArrayList<PollutionLevel> pollutionLevels) {
super(context,0,pollutionLevels);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.list_item_pollution, parent, false);
}
View view = convertView;
ButterKnife.bind(this,view);
PollutionLevel pollutionLevel = getItem(position);
tvName.setText(pollutionLevel.getName());
tvValue.setText(pollutionLevel.getValue());
return view;
}
}
You are binding your two TextView not Your ImageView as you gave your list_item_pollution, which is having ImageView so bind your ImageView like:
#BindView(R.id.iv_warning)
ImageView iv_warning;
and in getView method set is as :
iv_warning.setBackgroundColor(Color.parseColor("your color code"));