I've written this code for my recycler view, but it doesn't seem to work (it gives to me some errors)... Can someone tell me what I do wrong?
CustomAdapter.java:
public class CustomAdapter extends RecyclerView.Adapter<CustomViewHolder> {
//Attributi:
private Context context;
private int[] immagineDio;
private String[] nomeDio;
//Costruttori:
public CustomAdapter(Context context, int[] immagineDio, String[] nomeDio){
this.context = context;
this.immagineDio = immagineDio;
this.nomeDio = nomeDio;
}
//Metodi di istanza:
#NonNull
#Override
public CustomViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return CustomViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.listview_item, parent, false));
}
#Override
public void onBindViewHolder(#NonNull CustomViewHolder holder, int position) {
holder.bind(immagineDio[position], nomeDio[position]);
}
#Override
public int getItemCount() {
return nomeDio.length;
}
}
CustomViewHolder.java:
public class CustomViewHolder extends RecyclerView.ViewHolder {
ImageView mFlag;
TextView mName;
public CustomViewHolder(#NonNull View itemView) {
super(itemView);
mFlag = itemView.findViewById(R.id.imageView);
mName = itemView.findViewById(R.id.textView);
}
//binding data with UI
void bind(int imageId, String name) {
mFlag.setImageResource(imageId);
mName.setText(name);
} }
ListViewActivity.java:
public class ListViewActivity extends AppCompatActivity {
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.listview_layout);
String[] nomeDei = {"Baldr","Borr","Bragi","Dagr","Dellingr","Eir","Eostre","Forseti","Freya","Freyr","Frigg","Fulla","Gefjun","Gerðr","Gullveig","Heimdallr","Hel","Hermóðr","Höðr","Hœnir","Iðunn","Itreksjóð","Jǫrð","Kvasir","Lóðurr","Lofn","Logi","Lýtir","Máni","Mímir","Móði","Nanna","Njörun","Njörðr","Nótt","Óðr","Rán","Ríg","Sága","Sif","Signe","Sigyn","Sinfjötli","Sjöfn","Skaði","Skirnir","Snotra","Sól","Syn","Thor","Týr","Ullr","Váli","Vár","Ve","Viðarr","Víli","Vör"};
int[] immagineDei = {
R.drawable.profilo_baldr,
R.drawable.profilo_borr,
R.drawable.profilo_bragi,
R.drawable.profilo_dagr,
R.drawable.profilo_dellingr,
R.drawable.profilo_eir,
R.drawable.profilo_eostre,
R.drawable.profilo_forseti,
R.drawable.profilo_freya,
R.drawable.profilo_freyr,
R.drawable.profilo_frigg,
R.drawable.profilo_fulla,
R.drawable.profilo_gefjun,
R.drawable.profilo_geror,
R.drawable.profilo_gullveig,
R.drawable.profilo_heimdallr,
R.drawable.profilo_hel,
R.drawable.profilo_hermoor,
R.drawable.profilo_hoor,
R.drawable.profilo_hoenir,
R.drawable.profilo_iounn,
R.drawable.profilo_itreksjoo,
R.drawable.profilo_joro,
R.drawable.profilo_kvasir,
R.drawable.profilo_loourr,
R.drawable.profilo_lofn,
R.drawable.profilo_logi,
R.drawable.profilo_lytir,
R.drawable.profilo_mani,
R.drawable.profilo_mimir,
R.drawable.profilo_modi,
R.drawable.profilo_nanna,
R.drawable.profilo_njorun,
R.drawable.profilo_njoror,
R.drawable.profilo_nott,
R.drawable.profilo_oor,
R.drawable.profilo_ran,
R.drawable.profilo_rig,
R.drawable.profilo_saga,
R.drawable.profilo_sif,
R.drawable.profilo_signe,
R.drawable.profilo_sigyn,
R.drawable.profilo_sinfjotli,
R.drawable.profilo_sjofn,
R.drawable.profilo_skaoi,
R.drawable.profilo_skirnir,
R.drawable.profilo_snotra,
R.drawable.profilo_sol,
R.drawable.profilo_syn,
R.drawable.profilo_thor,
R.drawable.profilo_tyr,
R.drawable.profilo_ullr,
R.drawable.profilo_vali,
R.drawable.profilo_var,
R.drawable.profilo_ve,
R.drawable.profilo_vidar,
R.drawable.profilo_vili,
R.drawable.profilo_vor,
};
ListView listViewReference = findViewById(R.id.listView);
CustomAdapter customAdapter = new CustomAdapter(ListViewActivity.this, immagineDei, nomeDei);
listViewReference.setAdapter(customAdapter); //this line gives an error
} }
listview_layout.xml:
<android.support.v7.widget.RecyclerView
android:id="#+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
you have used RecyclerView in your XML file and try to getting ListView in Java code file try this
RecyclerView listViewReference = (RecyclerView )findViewById(R.id.listView);
This is a very detailed and good tutorial on how to implement the recyclerview. Please read it for better understanding. Hope it helps.
Summary:
Step 1: Below is the RecyclerView widget with necessary attributes.
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
Step 2: Open build.gradle and add recycler view dependency. com.android.support:recyclerview-v7:{{latest version}} and rebuild the project.
Step 3: Create your CustomAdapter
Step 4: From your activity/fragment:
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mAdapter = new MoviesAdapter(movieList);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(mAdapter);
You have not used a Layout Manager for the recycler view
link
Related
hi i am trying use recyclerview. I have two layout one of them mainactivity which has cardview and recyclerview and other one is feeditem xml this one has hold item requirements for show in recyclerview(name,feed,date). But i guess i might have problem onBindViewHolder or VievHolder because i just see mainactivity i cant show anything in recyclerview and the tools inside the feeditem xml actually i can't bind each other.
MainActivity
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView (R.layout.activity_main);
recyclerView = this.findViewById(R.id.rv_f2);
// recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
databaseReference = database.getReference("allfeed");
FirebaseRecyclerOptions<feedmember> options = new FirebaseRecyclerOptions.Builder<feedmember>().setQuery(databaseReference, feedmember.class).build();
FirebaseRecyclerAdapter<feedmember, VievHolder_feed> firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<feedmember, VievHolder_feed>(options) {
#Override
protected void onBindViewHolder(#NonNull VievHolder_feed holder, int position, #NonNull feedmember model)
{ holder.setitem(this , model.getName(), model.getFeed(), model.getTime()); }
#NonNull
#Override
public VievHolder_feed onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.feed_item, parent, false);
return new VievHolder_feed(view); }};
firebaseRecyclerAdapter.startListening();
recyclerView.setAdapter(firebaseRecyclerAdapter); }}
Viewholder_feed
public class VievHolder_feed extends RecyclerView.ViewHolder {
TextView time_result,name_result,que_result;
public VievHolder_feed(#NonNull View itemView) { super(itemView); }
public void setitem(FirebaseRecyclerAdapter<feedmember, VievHolder_feed> activity, String name, String time, String feed){
time_result =itemView.findViewById(R.id.time_que_item);
name_result =itemView.findViewById(R.id.name_que_item_tv);
que_result =itemView.findViewById(R.id.que_item_tv);
time_result.setText(time);
name_result.setText( name);
que_result.setText(feed); }}
[]
It seems that your recycler view received the item, but the view holder binds the fields with blank contents.
Did you verify if the mapping inside feedmember class works fine ?
I am trying to populate a recyclerview inside the Fragment under a TabLayout. Everything seems to be fine, but the data is not actually populated in the recyclerview, while all the content Logs[Log.e();] is working fine. Can anyone relate the issue ?
My Fragment Is Like :
public class SugarLevelReport extends Fragment
{
private ConstraintLayout view_constraintLayout;
private RecyclerView blood_sugar_recyclerView;
private ProgressBar progressBar;
private ArrayList<PatientRecordModel> patientRecordModelArrayList = new ArrayList<PatientRecordModel>();
private RecyclerView.Adapter bloodSugaradapter;
// for intent data
public String patient_id_from_intent, patient_name_from_intent, patient_dob_from_intent, patient_mobile_from_intent, patient_email_from_intent;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_sugar_level_report, container, false);
findViewById(view);
return view;
}
public void findViewById(View view)
{
view_constraintLayout = (ConstraintLayout)view.findViewById(R.id.view_constraintLayout);
/*progressBar = (ProgressBar)view.findViewById(R.id.progressBar);*/
blood_sugar_recyclerView = (RecyclerView)view.findViewById(R.id.blood_sugar_recyclerView);
blood_sugar_recyclerView.setHasFixedSize(true);
blood_sugar_recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
bloodSugaradapter = new SugarLevelReportAdapter(getActivity(), patientRecordModelArrayList);
blood_sugar_recyclerView.setAdapter(bloodSugaradapter);
loadData();
}
public void loadData()
{
if(GlobalMethods.isNetworkConnected(getActivity()))
{
String[] names = getResources().getStringArray(R.array.names);
for (int i = 0 ; i < names.length ; i++)
{
PatientRecordModel patientRecordModel = new PatientRecordModel();
patientRecordModel.setPatient_name(names[i]);
// log here is working fine , and its giving correct data
Log.e("patientsName", patientRecordModel.getPatient_name());
patientRecordModelArrayList.add(patientRecordModel);
bloodSugaradapter.notifyDataSetChanged();
}
}
else
{
}
}
Adapter Class
public class SugarLevelReportAdapter extends RecyclerView.Adapter<SugarLevelReportAdapter.SugarLevelReportHolder>{
public Context context;
public ArrayList<PatientRecordModel> patientRecordModelArrayList = new ArrayList<PatientRecordModel>();
public SugarLevelReportAdapter(Context context, ArrayList<PatientRecordModel> patientRecordModelArrayList)
{
this.context = context;
this.patientRecordModelArrayList = patientRecordModelArrayList;
}
#Override
public SugarLevelReportHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.sugar_level_report_cardview, parent, false);
SugarLevelReportHolder sugarLevelReportHolder = new SugarLevelReportHolder(view);
return sugarLevelReportHolder;
}
#Override
public void onBindViewHolder(SugarLevelReportHolder holder, int position)
{
PatientRecordModel patientRecordModel = patientRecordModelArrayList.get(position);
Log.e("patient_name",patientRecordModel.getPatient_name());
holder.patient_name_textView.setText(patientRecordModel.getPatient_name());
}
#Override
public int getItemCount()
{
return patientRecordModelArrayList.size();
}
public static class SugarLevelReportHolder extends RecyclerView.ViewHolder
{
public TextView month_textView, date_textView, year_textView;
public TextView patient_name_textView, patient_count_textView, meal_type_textView;
public ImageView overflow_menu_imageView;
public SugarLevelReportHolder(View itemView)
{
super(itemView);
month_textView = (TextView)itemView.findViewById(R.id.month_textView);
date_textView = (TextView)itemView.findViewById(R.id.date_textView);
year_textView = (TextView)itemView.findViewById(R.id.year_textView);
patient_name_textView = (TextView)itemView.findViewById(R.id.patient_name_textView);
patient_count_textView = (TextView)itemView.findViewById(R.id.patient_count_textView);
meal_type_textView = (TextView)itemView.findViewById(R.id.meal_type_textView);
overflow_menu_imageView = (ImageView)itemView.findViewById(R.id.overflow_menu_imageView);
}
}
}
xml code [fragment_sugar_level_report.xml]
<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">
<android.support.v7.widget.RecyclerView
android:id="#+id/blood_sugar_recyclerView"
android:layout_width="0dp"
android:layout_height="0dp"
android:scrollbars="vertical"
android:scrollbarSize="1dp"
android:layout_marginLeft="8dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="8dp"
android:layout_marginRight="8dp"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginBottom="8dp">
</android.support.v7.widget.RecyclerView>
So I had a similar problem on my current project. I cannot tell you why it happens but to solve it you need to move the part for updating data to the adapter.
on your adapter create the following method:
public void updateData(List<PatientRecordModel> list){
patientRecordModelArrayList = list;
notifyDatasetChanged();
}
On you Fragment class when you want to update the data just call
bloodSugaradapter.updateData(patientRecordModel);
On the same it is advisable to load your views onViewCreated instead of onCreateView. Also use a data mapping library such as GSON or or jackson to improve speed and reliability in data mapping.See a comparison here Hope this helps
So I am trying to create an android app on alcohol and mixers, but have been stuck on the following problem for a while now...
I want to display every alcohol category (eg: Gin, Vodka, Whiskey, etc..) in a RecyclerView that scrolls horizontally, and every alcohol type (eg: Bourbon and Scotch for the Whiskey Category) in a RecyclerView that scrolls vertically.
I have created one adapter for each RecyclerView (CategoryAdapter for the horizontal RecyclerView called category, and MixerAdapter for the vertical RecyclerView called categoryDetails).
So far I've managed to create and display category as desired, but have some difficulties for categoryDetails.
Basically, I can't figure out how to update the contents of categoryDetails when an item of category is selected:
For example
If the user selects Whiskey in category, I want categoryDetails to display Bourbon and Scotch.
If the user then selects Gin, I want categoryDetails to only display Gin and Flavoured Gin, etc...
I hope I've been clear enough on what it is I want to accomplish!
Any help would be much appreciated, thanks!!
Here is a screenshot of how the screen appears when the activity is loaded.
If a user selects Rum (white on black RecyclerView), I want the RecyclerView currently showing Gin and Flavored Gin (black on white RecyclerView) to show the alcohols associated with the Rum category.
Screenshot
Here is the XML file holding the two recyclerViews category and categoryDetails
<?xml version="1.0" encoding="utf-8"?>
<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=".TipsDrinks">
<android.support.v7.widget.RecyclerView
android:id="#+id/category"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:background="#android:color/black"
android:orientation="horizontal"
android:scrollbars="horizontal"
android:visibility="visible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/SpinnerPrompt" >
</android.support.v7.widget.RecyclerView>
<android.support.v7.widget.RecyclerView
android:id="#+id/categoryDetails"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:background="#android:color/white"
android:orientation="horizontal"
android:scrollbars="vertical"
android:visibility="visible"
app:layout_constraintBottom_toTopOf="#+id/adView4"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/category"
app:layout_constraintVertical_bias="0.0">
</android.support.v7.widget.RecyclerView>
</android.support.constraint.ConstraintLayout>
The Class associated with the previous layout
public class TipsDrinks extends AppCompatActivity {
private CategoryAdapter categoryAdapter; // Adapter used for the category RecyclerView
public MixerAdapter mixerAdapter; //Adapter used for the categoryDetails RecyclerView
private RecyclerView categories; // The RecyclerView holding the name of each alcohol category
public RecyclerView catDetails; // The RecyclerView holding each type of that alcohol category
private DrinkMenu drinkMenu; // The DrinkMenu is another Class holding every Alcohol Category, the type of each alcohol and the mixers good with it
private ArrayList<String> drinkCat = new ArrayList<>(); // A String ArrayList holding the name of each alcohol category (Gin, Vodka, Rum, Whiskey, Other)
private ArrayList<Drink> drinkMixers = new ArrayList<>(); // A Drink(String, ArrayList<String>) ArrayList holding the mixers of every Drink
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tips_drinks);
categories = findViewById(R.id.category);
catDetails = findViewById(R.id.categoryDetails);
drinkMenu = new DrinkMenu();
setCategoryView(); // Creates the category RecyclerView
setDrinkMixers(); // Creates the categoryDetails RecyclerView
}
private void setCategoryView(){
categoryAdapter = new CategoryAdapter(drinkCat);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(TipsDrinks.this, LinearLayoutManager.HORIZONTAL, false);
categories.addItemDecoration(new DividerItemDecoration(TipsDrinks.this, DividerItemDecoration.HORIZONTAL));
categories.setLayoutManager(layoutManager);
categories.setItemAnimator(new DefaultItemAnimator());
categories.setAdapter(categoryAdapter);
prepareCategories();
}
private void prepareCategories(){
drinkCat.clear();
drinkCat.addAll(drinkMenu.getDrinkCategories());
for (String drink : drinkCat) {
System.out.println(drink);
}
categoryAdapter.notifyItemInserted(drinkCat.size() - 1);
}
private void setDrinkMixers() {
mixerAdapter = new MixerAdapter(drinkMixers);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
catDetails.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
catDetails.setLayoutManager(layoutManager);
catDetails.setItemAnimator(new DefaultItemAnimator());
catDetails.setAdapter(mixerAdapter);
prepareMixers();
}
private void prepareMixers() {
drinkMixers.clear();
drinkMixers.addAll(drinkMenu.getDrinkMixers(categoryAdapter.getCurrentCategory()));
mixerAdapter.notifyItemChanged(drinkMixers.size() -1);
}
}
The CategoryAdapter Class for the category RecyclerView
public class CategoryAdapter extends RecyclerView.Adapter<CategoryAdapter.MyViewHolder> {
private List<String> drinkList; //A List of String holding the category for each drink
private String textName = "Gin";
class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
private TextView name; // The TextView holding the name of the category
MyViewHolder(View view) {
super(view);
view.setOnClickListener(this);
name = view.findViewById(R.id.catName);
}
#Override
public void onClick(View v) {
//Code to update the contents of the categoryDetails RecyclerView
}
}
CategoryAdapter(ArrayList<String> drinkList) { this.drinkList = drinkList; }
#Override
public CategoryAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.category_text, parent, false);
return new MyViewHolder(itemView);
}
#SuppressLint("SetTextI18n")
#Override
public void onBindViewHolder(CategoryAdapter.MyViewHolder holder, int position) {
String drink = drinkList.get(position);
holder.name.setText(drink);
textName = holder.name.getText().toString();
}
#Override
public int getItemCount() {
return drinkList.size();
}
public String getCurrentCategory() {
return textName;
}
}
The MixerAdapter Class for the categoryDetails RecyclerView
public class MixerAdapter extends RecyclerView.Adapter<MixerAdapter.MyViewHolder>{
private List<Drink> mixerList;
class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
TextView mixerCat, mixers;
MyViewHolder(View view) {
super(view);
view.setOnClickListener(this);
mixerCat = view.findViewById(R.id.mixerCat2);
mixers = view.findViewById(R.id.mixers2);
}
#Override
public void onClick(View v) {
if (mixers.getVisibility() == mixerCat.getVisibility()) {
mixers.setVisibility(View.GONE);
}
else {
mixers.setVisibility(View.VISIBLE);
}
}
}
MixerAdapter(ArrayList<Drink> mixerList) {
this.mixerList = mixerList;
}
#Override
public MixerAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.drinks_row, parent, false);
return new MixerAdapter.MyViewHolder(itemView);
}
#SuppressLint("SetTextI18n")
#Override
public void onBindViewHolder(MixerAdapter.MyViewHolder holder, int position) {
Drink drink = mixerList.get(position);
StringBuilder mixerStringList = new StringBuilder("");
holder.mixerCat.setText(drink.getSorM());
for (String mixer: drink.getMixers()) {
mixerStringList.append(mixer).append("\n");
}
holder.mixers.setText(mixerStringList.toString().trim());
}
#Override
public int getItemCount() {
return mixerList.size();
}
}
Create a callback interface in CategoryAdapter. When user clicks on an item in Category RecycleView, it's activity responsibility to populate MixerAdapter with new items as per selection.
CategoryAdapter
public class CategoryAdapter extends RecyclerView.Adapter<CategoryAdapter.MyViewHolder> {
private CategoryInterface callback;
CategoryAdapter(ArrayList<String> drinkList, CategoryInterface listener) {
this.drinkList = drinkList;
callback = listener;
}
#Override
public void onClick(View v) {
//Code to update the contents of the categoryDetails RecyclerView
callback.onItemSelected(getAdapterPosition());
}
public interface CategoryInterface {
void onItemSelected(int position);
}
}
Activity
public class TipsDrinks extends AppCompatActivity implements CategoryInterface {
private void setCategoryView(){
categoryAdapter = new CategoryAdapter(drinkCat, this);
}
#Override
void onItemSelected(int position) {
//Reassign items in MixerAdapter
}
}
that depends on your implementations , one global method which should work for all implementations is using HolderView method and using onTouchListener on the groups's root view
v.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_UP){
//the child should expand and be updated
}
return false;
}
});
This question has been asked a few times but those answers doesn't apply to me. I would like a more general answer about what causes this issue generally.
I have a recyclerview in my activity layout. Rows of the recyclerview is a constraint layout with one imageview and textview:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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="50dp"
android:clickable="true">
<ImageView
android:id="#+id/file_icon"
android:layout_width="50dp"
android:layout_height="50dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
android:text="File"
android:id="#+id/file_name"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintLeft_toRightOf="#+id/file_icon"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"/>
</android.support.constraint.ConstraintLayout>
I have several items to show in this row structure. I set up the adapter properly. However, when I run my application, textviews that are on the screen doesn't get shown, until I scroll-down and scroll-up again. Basically, in order for those textviews to be shown, they need to be discarded from display and enter again. Here is my adapter code:
public class FileViewAdapter extends RecyclerView.Adapter<FileViewAdapter.Viewholder> {
private Context context;
private List<File> files;
public FileViewAdapter(Context context, List<File> files) {
this.context = context;
this.files = files;
}
public FileViewAdapter(Context context){
this.context = context;
}
#Override
public Viewholder onCreateViewHolder(ViewGroup viewGroup, int i) {
LayoutInflater inflater = LayoutInflater.from(context);
View layout = inflater.inflate(R.layout.file_list_item, viewGroup, false);
return new Viewholder(layout);
}
#Override
public void onBindViewHolder(Viewholder viewholder, int i) {
File file = files.get(i);
if (file.isDirectory()) {
viewholder.fileIcon.setImageDrawable(
context.getResources().getDrawable(R.drawable.ic_folder_black_24dp));
viewholder.wholeThing.setOnClickListener(null);
} else {
viewholder.fileIcon.setImageDrawable(
context.getResources().getDrawable(R.drawable.ic_insert_drive_file_black_24dp));
viewholder.wholeThing.setOnClickListener(null);
}
viewholder.fileName.setText(file.getName());
}
#Override
public int getItemCount() {
return files.size();
}
public void clear() {
files.clear();
notifyDataSetChanged();
}
public void addAll(List<File> newFiles) {
files.addAll(newFiles);
notifyDataSetChanged();
}
class Viewholder extends RecyclerView.ViewHolder {
View wholeThing;
ImageView fileIcon;
TextView fileName;
public Viewholder(View itemView) {
super(itemView);
wholeThing = itemView;
fileIcon = (ImageView) itemView.findViewById(R.id.file_icon);
fileName = (TextView) itemView.findViewById(R.id.file_name);
}
}
}
EDIT: How I am calling the constructor of adapter on activity.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_file_viewer);
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
}
#Override
public void onResume() {
adapter = new Adapter(this, /*A list of File items*/);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
}
The problem from what i see is that the notifyDataSetChanged doesnt ocurr in the UiThread so if run ur setData method like this it will work.
this.runOnUiThread(new Runnable() {
public void run() {
mAdapter.setNewData(newDataListForAdapter);
mAdapter.notifyDataSetChanged();
}
});
As stupid as it might sound, calling this line of code after setting data for recyclerView, helped me for this issue:
recyclerView.smoothScrollToPosition(0)
PS: technologies that I was using that may have something to do with this were: RJava, Retrofit2, NavigationUI, Fragments, LiveData, and Databinding.
Please try this. I hope it will be helpful.
RecyclerView recyclerView;
FileViewAdapter adapter;
List<File> files = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_file_viewer);
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
adapter = new FileViewAdapter(this, files);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
}
#Override
public void onResume() {
super.onResume();
files = getFiles();//fetch files
adapter.notifyDataSetChanged();//update UI
}
public List<File> getFiles() {
//fetch files
//...
return files;
}
By the way, I did not find the situation happened to you. There may be some other errors in you code you did not show to us.
if you're setting data on the constructor, it might be that the adapter never gets notified about data inserted. Try to add a notifyDataSetChanged () either at the bottom of the constructor or externally (or call your setData method)
I'm trying to figure out how to achieve the same effect of
mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
in a RecyclerView implementation. Please help.
There is no built-in support for a "choice mode" structure with RecyclerView. Your options are to either roll it yourself or use a third-party library that offers it.
The DynamicRecyclerView library offers choice modes, but I have not tried it.
This sample app demonstrates implementing it yourself, in this case using the activated state to indicate which is the current choice. The overall pattern is:
Have your RecyclerView.ViewHolder detect a UI operation that indicates a choice (click on a row? click on a RadioButton in the row? etc.).
Keep track of the selection at the level of your RecyclerView.Adapter. In my case, a ChoiceCapableAdapter handles that, in conjunction with a SingleChoiceMode class that implements a ChoiceMode strategy.
When a choice is made, update the newly-chosen row to reflect the choice and update the previously-chosen row to reflect that it is no longer chosen. findViewHolderForPosition() on RecyclerView can help here -- if you track the position of the last choice, findViewHolderForPosition() can give you the ViewHolder for that choice, so you can "un-choose" it.
Keep track of the choice across configuration changes, by putting it in the saved instance state of the activity or fragment that is managing the RecyclerView.
I've created a library for this kind of choice mode applied to the RecyclerView, maybe it can help:
Description
This library has been created to help the integration of a multi-choice selection to the RecyclerView
Implementation
The integration with Gradle is very easy, you just need the jcenter repository and the library:
repositories {
jcenter()
}
...
dependencies {
compile 'com.davidecirillo.multichoicerecyclerview:multichoicerecyclerview:1.0.1'
}
Main steps for usage
Add the MultiChoiceRecyclerView to your xml file
<com.davidecirillo.multichoicesample.MultiChoiceRecyclerView
android:id="#+id/multiChoiceRecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Instanciate you object and connect the view
MultiChoiceRecyclerView mMultiChoiceRecyclerView = (MultiChoiceRecyclerView) findViewById(R.id.multiChoiceRecyclerView);
Extend you adapter to the MultiChoiceAdapter and add it to the RecyclerView as per normal usage
public class MyAdapter extends MultiChoiceAdapter<MyViewHolder> {
public MyAdapter(ArrayList<String> stringList, Context context) {
this.mList = stringList;
this.mContext = context;
}
...
}
MyAdapter myAdapter = new MyAdapter(mList, getApplicationContext());
mMultiChoiceRecyclerView.setAdapter(myAdapter);
For more information and customisations:
https://github.com/dvdciri/MultiChoiceRecyclerView
You can follow this:
– Data (String name, boolean selected)
– Adapter with itemClickListener
– Activity or fragment
– activity_main (recyclerView)
– list_item (TextView, CheckBox)
Data
public class MultipleData {
private String mTitle;
private boolean mBoolean;
public MultipleData(String title, boolean mBoolean) {
this.mTitle = title;
this.mBoolean = mBoolean;
}
public String getTitle() {
return mTitle;
}
public void setTitle(String mTitle) {
this.mTitle = mTitle;
}
public boolean isBoolean() {
return mBoolean;
}
public void setBoolean(boolean mBoolean) {
this.mBoolean = mBoolean;
}
}
Your views activity_main.xml (recyclerView)
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.thedeveloperworldisyours.fullrecycleview.multiple.MultipleFragment">
<android.support.v7.widget.RecyclerView
android:id="#+id/multiple_fragment_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
and list_item.xml (TextView, CheckBox)
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/multiple_list_item_text"
android:layout_width="match_parent"
android:layout_height="90dp"
android:text="#string/app_name"
android:typeface="monospace"
android:layout_toLeftOf="#+id/multiple_list_item_check_button"
android:gravity="center"
android:textSize="#dimen/multiple_list_item_size_rock_stars"/>
<RadioButton
android:id="#+id/multiple_list_item_check_button"
android:layout_width="wrap_content"
android:layout_height="90dp"
android:layout_alignParentRight="true"
android:checked="false"
android:clickable="false"
android:focusable="false" />
</RelativeLayout>
Adapter with ClickListener
public class MultipleRecyclerViewAdapter extends RecyclerView
.Adapter<MultipleRecyclerViewAdapter
.DataObjectHolder> {
private List<MultipleData> mList;
private static MultipleClickListener sClickListener;
MultipleRecyclerViewAdapter(List<MultipleData> mList) {
this.mList = mList;
}
static class DataObjectHolder extends RecyclerView.ViewHolder
implements View
.OnClickListener {
TextView mTextView;
RadioButton mRadioButton;
DataObjectHolder(View itemView) {
super(itemView);
mTextView = (TextView) itemView.findViewById(R.id.multiple_list_item_text);
mRadioButton = (RadioButton) itemView.findViewById(R.id.multiple_list_item_check_button);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
sClickListener.onItemClick(getAdapterPosition(), v);
}
}
void changedData(int position) {
if (mList.get(position).isBoolean()) {
mList.get(position).setBoolean(false);
} else {
mList.get(position).setBoolean(true);
}
notifyDataSetChanged();
}
void setOnItemClickListener(MultipleClickListener myClickListener) {
this.sClickListener = myClickListener;
}
#Override
public DataObjectHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.multiple_list_item, parent, false);
DataObjectHolder dataObjectHolder = new DataObjectHolder(view);
return dataObjectHolder;
}
#Override
public void onBindViewHolder(DataObjectHolder holder, int position) {
holder.mTextView.setText(mList.get(position).getTitle());
holder.mRadioButton.setChecked(mList.get(position).isBoolean());
}
#Override
public int getItemCount() {
return mList.size();
}
interface MultipleClickListener {
void onItemClick(int position, View v);
}
}
Activity or fragment
public class MultipleFragment extends Fragment implements MultipleRecyclerViewAdapter.MultipleClickListener{
MultipleRecyclerViewAdapter mAdapter;
public MultipleFragment() {
// Required empty public constructor
}
public static MultipleFragment newInstance() {
return new MultipleFragment();
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.multiple_fragment, container, false);
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.multiple_fragment_recycler_view);
MultipleData hendrix = new MultipleData("Jimi Hendrix", false);
MultipleData bowie = new MultipleData("David Bowie", false);
MultipleData morrison = new MultipleData("Jim Morrison", false);
MultipleData presley = new MultipleData("Elvis Presley", false);
MultipleData jagger = new MultipleData("Mick Jagger", false);
MultipleData cobain = new MultipleData("Kurt Cobain", false);
MultipleData dylan = new MultipleData("Bob Dylan", false);
MultipleData lennon = new MultipleData("John Lennon", false);
MultipleData mercury = new MultipleData("Freddie Mercury", false);
MultipleData elton = new MultipleData("Elton John", false);
MultipleData clapton = new MultipleData("Eric Clapton", false);
List<MultipleData> list = new ArrayList<>();
list.add(0, hendrix);
list.add(1, bowie);
list.add(2, morrison);
list.add(3, presley);
list.add(4, jagger);
list.add(5, cobain);
list.add(6, dylan);
list.add(7, lennon);
list.add(8, mercury);
list.add(9, elton);
list.add(10, clapton);
mAdapter = new MultipleRecyclerViewAdapter(list);
recyclerView.setAdapter(mAdapter);
recyclerView.setHasFixedSize(true);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
mAdapter.setOnItemClickListener(this);
return view;
}
#Override
public void onItemClick(int position, View v) {
mAdapter.changedData(position);
}
}
You can see this example in GitHub and this post for multiple choice, and this post for single choice Happy code!!!