I have a little problem with one of my RecyclerView.
In fact, it contains another RecyclerView in each of his items, and when I tried to scroll using LinearLayoutManager on my global RecyclerView (listener onClick on row), a blank space appears between second RecyclerView's item of the first and last item.
A screen of the problem (sorry for my crappy english).
My first RecyclerView adapter :
package com.ylly.hypred.process.adapter;
/**
* Created by YLLY on 24/06/2015.
*/
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.Toast;
import com.ylly.hypred.R;
import com.ylly.hypred.custom.HypredToast;
import com.ylly.hypred.custom.MyTextView;
import com.ylly.hypred.custom.RecyclerItemClickListener;
import com.ylly.hypred.dao.Etape;
import com.ylly.hypred.dao.Produit;
import com.ylly.hypred.dao.Protocole;
import com.ylly.hypred.db.HypredDbManager;
import com.ylly.hypred.process.atelierProcess.AtelierProcessModeleUn;
import com.ylly.hypred.process.recyclerView.SpacesItemDecoration;
import org.solovyev.android.views.llm.LinearLayoutManager;
import java.util.ArrayList;
import java.util.List;
public class AdapterProtocole extends RecyclerView.Adapter<AdapterProtocole.ViewHolder> implements AdapterEtape.clickOnProductListener {
private ArrayList<Protocole> protocoleArrayList;
private Context context;
private clickOnProductListener mCallback;
public AdapterProtocole(ArrayList<Protocole> protocoleArrayList, Context context) {
this.protocoleArrayList = protocoleArrayList;
this.context = context;
}
public interface clickOnProductListener {
void appelProduit(long productId);
void ajouterAllProduit(ArrayList<Produit> produitArrayList);
void ajouterProduit(Produit produit);
}
// Create new views (invoked by the layout manager)
#Override
public AdapterProtocole.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View itemLayoutView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_layout_process_protocole, null);
// create ViewHolder
ViewHolder viewHolder = new ViewHolder(itemLayoutView);
return viewHolder;
}
// Replace the contents of a view (invoked by the layout manager)
#Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
// - get data from your itemsData at this position
// - replace the contents of the view with that itemsData
View view = new View(context);
viewHolder.labelProtocoleTextView.setText(protocoleArrayList.get(position).getName());
viewHolder.produitsRecyclerView.addItemDecoration(new SpacesItemDecoration(0, 0, 0, 10));
viewHolder.produitsRecyclerView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false));
final ArrayList<Etape> fEtapeArrayList = new ArrayList<>();
Log.d("AdapterProtocole", "id des étapes du protocole " + protocoleArrayList.get(position).getName() + " = " +
protocoleArrayList.get(position).getEtapeId() + "," +
protocoleArrayList.get(position).getEtapeTwoId() + "," +
protocoleArrayList.get(position).getEtapeThreeId() + "," +
protocoleArrayList.get(position).getEtapeFourId() + "," +
protocoleArrayList.get(position).getEtapeFiveId() + "," +
protocoleArrayList.get(position).getEtapeSixId() + ".");
String test = "listes etapes dispo :";
List<Etape> etapes = HypredDbManager.getDbManager().getEtapeDbManager().getAllEtape();
for(int i=0; i<etapes.size(); i++) {
test += etapes.get(i).getId() + ",";
}
Log.d("AdapterProtocole", test);
if (HypredDbManager.getDbManager().getEtapeDbManager()
.getEtapeById(protocoleArrayList.get(position).getEtapeId()) != null) {
fEtapeArrayList.add(HypredDbManager.getDbManager().getEtapeDbManager()
.getEtapeById(protocoleArrayList.get(position).getEtapeId()));
}
if (HypredDbManager.getDbManager().getEtapeDbManager()
.getEtapeById(protocoleArrayList.get(position).getEtapeTwoId()) != null) {
fEtapeArrayList.add(HypredDbManager.getDbManager().getEtapeDbManager()
.getEtapeById(protocoleArrayList.get(position).getEtapeTwoId()));
}
if (HypredDbManager.getDbManager().getEtapeDbManager()
.getEtapeById(protocoleArrayList.get(position).getEtapeThreeId()) != null) {
fEtapeArrayList.add(HypredDbManager.getDbManager().getEtapeDbManager()
.getEtapeById(protocoleArrayList.get(position).getEtapeThreeId()));
}
if (HypredDbManager.getDbManager().getEtapeDbManager()
.getEtapeById(protocoleArrayList.get(position).getEtapeFourId()) != null) {
fEtapeArrayList.add(HypredDbManager.getDbManager().getEtapeDbManager()
.getEtapeById(protocoleArrayList.get(position).getEtapeFourId()));
}
if (HypredDbManager.getDbManager().getEtapeDbManager()
.getEtapeById(protocoleArrayList.get(position).getEtapeFiveId()) != null) {
fEtapeArrayList.add(HypredDbManager.getDbManager().getEtapeDbManager()
.getEtapeById(protocoleArrayList.get(position).getEtapeFiveId()));
}
if (HypredDbManager.getDbManager().getEtapeDbManager()
.getEtapeById(protocoleArrayList.get(position).getEtapeSixId()) != null) {
fEtapeArrayList.add(HypredDbManager.getDbManager().getEtapeDbManager()
.getEtapeById(protocoleArrayList.get(position).getEtapeSixId()));
}
Log.d("AdapterProtocole", Integer.toString(fEtapeArrayList.size()));
final AdapterEtape etapeAdapter = new AdapterEtape(fEtapeArrayList, view.getContext());
etapeAdapter.setClickOnProductListener(new AdapterEtape.clickOnProductListener() {
#Override
public void appelerProduit(long produitId) {
mCallback.appelProduit(produitId);
}
#Override
public void ajouterProduitSelection(Produit produit) {
mCallback.ajouterProduit(produit);
}
});
viewHolder.produitsRecyclerView.setAdapter(etapeAdapter);
viewHolder.imageViewPanierSelectionAll.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ArrayList<Produit> produits = new ArrayList<>();
for (int i = 0; i < fEtapeArrayList.size(); i++) {
produits.add((fEtapeArrayList.get(i).getProduit()));
}
mCallback.ajouterAllProduit(produits);
HypredToast.makeText(context, "Produits ajoutés au panier avec succès.", Toast.LENGTH_SHORT).show();
}
});
}
// inner class to hold a reference to each item of RecyclerView
public static class ViewHolder extends RecyclerView.ViewHolder {
public MyTextView labelProtocoleTextView;
public RecyclerView produitsRecyclerView;
public ImageView imageViewPanierSelectionAll;
public ViewHolder(View itemLayoutView) {
super(itemLayoutView);
labelProtocoleTextView = (MyTextView) itemLayoutView.findViewById(R.id.item_layout_protocole_label_text_view);
produitsRecyclerView = (RecyclerView) itemLayoutView.findViewById(R.id.item_layout_protocole_recycler_view);
imageViewPanierSelectionAll = (ImageView) itemLayoutView.findViewById(R.id.item_layout_process_protocole_panier_rouge);
}
}
// Return the size of your itemsData (invoked by the layout manager)
#Override
public int getItemCount() {
return protocoleArrayList.size();
}
#Override
public void appelerProduit(long produitId) {
}
public void setClickOnProductListener(clickOnProductListener callback) {
mCallback = callback;
}
#Override
public void ajouterProduitSelection(Produit produit) {
}
}
My inside RecyclerView :
package com.ylly.hypred.process.adapter;
/**
* Created by YLLY on 20/07/2015.
*/
import android.content.Context;
import android.graphics.Paint;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.Toast;
import com.ylly.hypred.R;
import com.ylly.hypred.custom.HypredToast;
import com.ylly.hypred.custom.MyTextView;
import com.ylly.hypred.dao.Etape;
import com.ylly.hypred.dao.Produit;
import com.ylly.hypred.db.HypredDbManager;
import com.ylly.hypred.process.atelierProcess.AtelierProcessModeleUn;
import java.util.ArrayList;
public class AdapterEtape extends RecyclerView.Adapter<AdapterEtape.ViewHolder> {
private ArrayList<Etape> etapeArrayList;
private Context context;
private clickOnProductListener mCallback;
public interface clickOnProductListener {
void appelerProduit(long produitId);
void ajouterProduitSelection(Produit produit);
}
public AdapterEtape(ArrayList<Etape> etapeArrayList, Context context) {
this.etapeArrayList = etapeArrayList;
this.context = context;
}
// Create new views (invoked by the layout manager)
#Override
public AdapterEtape.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View itemLayoutView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_layout_process_etape, null);
// create ViewHolder
ViewHolder viewHolder = new ViewHolder(itemLayoutView);
return viewHolder;
}
// Replace the contents of a view (invoked by the layout manager)
#Override
public void onBindViewHolder(final ViewHolder viewHolder, final int position) {
// - get data from your itemsData at this position
// - replace the contents of the view with that itemsData
viewHolder.labelEtapeTextView.setText(etapeArrayList.get(position).getTexte_etape());
if(HypredDbManager.getDbManager().getProductDbManager().
getProduitById(etapeArrayList.get(position).getProduitId())!=null) {
viewHolder.labelProduitTextView
.setText(HypredDbManager.getDbManager().getProductDbManager().
getProduitById(etapeArrayList.get(position).getProduitId()).getNom_produit());
}
viewHolder.labelProduitTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mCallback.appelerProduit(etapeArrayList.get(position).getProduitId());
}
});
viewHolder.descriptifTextView.setText(etapeArrayList.get(position).getTemps() + "/" +
etapeArrayList.get(position).getConcentration() + "/" + etapeArrayList.get(position).getTemperature());
int temp = 1 + position;
if (etapeArrayList.size() == temp && etapeArrayList.get(position).getRincage()) {
viewHolder.imageViewEtapeSuivante.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.hypred_protocole_vague_finale));
} else if(etapeArrayList.get(position).getRincage()) {
viewHolder.imageViewEtapeSuivante.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.hypred_protocole_vague));
}
viewHolder.imageViewPanierSelection.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mCallback.ajouterProduitSelection(etapeArrayList.get(position).getProduit());
HypredToast.makeText(context, "Produit ajouté au panier avec succès.", Toast.LENGTH_SHORT).show();
}
});
}
// inner class to hold a reference to each item of RecyclerView
public static class ViewHolder extends RecyclerView.ViewHolder {
public MyTextView labelEtapeTextView;
public MyTextView labelProduitTextView;
public MyTextView descriptifTextView;
public ImageView imageViewEtapeSuivante;
public ImageView imageViewPanierSelection;
public ViewHolder(View itemLayoutView) {
super(itemLayoutView);
labelEtapeTextView = (MyTextView) itemLayoutView.findViewById(R.id.item_layout_etape_label_etape_text_view);
labelProduitTextView = (MyTextView) itemLayoutView.findViewById(R.id.item_layout_etape_label_produit_text_view);
descriptifTextView = (MyTextView) itemLayoutView.findViewById(R.id.item_layout_etape_descriptif_text_view);
labelProduitTextView.setPaintFlags(labelProduitTextView.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
imageViewEtapeSuivante = (ImageView) itemLayoutView.findViewById(R.id.item_layout_etape_vague_image_view);
imageViewPanierSelection = (ImageView) itemLayoutView.findViewById(R.id.item_layout_etape_panier_image_view);
}
}
public Etape getEtape(int position) {
Etape etape = etapeArrayList.get(position);
return etape;
}
// Return the size of your itemsData (invoked by the layout manager)
#Override
public int getItemCount() {
return etapeArrayList.size();
}
public void setClickOnProductListener(clickOnProductListener callback) {
mCallback = callback;
}
}
My function which define the Protocole RecyclerView and the rows for scrolling :
public void initProtocole(View v, final FragmentProtocoles protocoleFragment, ArrayList<Protocole> protocoleArrayList) {
super.initProtocole(v, protocoleFragment, protocoleArrayList);
initFrameLayout(v, R.id.fragment_protocole_container, R.layout.view_process_protocole_rep);
ArrayList<Protocole> fProtocoleArrayList = new ArrayList<>();
for (int i = 0; i < protocoleArrayList.size(); i++) {
fProtocoleArrayList.add(protocoleArrayList.get(i));
}
final RecyclerView recyclerView = (RecyclerView) v.findViewById(R.id.protocole_rep_recycler_view);
recyclerView.addItemDecoration(new SpacesItemDecoration(25, 25, 25, 25));
final LinearLayoutManager mLayoutManager = new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false);
recyclerView.setLayoutManager(mLayoutManager);
AdapterProtocole adapterProtocole = new AdapterProtocole(fProtocoleArrayList, v.getContext());
adapterProtocole.setClickOnProductListener(new AdapterProtocole.clickOnProductListener() {
#Override
public void appelProduit(long productId) {
protocoleFragment.appelProduit(HypredDbManager.getDbManager().getProductDbManager().getProduitById(productId));
}
#Override
public void ajouterAllProduit(ArrayList<Produit> produitArrayList) {
for (int i = 0; i < produitArrayList.size(); i++) {
SelectionManager.getInstance().addProductToSelection(produitArrayList.get(i));
}
}
#Override
public void ajouterProduit(Produit produit) {
SelectionManager.getInstance().addProductToSelection(produit);
}
});
recyclerView.setAdapter(adapterProtocole);
ImageView imageViewProtocoleFlecheGauche = (ImageView) v.findViewById(R.id.protocole_rep_fleche_gauche);
imageViewProtocoleFlecheGauche.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
RecyclerViewPositionHelper recyclerViewPositionHelper = RecyclerViewPositionHelper.createHelper(recyclerView);
int firstVisibleItem = recyclerViewPositionHelper.findFirstCompletelyVisibleItemPosition();
if (firstVisibleItem != 0) {
mLayoutManager.scrollToPositionWithOffset(firstVisibleItem - 1, 0);
}
}
});
ImageView imageViewProtocoleFlecheDroite = (ImageView) v.findViewById(R.id.protocole_rep_fleche_droite);
imageViewProtocoleFlecheDroite.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
RecyclerViewPositionHelper recyclerViewPositionHelper = RecyclerViewPositionHelper.createHelper(recyclerView);
int lastVisibleItem = recyclerViewPositionHelper.findLastCompletelyVisibleItemPosition();
int firstVisibleItem = recyclerViewPositionHelper.findFirstCompletelyVisibleItemPosition();
if (lastVisibleItem != recyclerViewPositionHelper.getItemCount() - 1) {
mLayoutManager.scrollToPositionWithOffset(firstVisibleItem + 1, 0);
}
}
});
}
Thanks in advance :)
I also face the same problem, you need to change your RecyclerView adapter::
Now it is like this in your code::
// Create new views (invoked by the layout manager)
#Override
public AdapterEtape.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View itemLayoutView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_layout_process_etape, null);
// create ViewHolder
ViewHolder viewHolder = new ViewHolder(itemLayoutView);
return viewHolder;
}
You need to change like this::
// Create new views (invoked by the layout manager)
#Override
public AdapterEtape.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View itemLayoutView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_layout_process_etape, parent, false);
// create ViewHolder
ViewHolder viewHolder = new ViewHolder(itemLayoutView);
return viewHolder;
}
Related
I want to loop through all CardViews and change the text and color of a TextView within a single CardView item using a button click. The following code seems to produce the desired results but I'm not certain that it's the most effective code or even accurate (index).
// CustomAdapter
import android.view.LayoutInflater;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
public class CustomAdapter extends RecyclerView.Adapter<CustomViewHolder> {
private Context context;
private List<MyModel> list;
public CustomAdapter(Context context, List<MyModel> list) {
this.context = context;
this.list = list;
}
#NonNull
#Override
public CustomViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new CustomViewHolder(LayoutInflater.from(context).inflate(R.layout.single_items, parent, false));
}
#Override
public void onBindViewHolder(#NonNull CustomViewHolder holder, int position) {
holder.textName.setText(list.get(position).getName());
holder.textAge.setText(String.valueOf(list.get(position).getAge()));
}
#Override
public int getItemCount() {
return list.size();
}
}
//CustomViewHolder
import android.view.View;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
public class CustomViewHolder extends RecyclerView.ViewHolder {
public TextView textName, textAge;
public CustomViewHolder(#NonNull View itemView) {
super(itemView);
textName = itemView.findViewById(R.id.textName);
textAge = itemView.findViewById(R.id.textAge);
}
}
MainActivity
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
RecyclerView recyclerView;
List<MyModel> myModelList;
CustomAdapter customAdapter;
private Button button1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
loadData();
}
private void loadData() {
recyclerView = findViewById(R.id.recycler_main);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new GridLayoutManager(this, 1));
myModelList = new ArrayList<>();
myModelList.add(new MyModel("Joe", 21));
myModelList.add(new MyModel("Jane", 26));
myModelList.add(new MyModel("Kyle", 19));
myModelList.add(new MyModel("Scott", 30));
customAdapter = new CustomAdapter(this, myModelList);
recyclerView.setAdapter(customAdapter);
}
public void onClickBtn(View v)
{
String searchString = "Kyle";
for (int x = recyclerView.getChildCount(), i = 0; i < x; ++i) {
RecyclerView.ViewHolder holder = recyclerView.getChildViewHolder(recyclerView.getChildAt(i));
TextView txtName = holder.itemView.findViewById(R.id.textName);
if (txtName.getText().toString().equals(searchString.toString())) {
txtName.setText("Found " + txtName.getText().toString());
txtName.setTextColor(Color.GREEN);
customAdapter.notifyItemChanged(x);
}
}
}
}
//MyModel
public class MyModel {
String name = "";
int age = 0;
public MyModel(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
It's important that I iterate through the list in button click event. Functionality to be changed later. Really appreciate any advice and feedback. Update. Must be an index or other related problem. When my ArrayList contains many, many more items and button is clicked, a lot of non found rows text and color are changed.
Try this adapter:
public class CustomAdapter extends RecyclerView.Adapter<CustomViewHolder> {
private Context context;
private List<MyModel> list;
private String searchString = "";
public CustomAdapter(Context context, List<MyModel> list) {
this.context = context;
this.list = list;
}
#NonNull
#Override
public CustomViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new CustomViewHolder(LayoutInflater.from(context).inflate(R.layout.single_items, parent, false));
}
#Override
public void onBindViewHolder(#NonNull CustomViewHolder holder, int position) {
holder.textAge.setText(String.valueOf(list.get(position).getAge()));
if(list.get(position).getName().equals(searchString)){
holder.textName.setText("Found " + list.get(position).getName());
holder.textName.setTextColor(Color.GREEN);
} else {
holder.textName.setText(list.get(position).getName());
holder.textName.setTextColor(Color.BLACK);
}
}
#Override
public int getItemCount() {
return list.size();
}
public void setNewSearchString(String searchString) {
this.searchString = searchString;
notifyDataSetChanged();
}
}
and button click:
public void onClickBtn(View v)
{
customAdapter.setNewSearchString("Kyle");
}
For Multiple search, the adapter:
public class CustomAdapter extends RecyclerView.Adapter<CustomViewHolder> {
private Context context;
private List<MyModel> list;
//private String searchString = "";
private ArrayList<String> arraySearchStrings = new ArrayList<>();
public CustomAdapter(Context context, List<MyModel> list) {
this.context = context;
this.list = list;
}
#NonNull
#Override
public CustomViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new CustomViewHolder(LayoutInflater.from(context).inflate(R.layout.single_items, parent, false));
}
#Override
public void onBindViewHolder(#NonNull CustomViewHolder holder, int position) {
holder.textAge.setText(String.valueOf(list.get(position).getAge()));
boolean found = false;
for (String searchString : arraySearchStrings) {
if (list.get(position).getName().equals(searchString)) {
found = true;
break;
}
}
if (found) {
holder.textName.setText("Found " + list.get(position).getName());
holder.textName.setTextColor(Color.GREEN);
} else {
holder.textName.setText(list.get(position).getName());
holder.textName.setTextColor(Color.BLACK);
}
}
#Override
public int getItemCount() {
return list.size();
}
public void setNewSearchString(String searchString) {
//this.searchString = searchString;
arraySearchStrings.add(searchString);
notifyDataSetChanged();
}
public void resetSearchString() {
arraySearchStrings.clear();
notifyDataSetChanged();
}
}
Button click:
public void onClickBtn(View v)
{
customAdapter.setNewSearchString("Kyle");
customAdapter.setNewSearchString("Steve");
customAdapter.setNewSearchString("Joe");
}
Alternative answser:
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.CustomViewHolder> {
private Context context;
private List<MyModel> list;
private ArrayList<String> arraySearchStrings = new ArrayList<>();
private ArrayList<Boolean> arrayFound = new ArrayList<>();
private int[] arrayFoundCount;
private int foundTotalCount = 0;
public CustomAdapter(Context context, List<MyModel> list) {
this.context = context;
this.list = list;
arrayFoundCount = new int[list.size()];
for (int i = 0; i < list.size(); i++) {
arrayFound.add(false);
arrayFoundCount[i] = 0;
}
}
#NonNull
#Override
public CustomViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new CustomViewHolder(LayoutInflater.from(context).inflate(R.layout.single_items, parent, false));
}
#Override
public void onBindViewHolder(#NonNull CustomViewHolder holder, int position) {
holder.textAge.setText(String.valueOf(list.get(position).getAge()));
holder.textCount.setText(String.valueOf(arrayFoundCount[position]));
if (arrayFound.get(position)) {
holder.textName.setText("Found " + list.get(position).getName());
holder.textName.setTextColor(Color.GREEN);
} else {
holder.textName.setText(list.get(position).getName());
holder.textName.setTextColor(Color.BLACK);
}
}
#Override
public int getItemCount() { return list.size(); }
public class CustomViewHolder extends RecyclerView.ViewHolder {
public TextView textName, textAge, textCount;
public CustomViewHolder(#NonNull View itemView) {
super(itemView);
textName = itemView.findViewById(R.id.textName);
textAge = itemView.findViewById(R.id.textAge);
textCount = itemView.findViewById(R.id.textCount);
}
}
private int countFoundNameInList() {
int count = 0;
boolean found;
MyModel model;
arrayFound.clear();
for (int i = 0; i < list.size(); i++) {
model = list.get(i);
found = false;
for (String searchString : arraySearchStrings) {
if (model.getName().equals(searchString)) {
found = true;
arrayFoundCount[i] = arrayFoundCount[i]++;
count++;
break;
}
}
arrayFound.add(found);
}
return count;
}
public void setNewSearchString(String searchString) {
arraySearchStrings.add(searchString);
int newCount = countFoundNameInList();
if (newCount > foundTotalCount) {
Toast.makeText(context, searchString + " found.", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(context, "Error: Nothing found!!", Toast.LENGTH_LONG).show();
}
foundTotalCount = newCount;
notifyDataSetChanged();
}
}
I don't think this code will give you accurate result.
you have to come up with different logic for this
In your logic you are searching static name i am sure this is for demo purpose only. later you will implement with user input string.
So As per my opinion you can create variable in your adapter that search mode is on or off
after this when ever user start searching make searchMode On and same as when they done with searching set searchMode Off
in your viewHolder Class you can update View on searchMode on off Status.
You can Create 2 list
1 is for main List
seconds is for searched list
when user starts searching you have to filter main list with search string and then set it to searchedList and also make searchMode On and then update it to your adapter. rest will handle your adapter. no need to change it one by one from your list.
I am adding here required changes as per my opinion
Your Custom Adapter
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.CustomViewHolder> {
private Context context;
private List<MyModel> list;
private Boolean isSearchModeOn = false;
public CustomAdapter(#NonNull Context context, #NonNull List<MyModel> list) {
this.context = context;
this.list = list;
}
#NonNull
#Override
public CustomViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new CustomViewHolder(LayoutInflater.from(context).inflate(R.layout.single_items, parent, false));
}
#Override
public void onBindViewHolder(#NonNull CustomViewHolder holder, int position) {
if (isSearchModeOn){
holder.textName.setText("Found " + list.get(position).getName());
holder.textName.setTextColor(Color.GREEN);
}else {
holder.textName.setText(list.get(position).getName());
//Also set Here normal text color
}
holder.textAge.setText(String.valueOf(list.get(position).getAge()));
}
#SuppressLint("NotifyDataSetChanged")
public void updateList(#NonNull List<MyModel> searchedList){
list = searchedList;
notifyDataSetChanged();
}
#SuppressLint("NotifyDataSetChanged")
public void setSearchMode(#NonNull Boolean isOn){
isSearchModeOn = isOn;
notifyDataSetChanged();
}
#Override
public int getItemCount() {
return list.size();
}
public class CustomViewHolder extends RecyclerView.ViewHolder {
#NonNull
public TextView textName, textAge;
public CustomViewHolder(#NonNull View itemView) {
super(itemView);
textName = itemView.findViewById(R.id.textName);
textAge = itemView.findViewById(R.id.textAge);
}
}
}
MainActivity
public class MainActivity extends AppCompatActivity {
RecyclerView recyclerView;
List<MyModel> myModelList;
List<MyModel> searchedList;
CustomAdapter customAdapter;
#Override
protected void onCreate(#NonNull Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
loadData();
}
private void loadData() {
recyclerView = findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new GridLayoutManager(this, 1));
myModelList = new ArrayList<>();
myModelList.add(new MyModel("Joe", 21));
myModelList.add(new MyModel("Jane", 26));
myModelList.add(new MyModel("Kyle", 19));
myModelList.add(new MyModel("Scott", 30));
customAdapter = new CustomAdapter(this, myModelList);
recyclerView.setAdapter(customAdapter);
}
public void onClickBtn(#NonNull View v)
{
String searchString = "Kyle";
searchedList = new ArrayList<>();
for (int x = myModelList.size(), i = 0; i < x; ++i) {
if (myModelList.get(i).getName().equals(searchString)){
searchedList.add(myModelList.get(i));
}
}
customAdapter.updateList(searchedList);
customAdapter.setSearchMode(true);
}
}
I am mostly develop in kotlin so maybe some text error can happen in this code. you can check the logic for this requirement
I tried to implement OnItemClickListener in Fragment with RecycleView Adapter, but my code seems not to work well, OnItemClickListener keeps turning red when I try to change it to getContext().
I've tried to find many ways to get it done, but that makes me find another error in my code.
.
your help will make my day brighter,
public class MountainFragment extends Fragment {
private final int LOCATION_SIZE = 10;
private final int LOCATION_TYPE = 1;
public MountainFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.word_list_activity, container, false);
String name, imageName, address;
Drawable image;
int resourceId, imageId;
final ArrayList<WorldDataModel> mountainArrays = new ArrayList<WorldDataModel>();
for (int n = 1; n <= LOCATION_SIZE; n++) {
//get Location Name
resourceId = getResources().getIdentifier("location_name_" + LOCATION_TYPE
+ "_" + n, "string", getActivity().getPackageName());
name = getResources().getString(resourceId);
//get address
resourceId = getResources().getIdentifier("location_address_" + LOCATION_TYPE
+ "_" + n, "string", getActivity().getPackageName());
address = getResources().getString(resourceId);
//get image thumbnail
resourceId = getResources().getIdentifier("location_thumbnail_" + LOCATION_TYPE
+ "_" + n, "string", getActivity().getPackageName());
imageName = getResources().getString(resourceId);
imageId = getResources().getIdentifier(imageName, "drawable", getActivity().getPackageName());
image = getResources().getDrawable(imageId);
//add new data to list
mountainArrays.add(new WorldDataModel(name, address, image));
}
// using simple recycle view
RecyclerView recyclerView = (RecyclerView) rootView.findViewById(R.id.word_list_activity);
recyclerView.setLayoutManager(new LinearLayoutManager(this.getContext()));
RecycleViewWorldAdapter adapter = new RecycleViewWorldAdapter(mountainArrays);
recyclerView.setAdapter(adapter);
//on list item click
recyclerView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
WorldDataModel worldDataModel = mountainArrays.get(position);
Intent intent = new Intent(getActivity(), DetailsActivity.class);
intent.putExtra("category", LOCATION_TYPE);
intent.putExtra("location", position + 1);
getActivity().startActivity(intent);
}
});
// Inflate the layout for this fragment
return rootView;
}
and here's my adapter class
package com.example.mytourguideapp;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
public class RecycleViewWorldAdapter extends RecyclerView.Adapter<RecycleViewWorldAdapter.MyViewHolder> {
private ArrayList<WorldDataModel> worldDataModelArrayList;
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView textViewLocationName, textViewPlacesName;
public ImageView imageOnCard;
public MyViewHolder(View itemView) {
super(itemView);
textViewLocationName = (TextView) itemView.findViewById(R.id.location_name);
textViewPlacesName = (TextView) itemView.findViewById(R.id.places_name);
imageOnCard = (ImageView) itemView.findViewById(R.id.image_on_cardview);
}
}
public RecycleViewWorldAdapter(ArrayList<WorldDataModel> worldDataModelArrayList) {
this.worldDataModelArrayList = worldDataModelArrayList;
}
#Override
public MyViewHolder onCreateViewHolder( ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item_layout, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(RecycleViewWorldAdapter.MyViewHolder holder, int position) {
WorldDataModel worldDataModel = worldDataModelArrayList.get(position);
holder.textViewPlacesName.setText(worldDataModel.getName());
holder.textViewLocationName.setText(worldDataModel.getAddress());
holder.imageOnCard.setImageDrawable(worldDataModel.getImageThumbnail());
}
#Override
public int getItemCount() {
return worldDataModelArrayList.size();
}
}
You can send the callback from your Adapter class to your fragment/activity.
First create a interface class
public interface OnItemClickListener {
void onItemClick(WorldDataModel item,int position);
}
Next modify your Adapter class , in your case RecycleViewWorldAdapter
i) Send listener as a parameter in your constructor
private final OnItemClickListener listener;
public RecycleViewWorldAdapter(ArrayList<WorldDataModel> worldDataModelArrayList, OnItemClickListener listener) {
this.worldDataModelArrayList = worldDataModelArrayList;
this.listener = listener;
}
ii) Set onCLick listener on some view in your ViewHolder class
public MyViewHolder(View itemView) {
super(itemView);
textViewLocationName = (TextView) itemView.findViewById(R.id.location_name);
textViewPlacesName = (TextView) itemView.findViewById(R.id.places_name);
imageOnCard = (ImageView) itemView.findViewById(R.id.image_on_cardview);
// change your listener on any other view if you want
imageOnCard..setOnClickListener(new View.OnClickListener() {
#Override public void onClick(View v) {
listener.onItemClick(worldDataModelArrayList.get(getAdapterPosition()),getAdapterPosition());
}
});
}
Now modify your Activity/Fragment class to listen to your interface callback , in your case MountainFragment in onCreateView
// using simple recycle view
RecyclerView recyclerView = (RecyclerView) rootView.findViewById(R.id.word_list_activity);
recyclerView.setLayoutManager(new LinearLayoutManager(this.getContext()));
RecycleViewWorldAdapter adapter = new RecycleViewWorldAdapter(mountainArrays,new RecycleViewWorldAdapter.OnItemClickListener() {
#Override public void onItemClick(WorldDataModel item, int position) {
// implement click listener as per your requirement
WorldDataModel worldDataModel = item;
Intent intent = new Intent(getActivity(), DetailsActivity.class);
intent.putExtra("category", LOCATION_TYPE);
intent.putExtra("location", position + 1);
getActivity().startActivity(intent);
});
recyclerView.setAdapter(adapter);
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 3 years ago.
I have searched a lot and didn't find any solution for my problem.I have created an interface for handling click listeners on particular item on recycler view.Logcat shows the error is occured in setting the listener in maiactivity
here is my MainActivity.java file
package com.example.mynotes;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import java.util.List;
public class MainActivity extends AppCompatActivity implements NoteAdapter.OnItemClickListener {
public static final int ADD_NOTE_REQUEST = 1;
public static final int EDIT_NOTE_REQUEST = 2;
NoteViewModel noteViewModel;
List<Note> allNotes;
RecyclerView rv;
NoteAdapter adapter;
FloatingActionButton floatingActionButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
floatingActionButton = (FloatingActionButton) findViewById(R.id.fab);
rv = (RecyclerView) findViewById(R.id.noterv);
rv.setLayoutManager(new LinearLayoutManager(this));
rv.setHasFixedSize(true);
noteViewModel = ViewModelProviders.of(this).get(NoteViewModel.class);
noteViewModel.getAllnotes().observe(this, new Observer<List<Note>>() {
#Override
public void onChanged(List<Note> notes) {
adapter = new NoteAdapter(notes);
rv.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
});
adapter.SetOnItemClickListener(this) ;
floatingActionButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(getApplicationContext(), AddNoteActivity.class);
startActivityForResult(intent, ADD_NOTE_REQUEST);
}
});
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0,
ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
#Override
public boolean onMove(#NonNull RecyclerView recyclerView, #NonNull RecyclerView.ViewHolder viewHolder, #NonNull RecyclerView.ViewHolder target) {
return false;
}
#Override
public void onSwiped(#NonNull RecyclerView.ViewHolder viewHolder, int direction) {
noteViewModel.delete(adapter.getAt(viewHolder.getAdapterPosition()));
Toast.makeText(MainActivity.this, "note has been deleted", Toast.LENGTH_SHORT).show();
}
});
itemTouchHelper.attachToRecyclerView(rv);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == ADD_NOTE_REQUEST && resultCode == RESULT_OK) {
String title = data.getStringExtra("EXTRA_TITLE");
String description = data.getStringExtra("EXTRA_DESCRIPTION");
String time = data.getStringExtra("EXTRA_TIME");
Note note = new Note(title, description, time);
noteViewModel.insert(note);
}
else if(requestCode == EDIT_NOTE_REQUEST && resultCode == RESULT_OK){
String title = data.getStringExtra("EXTRA_TITLE");
String description = data.getStringExtra("EXTRA_DESCRIPTION");
String time = data.getStringExtra("EXTRA_TIME");
Note note = new Note(title, description, time);
note.setId(data.getIntExtra("EXTRA_ID",-1));
noteViewModel.update(note);
Toast.makeText(this, "note has been updated", Toast.LENGTH_SHORT).show();
}
}
#Override
public void OnItemClick(Note note) {
Intent intent =new Intent(MainActivity.this,AddNoteActivity.class);
intent.putExtra("EXTRA_ID",note.getId());
intent.putExtra("EXTRA_TITLE",note.getTitle());
intent.putExtra("EXTRA_DESCRIPTION",note.getDescription());
intent.putExtra("EXTRA_TIME",note.getModified_time());
startActivityForResult(intent,EDIT_NOTE_REQUEST);
}
}
here is my NoteAdapter.java file
package com.example.mynotes;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
public class NoteAdapter extends RecyclerView.Adapter<NoteAdapter.NoteViewHolder> {
OnItemClickListener listener;
List<Note> notes=new ArrayList<>();
public NoteAdapter(List<Note> notes) {
this.notes = notes;
}
#NonNull
#Override
public NoteViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
// Inflate the custom layout
View item_view = inflater.inflate(R.layout.single_note_item, parent, false);
// Return a new holder instance
NoteViewHolder viewHolder = new NoteViewHolder(item_view);
return viewHolder;
}
#Override
public void onBindViewHolder(#NonNull NoteViewHolder holder, int position) {
Note note =notes.get(position);
holder.titletv.setText(note.getTitle());
holder.datetv.setText(note.getModified_time());
}
#Override
public int getItemCount() {
return notes.size();
}
public class NoteViewHolder extends RecyclerView.ViewHolder{
TextView titletv ;
TextView datetv;
public NoteViewHolder(#NonNull View itemView) {
super(itemView);
titletv=(TextView) itemView.findViewById(R.id.titletv);
datetv=(TextView) itemView.findViewById(R.id.datetv);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(listener !=null && getAdapterPosition() != RecyclerView.NO_POSITION){
int position=getAdapterPosition();
listener.OnItemClick(notes.get(position));
}
}
});
}
}
Note getAt(int position){
return notes.get(position);
}
public interface OnItemClickListener{
void OnItemClick(Note note);
}
public void SetOnItemClickListener(OnItemClickListener onItemClickListener){
this.listener =onItemClickListener;
}
}
here is my Logcat message:
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.example.mynotes.NoteAdapter.SetOnItemClickListener(com.example.mynotes.NoteAdapter$OnItemClickListener)' on a null object reference
at com.example.mynotes.MainActivity.onCreate(MainActivity.java:52)
at android.app.Activity.performCreate(Activity.java:7009)
at android.app.Activity.performCreate(Activity.java:7000)
Move this code to observer
adapter.SetOnItemClickListener(this) ;
So your code must be like this
noteViewModel.getAllnotes().observe(this, new Observer<List<Note>>() {
#Override
public void onChanged(List<Note> notes) {
adapter = new NoteAdapter(notes);
adapter.SetOnItemClickListener(this);
rv.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
});
do this in your adapter and where you will new your adapter in activity:
package com.example.mynotes;
public class NoteAdapter extends RecyclerView.Adapter {
OnItemClickListener listener;
List<Note> notes=new ArrayList<>();
public NoteAdapter(List<Note> notes, OnItemClickListener listener) {
this.notes = notes;
this.listener = listener;
}
#NonNull
#Override
public NoteViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
// Inflate the custom layout
View item_view = inflater.inflate(R.layout.single_note_item, parent, false);
// Return a new holder instance
NoteViewHolder viewHolder = new NoteViewHolder(item_view);
return viewHolder;
}
#Override
public void onBindViewHolder(#NonNull NoteViewHolder holder, int position) {
Note note =notes.get(position);
holder.titletv.setText(note.getTitle());
holder.datetv.setText(note.getModified_time());
}
#Override
public int getItemCount() {
return notes.size();
}
public class NoteViewHolder extends RecyclerView.ViewHolder{
TextView titletv ;
TextView datetv;
public NoteViewHolder(#NonNull View itemView) {
super(itemView);
titletv=(TextView) itemView.findViewById(R.id.titletv);
datetv=(TextView) itemView.findViewById(R.id.datetv);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(listener !=null && getAdapterPosition() != RecyclerView.NO_POSITION){
int position=getAdapterPosition();
listener.OnItemClick(notes.get(position));
}
}
});
}
}
Note getAt(int position){
return notes.get(position);
}
public interface OnItemClickListener{
void OnItemClick(Note note);
}
public void SetOnItemClickListener(OnItemClickListener onItemClickListener){
this.listener =onItemClickListener;
}
}
and now in your activity where you will new your adapter do this:
adapter = new NoteAdapter(notes, NoteAdapter.OnItemClickListener() {
#Override
public void OnItemClick(Note note) {
//DO WHATEVER YOU WANT HERE
}
I found similar issue Facebook Native ads in recycler view android , but had some problems with integration with Custom Ad.
For the first I tried to describe NativeAdsManager :
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
manager = new NativeAdsManager(getActivity(), "892769720837476_892772047503910", 5);
manager.setListener(this);
manager.loadAds();
nativeAd = new NativeAd(getActivity(), "892769720837476_892772047503910");
nativeAd.setAdListener(this);
nativeAd.loadAd();
...
}
Then I included Native ad as a parameter in RecyclerAdapter constructor:
adapter = new RecyclerAdapter(foodDataList, getActivity(), nativeAd);
In this Class I also implement AdListener and NativeAdsManager.Listener methods:
#Override
public void onError(Ad ad, AdError adError) {
}
#Override
public void onAdLoaded(Ad ad) {
}
#Override
public void onAdClicked(Ad ad) {
}
#Override
public void onAdsLoaded() {
System.out.println("Loaded in fragment");
nativeAd = manager.nextNativeAd();
nativeAd.setAdListener(this);
adapter.notifyDataSetChanged();
}
#Override
public void onAdError(AdError adError) {
}
After that in RecyclerAdapter class :
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
switch (holder.getItemViewType()) {
...
case 2:
AdditionalHolder new_holder = (AdditionalHolder) holder;
adView = NativeAdView.render(context, nativeAd, NativeAdView.Type.HEIGHT_100);
new_holder.templateContainer.addView(adView);
return;
...
public class AdditionalHolder extends RecyclerView.ViewHolder {
protected LinearLayout templateContainer;
public AdditionalHolder(View view) {
super(view);
templateContainer = (LinearLayout) view.findViewById(R.id.ad_test2);
}
}
After all of that my Fragment with RecyclerView becomes very "luggy" and every time I can see more and more ads items (1 - from the beginning, 2 - after 10 items, 3 - after next 10 and so on).
It's my first time of using multiple RecyclerView holders, and find this issue difficult.
Provide you with gist of 2 Classes
https://gist.github.com/burnix/6af8196ee8acf5c8f94e - RecyclerAdapter.class
https://gist.github.com/burnix/53dc2ed7446969b78f07 - FragmentList.class
Help me please to solve lugs problem and to place AudienceNetwork as it needs to be.
Thanks in advance!
After several hours of headache I solved my problem.
I needed to change the constructor of RecyclerView:
public RecyclerAdapter(List<FoodData> food, Context context, NativeAd nativeAd, NativeAdsManager manager) {
this.foodDataList = food;
this.context = context;
this.nativeAd = nativeAd;
this.manager = manager;
}
And implement the behavior of Native Ads in onBindViewHolder:
AdditionalHolder new_holder = (AdditionalHolder) holder;
try {
new_holder.templateContainer.removeViewInLayout(adView);
} catch (Exception e) {
e.printStackTrace();
}
nativeAd = manager.nextNativeAd();
try {
adView = NativeAdView.render(context, nativeAd, NativeAdView.Type.HEIGHT_300);
} catch (NullPointerException e) {
e.printStackTrace();
}
new_holder.templateContainer.addView(adView);
new_holder.blank_holder.setVisibility(View.GONE);
But it hasn't solved my problem entirely (micro-lags while scrolling), but still it could be useful for someone, I hoped.
Youur adapter==>
import android.app.Activity;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.drawable.GlideDrawable;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.target.Target;
import com.romantic.pictures.hd.love.wallpaper.download.R;
import com.romantic.pictures.hd.love.wallpaper.download.activity.ROMANTIC_LOVE_WALLPAPER;
import com.romantic.pictures.hd.love.wallpaper.download.model.ImageStorage;
import java.util.ArrayList;
/**
* Created by abc on 4/11/2018.
*/
public class ImageAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public final int CONTENT_TYPE = 0;
public final int AD_TYPE = 1;
private OnItemClickListener mOnItemClickListener;
Activity context;
ArrayList<ImageStorage> catagorilist;
public ImageAdapter(Activity context, ArrayList<ImageStorage> catagorilist, OnItemClickListener mOnItemClickListener) {
this.mOnItemClickListener = mOnItemClickListener;
this.context = context;
this.catagorilist = catagorilist;
}
public interface OnItemClickListener {
public void onItemClick(View view, int position);
}
#Override
public int getItemViewType(int position) {
Log.e("TAG", "getItemViewType position : " + position);
Log.e("TAG", "getItemViewType position% : " + position % 5);
if (position % 7 == 0)
return AD_TYPE;
return CONTENT_TYPE;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case CONTENT_TYPE:
Log.e("TAG", "content type : ");
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.my_layout2, parent, false);
return new MyHolder(view);
case AD_TYPE:
Log.e("TAG", "ad type : ");
View nativeView = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_nativead, parent, false);
return new NativeAd(nativeView);
default:
Log.e("TAG", "default : ");
LayoutInflater inflater1 = LayoutInflater.from(parent.getContext());
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.my_layout2, parent, false);
return new MyHolder(v);
}
}
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
holder.setIsRecyclable(false);
int viewType = getItemViewType(position);
ImageStorage listitem = catagorilist.get(position);
switch (viewType) {
case CONTENT_TYPE:
Log.e("TAG", "bind CONTENT_TYPE : ");
final MyHolder menuItemHolder = (MyHolder) holder;
// holder.imagview.setText(listitem.getId());
/*holder.cat_name.setText(listitem.getName());*/
Glide.with(context).load("http://learntodraw.in/ImageApp/new_" + listitem.getCat_imagem()).listener(new RequestListener<String, GlideDrawable>() {
#Override
public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
return false;
}
#Override
public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
menuItemHolder.progressBar.setVisibility(View.GONE);
return false;
}
}).into(menuItemHolder.imagview);
Log.e("TAG", "onBindViewHolder: " + "http://learntodraw.in/ImageApp/new_" + listitem.getCat_imagem());
Log.e("TAG", "onBindViewHolder: " + position);
menuItemHolder.mainLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mOnItemClickListener.onItemClick(v, position);
}
});
break;
case AD_TYPE:
Log.e("TAG", "bind AD_TYPE : ");
final NativeAd nativeHolder = (NativeAd) holder;
ROMANTIC_LOVE_WALLPAPER.showNativeVidAd(context, nativeHolder.container);
nativeHolder.container_height.post(new Runnable() {
public void run() {
// int height = nativeHolder.container_height.getHeight();
ViewGroup.LayoutParams params = nativeHolder.container.getLayoutParams();
// params.height = height;
params.height = LinearLayout.LayoutParams.WRAP_CONTENT;
nativeHolder.container.setLayoutParams(params);
// nativeHolder.linearlayout_title.setVisibility(View.GONE);
}
});
break;
}
}
#Override
public int getItemCount() {
return catagorilist.size();
}
public class MyHolder extends RecyclerView.ViewHolder {
public ImageView imagview;
public LinearLayout mainLayout;
public CardView cardview;
public ProgressBar progressBar;
public MyHolder(View itemView) {
super(itemView);
imagview = (ImageView) itemView.findViewById(R.id.imagview);
mainLayout = (LinearLayout) itemView.findViewById(R.id.mainLayout);
progressBar = (ProgressBar) itemView.findViewById(R.id.progressBar);
cardview = (CardView) itemView.findViewById(R.id.cardview);
}
}
public static class NativeAd extends RecyclerView.ViewHolder {
LinearLayout container;
LinearLayout container_height;
// LinearLayout linearlayout_title;
public NativeAd(View view) {
super(view);
container = view.findViewById(R.id.native_ad_container);
container_height = view.findViewById(R.id.container_height);
/* linearlayout_title = view.findViewById(R.id.linearlayout_title);*/
}
}
}
public static void showNativeVidAd(final Activity context, final LinearLayout nativeContainer) {
final NativeAd nativeAd = new NativeAd(context, context.getString(R.string.fb_test_ad_img) + context.getString(R.string.native_ads3));
// final NativeAd nativeAd = new NativeAd(context, context.getString(R.string.facebook_native_ad_unit_id));
nativeAd.setAdListener(new com.facebook.ads.AdListener() {
#Override
public void onError(Ad ad, AdError error) {
// Ad error callback
Log.e("TAG", "facebook native error : " + error.getErrorMessage());
nativeContainer.setVisibility(View.GONE);
}
#Override
public void onAdLoaded(Ad ad) {
// Ad loaded callback
Log.e("TAG", "facebook native onAdLoaded : ");
if (nativeAd != null) {
nativeAd.unregisterView();
}
try {
LinearLayout nativeAdContainer = nativeContainer;
nativeAdContainer.setVisibility(View.VISIBLE);
// Add the Ad view into the ad container.
nativeAdContainer = (LinearLayout) context.findViewById(R.id.native_ad_container);
LayoutInflater inflater = LayoutInflater.from(context);
// Inflate the Ad view. The layout referenced should be the one you created in the last step.
RelativeLayout adView = (RelativeLayout) inflater.inflate(R.layout.custom_nativead, nativeAdContainer, false);
nativeAdContainer.removeAllViews();
nativeAdContainer.addView(adView);
// Create native UI using the ad metadata.
MediaView nativeAdMedia = (MediaView) adView.findViewById(R.id.native_ad_media);
/* //TextView nativeAdSocialContext = (TextView) adView.findViewById(R.id.native_ad_social_context);
Typeface typeface = Typeface.createFromAsset(context.getAssets(), "ProximaNova-Semibold.otf");
nativeAdSocialContext.setTypeface(typeface);*/
// TextView nativeAdCallToAction = (TextView) adView.findViewById(R.id.native_ad_call_to_action);
// Set the Text.
// nativeAdSocialContext.setText(nativeAd.getAdSocialContext());
// nativeAdCallToAction.setText(nativeAd.getAdCallToAction());
// Download and display the ad icon.
// NativeAd.Image adIcon = nativeAd.getAdIcon();
// Download and display the cover image.
nativeAdMedia.setNativeAd(nativeAd);
// Add the AdChoices icon
LinearLayout adChoicesContainer = (LinearLayout) adView.findViewById(R.id.ad_choices_container);
AdChoicesView adChoicesView = new AdChoicesView(context, nativeAd, true);
adChoicesContainer.addView(adChoicesView);
// Register the Title and CTA button to listen for clicks.
List<View> clickableViews = new ArrayList<>();
// clickableViews.add(nativeAdCallToAction);
clickableViews.add(nativeAdMedia);
clickableViews.add(adChoicesContainer);
nativeAd.registerViewForInteraction(nativeAdContainer, clickableViews);
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onAdClicked(Ad ad) {
// Ad clicked callback
}
#Override
public void onLoggingImpression(Ad ad) {
// Ad impression logged callback
Log.e("TAG", "facebook native onLoggingImpression");
}
});
// Request an ad
nativeAd.loadAd(NativeAd.MediaCacheFlag.ALL);
}
when I dynamic remove an item, or when I refresh the adapter(swipe to fresh) i get these erros:
recyclerview onclicklistener java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0
Really can't figure out why this is happening, Really Appreciate any feed back.
MainActivity:
adapter.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(View view, int position) {
GroupModel selectedList = mGroupModels.get(position);
if (selectedList != null) {
Log.d(TAG, "setAdpterListner > view.getId: " + view.getId() +
" | P: " + position +
" | data ID: " + selectedList.getGroupName()
//" | viewID: " + viewID
);
Intent intent = new Intent(this, DetailsActivity.class);
String listId = selectedList.getGroupID();
String listName = selectedList.getGroupName();
intent.putExtra(Constant.KEY_LIST_ID, listId);
intent.putExtra(Constant.KEY_LIST_NAME, listName);
startActivity(intent);
}
}
});
Adapter:
public class GroupListAdapter extends RecyclerView.Adapter<GroupListAdapter.StatusViewHolder> {
Context context;
private List<GroupModel> mGroupModels;
private static OnItemClickListener listener;
public GroupListAdapter(Context context, List<GroupModel> groupList) {
this.context = context;
this.mGroupModels = groupList;
}
public void setOnItemClickListener(OnItemClickListener listener) {
GroupListAdapter.listener = listener;
}
#Override
public StatusViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.single_group_list, parent, false);
return new StatusViewHolder(view);
}
#Override
public void onBindViewHolder(StatusViewHolder holder, int position) {
final GroupModel data = mGroupModels.get(position);
holder.text_view_list_name.setText(data.getGroupName());
}//end onBindViewHolder
#Override
public int getItemCount() {
return mGroupModels.size();
}
public class StatusViewHolder extends RecyclerView.ViewHolder {
public TextView text_view_list_name;
public TextView created_by;
public StatusViewHolder(final View itemView) {
super(itemView);
text_view_list_name = (TextView) itemView.findViewById(R.id.text_view_list_name);
created_by = (TextView) itemView.findViewById(R.id.created_by);
// Setup the click listener
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (listener != null)
listener.onItemClick(itemView, getLayoutPosition());
}
});
}
}//end StatusViewHolder
}//end GroupListAdapter
UPDATE:
I taken into consideration Yurii Tsap Feedback. I check the code again. I think the problem is somewhere below:
Whenever I swipe to Fresh, and If i click on the list straight way, the app Crash with the error from above.
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
// Refresh items
mRecyclerView.invalidate();
adapter = null;
initGetGroupList();
mSwipeRefreshLayout.setRefreshing(false);
}
});
In the API call
...
GroupModel groupModel = new GroupModel(groupID, groupName, groupCreatedBy);
mGroupModels.add(groupModel);
}
updateUI(true);
if (adapter == null) {
adapter = new GroupListAdapter(MainActivity.this, mGroupModels);
mRecyclerView.setAdapter(adapter);
setAdapterListener(adapter);
}
The problem is definitely not in the static listener. And also the listener is just an interface callback(related to the comment above) not a AdapterView.OnItemClickListener(). I think the problem is somewhere behind this code, maybe you are clearing the item list somewhere else or something like that?
And also as for me in your case it's better to use getAdapterPosition() instead of getLayoutPosition().
As mentioned in docs :
If LayoutManager needs to call an external method that requires the adapter position of the item, it can use getAdapterPosition() or RecyclerView.Recycler.convertPreLayoutPositionToPostLayout(int).
Make OnItemClickListener non static .Like
private OnItemClickListener listener;
your code have alot of problem
i will explain my way to handle recycle view
very simple adapter
package com.pentavalue.ongo.transportway.adapter;
import android.app.Activity;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import com.pentavalue.ongo.R;
import com.pentavalue.ongo.Utilts.ImageLoaderHelper;
import com.pentavalue.ongo.register.model.Vechiles;
import com.pentavalue.ongo.widget.ArabicTextView;
import java.util.ArrayList;
/**
* Created by hamada on 19/09/2015.
*/
public class TransportTypeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public LayoutInflater inflater = null;
Activity activity;
ArrayList<Vechiles> vechileList;
ImageLoaderHelper imageLoaderHelper;
public TransportTypeAdapter(Activity activity, ArrayList<Vechiles> vechileList) {
this.activity = activity;
this.vechileList = vechileList;
imageLoaderHelper = new ImageLoaderHelper(activity, null);
inflater = LayoutInflater.from(activity);
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View vi = inflater.inflate(R.layout.single_transport_item, parent, false);
RecyclerView.ViewHolder vh = new VechileListHolder(vi);
return vh;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int pos) {
VechileListHolder mHolder = (VechileListHolder) viewHolder;
mHolder.renderDate(vechileList.get(pos));
}
#Override
public int getItemCount() {
if (vechileList != null)
return this.vechileList.size();
else
return 0;
}
public class VechileListHolder extends RecyclerView.ViewHolder implements
View.OnClickListener {
ArabicTextView vecName;
RelativeLayout img_layout;
ProgressBar progress;
ImageView imgView;
public VechileListHolder(View vi) {
super(vi);
vi.setOnClickListener(this);
img_layout = (RelativeLayout) vi.findViewById(R.id.img_layout);
vecName = (ArabicTextView) vi.findViewById(R.id.TVVecName);
progress = (ProgressBar) vi.findViewById(R.id.progress);
imgView = (ImageView) vi.findViewById(R.id.imgView);
}
public void renderDate(Vechiles item) {
imageLoaderHelper.loadImage(imgView, progress, item.getImg());
vecName.setText(item.getVecName());
}
#Override
public void onClick(View v) {
if (mItemClickListener != null)
mItemClickListener.onItemClickListener(getPosition(), v);
}
}
public void setOnItemClickListener(ItemClickListener itemClick) {
this.mItemClickListener = itemClick;
}
public ItemClickListener mItemClickListener;
public interface ItemClickListener {
public void onItemClickListener(int pos, View v);
}
public void updateList(ArrayList<Vechiles> vechileList) {
this.vechileList = vechileList;
notifyDataSetChanged();
}
public void removeItem(int pos){
this.vechileList.remove(pos);
notifyItemRemoved(pos);
}
}
and in Fragment or activity can
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initListView();
}
private void initRecycleView(){
listView = (RecyclerView) v.findViewById(R.id.listView);
listView.getItemAnimator().setAddDuration(1000);
listView.getItemAnimator().setChangeDuration(1000);
listView.getItemAnimator().setMoveDuration(1000);
listView.getItemAnimator().setRemoveDuration(1000);
listView.setLayoutManager(new GridLayoutManager(getActivity(), 3));
listView.setAdapter(new TransportTypeAdapter(getActivity(), vecList));
}
then after data back from API can update adapter with new data by use method update
((VechileListHolder ) listView.getAdapter).updateList( vechileList);
in case went to remove any item by using Pos can do call method that in adapter removeItem(pos)
((VechileListHolder ) listView.getAdapter).removeItem(1);
hope this code help you