RecyclerView with Header Getting Duplicate Items - android

I have a recyclerview list of items and in the adapter, I have a button for adding an item as favorite to an active android database like below code:
viewholder.favoriteWP_IV.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Favorites favorites = new Favorites(); // Model class for db crud
favorites.setFavoritesId(UUID.randomUUID().toString());
favorites.setLargeImgURL(pixaImages.getLargeImgURL());
favorites.setPreviewImgURL(pixaImages.getPreviewImgURL());
favorites.setImageId(favorites.getImageId());
favorites.save();
Log.d(TAG, "Fav_id:\t" + favorites.getId());
Log.d(TAG, "Favorites Id:\t" + favorites.getFavoritesId());
//TODO: 6/13/2018 Fix Duplicate Favorite WP
Toast.makeText(context, "Added to Favorites", Toast.LENGTH_SHORT).show();
}
});
and in my FavoritesActivity, I have retrieved all the items and shown them in a recyclerview like below code:
public List<Favorites> getAllFavorites() {
return new Select()
.all()
.from(Favorites.class)
.orderBy("favorites_id ASC")
.execute();
}
private void getFavorites() {
favsRV.setHasFixedSize(true);
favsRV.setLayoutManager(new LinearLayoutManager(this));
AdapterHeaderItem headerItem = new AdapterHeaderItem();
headerItem.setHeaderIcon(R.drawable.drawer_header_trimmed);
headerItem.setHeaderTitle("you can toggle through your favorite wallpapers using the wallpaper widget on your home screen");
objectList.add(headerItem);
//itemsList = getAllFavorites();
Favorites favorites = new Favorites();
for (int i = 0; i < getAllFavorites().size(); i++) {
favorites.setFavoritesId(getAllFavorites().get(i).getFavoritesId());
favorites.setLargeImgURL(getAllFavorites().get(i).getLargeImgURL());
favorites.setPreviewImgURL(getAllFavorites().get(i).getPreviewImgURL());
favorites.setImageId(getAllFavorites().get(i).getImageId());
Log.d(TAG, "All Favs Ids:\t" + getAllFavorites().get(i).getFavoritesId());
objectList.add(favorites);
}
Log.d(TAG, "Favorites List Size:\t" + objectList.size());
adapter = new FavoritesAdapter(this, objectList);
favsRV.setAdapter(adapter);
}
The problem here is that the item clicked on to be saved is not the one actually saved and when the list has multiple items, it retrieves duplicate copies of same item.
Previously, my adapter wasn't having a header and it was working fine but when I added the header to adapter, I had to change from List<Favorites> to List<Object> to enable me add the header items to the view.
In my activity, I have retrieved all the records while using old adapter code by this line itemsList = getAllFavorites(); but with the new adapter code, I have to use an object to store items in list.
I have tried this Favorites favs = (Favorites) itemsList = getAllFavorites(); but the app crashed, only other option I had was to do this and save in object list:
Favorites favorites = new Favorites();
for (int i = 0; i < getAllFavorites().size(); i++) {
favorites.setFavoritesId(getAllFavorites().get(i).getFavoritesId());
favorites.setLargeImgURL(getAllFavorites().get(i).getLargeImgURL());
favorites.setPreviewImgURL(getAllFavorites().get(i).getPreviewImgURL());
favorites.setImageId(getAllFavorites().get(i).getImageId());
Log.d(TAG, "All Favs Ids:\t" + getAllFavorites().get(i).getFavoritesId());
objectList.add(favorites);
}
Here's my model class:
import com.activeandroid.Model;
import com.activeandroid.annotation.Column;
import com.activeandroid.annotation.Table;
#Table(name = "favorites")
public class Favorites extends Model{
#Column(name = "favorites_id")
public String favoritesId;
#Column(name = "image_id")
public int imageId;
#Column(name = "large_img_url")
public String largeImgURL;
#Column(name = "preview_img")
public String previewImgURL;
public Favorites() { }
public Favorites(String favoritesId, int imageId, String largeImgURL, String previewImgURL) {
this.favoritesId = favoritesId;
this.imageId = imageId;
this.largeImgURL = largeImgURL;
this.previewImgURL = previewImgURL;
}
public String getFavoritesId() {
return favoritesId;
}
public void setFavoritesId(String favoritesId) {
this.favoritesId = favoritesId;
}
public int getImageId() {
return imageId;
}
public void setImageId(int imageId) {
this.imageId = imageId;
}
public String getLargeImgURL() {
return largeImgURL;
}
public void setLargeImgURL(String largeImgURL) {
this.largeImgURL = largeImgURL;
}
public String getPreviewImgURL() {
return previewImgURL;
}
public void setPreviewImgURL(String previewImgURL) {
this.previewImgURL = previewImgURL;
}
}
but this code block gives me for a list of three items, one item duplicated three times. I think it's because of the change in code. The adapter works well but in activity, I am fetching wrong results.
Here's my adapter code:
public class FavoritesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final String TAG = FavoritesAdapter.class.getSimpleName();
private final Context context;
private List<Object> itemsList;
public static final int HEADER_VIEW = 0;
public static final int ITEMS_VIEW = 1;
public FavoritesAdapter(Context context, List<Object> itemsList) {
this.context = context;
this.itemsList = itemsList;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
if (viewType == HEADER_VIEW) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.app_adapter_header_layout, parent, false);
return new AdapterHeaderItemViewHolder(view);
} else if (viewType == ITEMS_VIEW) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.favorites_item_layout, parent, false);
return new FavoritesViewHolder(view);
}
throw new RuntimeException("No matching viewTypes");
}
#Override
public void onBindViewHolder(#NonNull final RecyclerView.ViewHolder holder, int position) {
if (holder instanceof AdapterHeaderItemViewHolder) {
AdapterHeaderItem header = (AdapterHeaderItem) itemsList.get(position);
((AdapterHeaderItemViewHolder) holder).headerTitleTV.setText(header.getHeaderTitle());
Picasso.with(context)
.load(header.getHeaderIcon())
.placeholder(R.drawable.drawer_header_trimmed)
.into(((AdapterHeaderItemViewHolder) holder).headerIconIV);
} else if (holder instanceof FavoritesViewHolder) {
final Favorites favorites = (Favorites) itemsList.get(position);
Picasso.with(context)
.load(favorites.getLargeImgURL())
.placeholder(R.mipmap.ic_launcher)
.into(((FavoritesViewHolder) holder).favoriteWPImg);
((FavoritesViewHolder) holder).removeTV.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.d(TAG, "Adapter VH Posn:\t" + holder.getAdapterPosition());
String fav_id = favorites.getFavoritesId();
Log.d(TAG, "Favorites+id:\t" + fav_id);
removeAtPosition(holder.getAdapterPosition(), fav_id);
}
});
((FavoritesViewHolder) holder).previewTV.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent previewIntent = new Intent(context, PreviewWallPaperActivity.class);
previewIntent.putExtra("fav_id", favorites.getFavoritesId());
previewIntent.putExtra("large_url", favorites.getLargeImgURL());
previewIntent.putExtra("preview_url", favorites.getPreviewImgURL());
context.startActivity(previewIntent);
}
});
}
}
private void removeAtPosition(int position, String id) {
Log.d(TAG, "id in method:\t" + id);
new Delete()
.from(Favorites.class)
.where("favorites_id=?", id)
.execute();
Log.d(TAG, "Favorite Removed from db");
itemsList.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, itemsList.size());
Toast.makeText(context, "Removed From Favorites", Toast.LENGTH_SHORT).show();
}
#Override
public int getItemCount() {
if (itemsList == null) {
return 0;
}
return itemsList.size();
}
#Override
public int getItemViewType(int position) {
if (isPositionHeader(position))
return HEADER_VIEW;
return ITEMS_VIEW;
}
private boolean isPositionHeader(int position) {
return position == 0;
}
}
I think the problem lies here with the loop and inserting into the adapter list:
itemsList = getAllFavorites();
Favorites favorites = new Favorites();
for (int i = 0; i < getAllFavorites().size(); i++) {
favorites.setFavoritesId(getAllFavorites().get(i).getFavoritesId());
favorites.setLargeImgURL(getAllFavorites().get(i).getLargeImgURL());
favorites.setPreviewImgURL(getAllFavorites().get(i).getPreviewImgURL());
favorites.setImageId(getAllFavorites().get(i).getImageId());
Log.d(TAG, "All Favs Ids:\t" + getAllFavorites().get(i).getFavoritesId());
objectList.add(favorites);
}
//objectList.add(itemsList); // I have tried adding the first list of Favorite model class into the adapter list but it gives `classcast exception: Model class can't be cast to ArrayList`
Can anyone help me understand why same item is coming multiple times? Thanks.

Related

How to update inner adapter item in android nested recycler view

I would like to update panel wise items in inner adapter item android recyclerview. When we pass the data dynamically.Data displaying is working fine. When we go to update the inner adapter item, it's not getting updated. But last item was getting update fine.
Activity.
public class PannelCreation extends AppCompatActivity {
RecyclerView userPanelRecycler;
List<String> roomPanels = new ArrayList<>();
List<JSONObject> roomItemObject = new ArrayList<JSONObject>();
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pannel_creation);
userPanelRecycler = findViewById(R.id.user_panel_recycler);
for(int i=0; i<=5;i++){
roomPanels.add("Panels "+i)
}
PanelAdapter panelAdapter = new PanelAdapter(getApplicationContext(),roomPanels);
userPanelRecycler.setLayoutManager(new LinearLayoutManager(this));
userPanelRecycler.setHasFixedSize(true);
userPanelRecycler.setAdapter(panelAdapter);
}
}
// OuterAdapter
class PanelAdapter extends RecyclerView.Adapter<PanelAdapter.ViewHolder>{
Context context;
List<String> roomPanelList;
RecyclerView.RecycledViewPool recycledViewPool;
List<ItemData> itemDataList = new ArrayList<>();
public PanelAdapter(Context context, List<String> roomPanels) {
this.context = context;
this.roomPanelList = roomPanels;
recycledViewPool = new RecyclerView.RecycledViewPool();
}
#NonNull
#Override
public PanelAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.panel_wise_layout,parent,false);
ViewHolder viewHolder = new ViewHolder(view);
viewHolder.itemsRecycler.setRecycledViewPool(recycledViewPool);
return viewHolder;
}
#Override
public void onBindViewHolder(#NonNull PanelAdapter.ViewHolder holder, int position) {
holder.userPanelName.setText(roomPanelList.get(position));
String cur_panelName = roomPanelList.get(position);
itemsAdapter = new ItemsAdapter(context);
holder.itemsRecycler.setLayoutManager(new GridLayoutManager(context,3));
holder. itemsRecycler.setHasFixedSize(true);
holder.itemsRecycler.setAdapter(itemsAdapter);
holder.itemsRecycler.setNestedScrollingEnabled(false);
try {
roomItemObject.clear();
JSONArray metaArray = new JSONArray(metaData);
int count = 0;
for(int i = 0;i<metaArray.length();i++){
JSONObject object = metaArray.getJSONObject(i);
String name = object.getString("name");
String[] rNum = name.split("_");
if(rNum[0].equalsIgnoreCase(roomNumber)){
roomItemObject.add(object);
}
count = count+1;
}
if(count == metaArray.length()){
int count1 = 0;
itemDataList.clear();
for(int i =0; i < roomItemObject.size();i++){
JSONObject itemObject1 = roomItemObject.get(i);
String groupNames = itemObject1.getString("groupNames");
String types = itemObject1.getString("type");
String metaValue = itemObject1.getString("metadata");
JSONObject panelObject = new JSONObject(metaValue);
String panel_name = panelObject.getString("panelName");
JSONObject valueObject = new JSONObject(panel_name);
String value = valueObject.getString("value");
if(value.equalsIgnoreCase(cur_panelName)){
String labels = itemObject1.getString("label");
String names = itemObject1.getString("name");
String state = itemObject1.getString("state");
String groupName = itemObject1.getString("groupNames");
String tags = itemObject1.getString("tags");
ItemData itemData = new ItemData();
itemData.setLabelName(labels);
itemData.setState(state);
itemData.setItemName(names);
itemData.setTags(tags);
itemData.setTypes(types);
itemData.setGroup(groupName);
itemDataList.add(itemData);
itemsAdapter.addItems(itemDataList);
itemsAdapter.notifyDataSetChanged();
}
}
}
}catch (JSONException e){
e.printStackTrace();
}
}
#Override
public int getItemCount() {
return roomPanelList.size();
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemViewType(int position) {
return position;
}
public class ViewHolder extends RecyclerView.ViewHolder{
RecyclerView itemsRecycler;
TextView userPanelName;
Button deletePanel;
public ViewHolder(#NonNull View itemView) {
super(itemView);
itemsRecycler = itemView.findViewById(R.id.panel_item_recycler);
userPanelName = itemView.findViewById(R.id.test_panel_name);
deletePanel = itemView.findViewById(R.id.delete_panel);
}
}
}
//Inner Adapter
class ItemsAdapter extends RecyclerView.Adapter<ItemsAdapter.ItemHolder>{
Context mContext;
List<ItemData> innerItemDataList = new ArrayList<>();
List<JSONObject> itemObjectList = new ArrayList<JSONObject>();
List<JSONObject> recObjectList = new ArrayList<>();
ItemData itemData;
public ItemsAdapter(Context context) {
this.mContext = context;
this.itemData = new ItemData();
}
public void addItems(List<ItemData> itemData){
this.innerItemDataList.clear();
this.innerItemDataList.addAll(itemData);
notifyDataSetChanged();
}
#NonNull
#Override
public ItemsAdapter.ItemHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(mContext).inflate(R.layout.panel_wise_item,parent,false);
return new ItemHolder(itemView);
}
#Override
public void onBindViewHolder(#NonNull ItemHolder holder, int position) {
itemData = innerItemDataList.get(position);
if(itemData != null){
holder.itemNames.setText(itemData.getLabelName());
}
#Override
public int getItemCount() {
return innerItemDataList.size();
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemViewType(int position) {
return position;
}
public class ItemHolder extends RecyclerView.ViewHolder {
TextView itemNames;
LinearLayout itemLayout;
ImageView itemImg;
public ItemHolder(#NonNull View itemView) {
super(itemView);
itemNames = itemView.findViewById(R.id.panel_item_name);
itemLayout = itemView.findViewById(R.id.panel_light_linear);
itemImg = itemView.findViewById(R.id.panel_item_img);
}
}
public void updateItem(String itemName,String state){
for(int j=0;j<innerItemDataList.size();j++){
if(itemName.equalsIgnoreCase(innerItemDataList.get(j).getItemName())){
innerItemDataList.get(j).setState(state);
notifyDataSetChanged();
}
}
}
}
//Inner adapter data model class
public class ItemData {
String labelName;
String itemName;
String state;
String group;
String tags;
String types;
public String getTypes() {
return types;
}
public void setTypes(String types) {
this.types = types;
}
public String getTags() {
return tags;
}
public void setTags(String tags) {
this.tags = tags;
}
public String getLabelName() {
return labelName;
}
public void setLabelName(String labelName) {
this.labelName = labelName;
}
public String getItemName() {
return itemName;
}
public void setItemName(String itemName) {
this.itemName = itemName;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getGroup() {
return group;
}
public void setGroup(String group) {
this.group = group;
}
}
How to update specific item in inner adapter android nested recycler view.Can anyone guide me how to deal with update specific item. One more thing have observed inner adapter returns last position of array list only. Items are updating fine in last position of array list. When trying to updating the rest of position array list items, not getting updated.
Thanks in Advance.
Amar.
In outer adapter when ever data changes need to notify. Try this code
panelAdapter.notifyDataSetChanged();

Database appears, but data cannot be filtered or searched

sorry if the explanation is incomplete. I just learned about Android. and in my project this time, I made a filter feature using the radio button
I followed a totorial, but the tutorial uses static data, then I change it to dynamic using my data in the database. all works !! the data appears
but when I type something in the search bar that I make, suddenly my data disappears, I make 3 radio buttons to be selected by the user to be searched / filtered, namely type, price and facilities. the three radio buttons don't work, my data that appears are gone.
How to handle that problem?? if anyone can help me please help, thank you
this is the code
this fragment
public class FilterFragment extends Fragment implements RadioGroup.OnCheckedChangeListener, View.OnClickListener {
private static final String data_url = "http://000.000.00.000/kos/get_kos.php";
RecyclerView mRecyclerView;
ProgressDialog pd;
private Context context;
private RecyclerViewAdapter adapter;
private ArrayList<UserModel> arrayList;
private RadioGroup searchViaRadioGroup;
private EditText searchEditText;
private TextView searchViaLabel;
/* Filter Type to identify the type of Filter */
private FilterType filterType;
/* boolean variable for Filtering */
private boolean isSearchWithPrefix = false;
public FilterFragment() {
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
this.context = context;
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_filter, container, false);
pd = new ProgressDialog(getActivity());
mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
arrayList = new ArrayList<>();
mRecyclerView.setLayoutManager(new GridLayoutManager(getActivity(), LinearLayoutManager.VERTICAL));
adapter = new RecyclerViewAdapter(getActivity(), arrayList);
mRecyclerView.setAdapter(adapter);
loadjson();
return view;
}
private void loadjson(){
pd.setMessage("Mengambil Data");
pd.setCancelable(false);
pd.show();
JsonArrayRequest arrayRequest = new JsonArrayRequest(Request.Method.POST, data_url, null, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
pd.cancel();
Log.d("volley", "response : " + response.toString());
for (int i=0; i < response.length(); i++)
try {
JSONObject data = response.getJSONObject(i);
UserModel md = new UserModel();
md.setJudul(data.getString("judul")); // memanggil nama array yang kita buat
md.setAlamat(data.getString("alamat"));
md.setHarga(data.getString("harga"));
md.setTipe_kos(data.getString("tipe_kos"));
md.setFasilitas(data.getString("fasilitas"));
arrayList.add(md);
} catch (JSONException e) {
e.printStackTrace();
}
adapter.notifyDataSetChanged();
}
}, new Response.ErrorListener(){
#Override
public void onErrorResponse(VolleyError error) {
pd.cancel();
Log.d("volley", "error : " + error.getMessage());
}
});
Controller.getInstance().addToRequestQueue(arrayRequest);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
findViews(view);
implementEvents();
}
//Bind all Views
private void findViews(View view) {
filterType = FilterType.TIPE_KOS;
searchViaRadioGroup = (RadioGroup) view.findViewById(R.id.search_via_radio_group);
searchEditText = (EditText) view.findViewById(R.id.search_text);
searchViaLabel = (TextView) view.findViewById(R.id.search_via_label);
}
//Populate recycler view
private void implementEvents() {
searchViaRadioGroup.setOnCheckedChangeListener(this);
searchViaLabel.setOnClickListener(this);
searchEditText.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
//On text changed in Edit text start filtering the list
adapter.filter(filterType, charSequence.toString(), isSearchWithPrefix);
}
#Override
public void afterTextChanged(Editable editable) {
}
});
}
#Override
public void onCheckedChanged(RadioGroup radioGroup, int checkedId) {
int pos = radioGroup.indexOfChild(radioGroup.findViewById(checkedId));//get the checked position of radio button
switch (radioGroup.getId()) {
case R.id.search_via_radio_group:
switch (pos) {
case 0:
filterType = FilterType.TIPE_KOS;//Change filter type to Name if pos = 0
break;
case 1:
filterType = FilterType.NUMBER;//Change filter type to Number if pos = 1
break;
case 2:
filterType = FilterType.EMAIL;//Change filter type to Email if pos = 2
break;
}
}
}
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.search_via_label:
//show hide the radio group
if (searchViaRadioGroup.isShown()) {
searchViaLabel.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.up_dropdown, 0);
searchViaRadioGroup.setVisibility(View.GONE);
} else {
searchViaLabel.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.down_dropdown, 0);
searchViaRadioGroup.setVisibility(View.VISIBLE);
}
break;
}
}
}
this adapter
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.RecyclerViewHolder> {
static class RecyclerViewHolder extends RecyclerView.ViewHolder {
private TextView judul, alamat, tipe_kos, fasilitas, harga;
RecyclerViewHolder(View view) {
super(view);
judul = (TextView) view.findViewById(R.id.judul);
alamat = (TextView) view.findViewById(R.id.alamat);
tipe_kos = (TextView) view.findViewById(R.id.tipe_kos);
fasilitas = (TextView) view.findViewById(R.id.fasilitas);
harga = (TextView) view.findViewById(R.id.harga);
}
}
private ArrayList<UserModel> arrayList;
private ArrayList<UserModel> filterArrayList;//duplicate list for filtering
private Context context;
public RecyclerViewAdapter(Context context, ArrayList<UserModel> arrayList) {
this.arrayList = arrayList;
this.context = context;
this.filterArrayList = new ArrayList<>();//initiate filter list
this.filterArrayList.addAll(arrayList);//add all items of array list to filter list
}
#Override
public RecyclerViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.custom_list_filter, viewGroup, false);
return new RecyclerViewHolder(v);
}
#Override
public void onBindViewHolder(final RecyclerViewHolder holder, final int i) {
final UserModel model = arrayList.get(i);
holder.judul.setText(model.getJudul());//menampilkan data
holder.alamat.setText(model.getAlamat());
holder.harga.setText(model.getHarga());
holder.tipe_kos.setText(model.getTipe_kos());
holder.fasilitas.setText(model.getFasilitas());
}
#Override
public int getItemCount() {
return (null != arrayList ? arrayList.size() : 0);
}
// Filter Class to filter data
public void filter(FilterType filterType, String charText, boolean isSearchWithPrefix) {
//If Filter type is TIPE_KOS and EMAIL then only do lowercase, else in case of NUMBER no need to do lowercase because of number format
if (filterType == FilterType.TIPE_KOS || filterType == FilterType.EMAIL)
charText = charText.toLowerCase(Locale.getDefault());
arrayList.clear();//Clear the main ArrayList
//If search query is null or length is 0 then add all filterList items back to arrayList
if (charText.length() == 0) {
arrayList.addAll(filterArrayList);
} else {
//Else if search query is not null do a loop to all filterList items
for (UserModel model : filterArrayList) {
//Now check the type of search filter
switch (filterType) {
case TIPE_KOS:
if (isSearchWithPrefix) {
//if STARTS WITH radio button is selected then it will match the exact TIPE_KOS which match with search query
if (model.getTipe_kos().toLowerCase(Locale.getDefault()).startsWith(charText))
arrayList.add(model);
} else {
//if CONTAINS radio button is selected then it will match the TIPE_KOS wherever it contains search query
if (model.getTipe_kos().toLowerCase(Locale.getDefault()).contains(charText))
arrayList.add(model);
}
break;
case EMAIL:
if (isSearchWithPrefix) {
//if STARTS WITH radio button is selected then it will match the exact EMAIL which match with search query
if (model.getFasilitas().toLowerCase(Locale.getDefault()).startsWith(charText))
arrayList.add(model);
} else {
//if CONTAINS radio button is selected then it will match the EMAIL wherever it contains search query
if (model.getFasilitas().toLowerCase(Locale.getDefault()).contains(charText))
arrayList.add(model);
}
break;
case NUMBER:
if (isSearchWithPrefix) {
//if STARTS WITH radio button is selected then it will match the exact NUMBER which match with search query
if (model.getHarga().startsWith(charText))
arrayList.add(model);
} else {
//if CONTAINS radio button is selected then it will match the NUMBER wherever it contains search query
if (model.getHarga().contains(charText))
arrayList.add(model);
}
break;
}
}
}
notifyDataSetChanged();
}
}
this FilterType
public enum FilterType {
TIPE_KOS, NUMBER, EMAIL;
}
and this user model
package com.example.asus.myapplication.fragment.filter;
public class UserModel {
private String judul, alamat, harga, tipe_kos, fasilitas;
public String getJudul() {
return judul;
}
public String getAlamat() {
return alamat;
}
public String getHarga() {
return harga;
}
public String getTipe_kos() {
return tipe_kos;
}
public String getFasilitas() {
return fasilitas;
}
public void setJudul(String mJudul) {
judul = mJudul;
}
public void setAlamat(String mAlamat) {
alamat = mAlamat;
}
public void setHarga(String mHarga) {
harga = mHarga;
}
public void setTipe_kos(String mTipe_kos) {
tipe_kos = mTipe_kos;
}
public void setFasilitas(String mFasilitas) { fasilitas= mFasilitas;
}
}
another one I do not understand at all for this filter API, I just pulled all the data in my database
My database is like this, which I circle, that's the data I want to filter later

Issue with RecyclerView item selection

I am designing a live quiz app that fetches data from server and question are displayed in a RecyclerView that contains a question and four options. Now when I select one option for a given question, it is selected properly but at the same time, the corresponding option for other question is selected automatically.
Screenshot of the item selection issue is the following.
I have designed Data Model Class and RecylerView Adapter (with the help of #Reaz Murshed) but have been stuck with the code
My Data Model Class is :
//DmLiveQuiz
public class DmLiveQuiz {
String testId;
int questionId;
String question;
String optA;
String optB;
String optC;
String optD;
String answer;
String explain;
...
}
My Adapter Class is //LiveTestAdapter
public class LiveTestAdapter extends RecyclerView.Adapter<LiveTestAdapter.CustomViewHolder> {
private List<DmLiveQuiz> questionList;
private int[] answerList; // Get a list of your answers here.
private DmLiveQuiz questionsList;
private Context context;
public List<Integer> myResponse = new ArrayList<Integer>();
public int qno;
public LiveTestAdapter(List<DmLiveQuiz> questionList, Context context) {
this.questionList = questionList;
this.context = context;
}
#NonNull
#Override
public CustomViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.live_quiz_display_format, parent, false);
return new CustomViewHolder(itemView);
}
#Override
public void onBindViewHolder(#NonNull final CustomViewHolder holder, int position) {
questionsList = questionList.get(holder.getAdapterPosition());
holder.tvQNo.setText(questionsList.getQuestionId() + "");
holder.tvquestion.getLayoutParams().width = LinearLayout.LayoutParams.WRAP_CONTENT;
holder.tvquestion.setText(questionsList.getQuestion());
holder.optA.setText(questionsList.getOptA());
holder.optB.setText(questionsList.getOptB());
holder.optC.setText(questionsList.getOptC());
holder.optD.setText(questionsList.getOptD());
// Now you need to modify the backgrounds of your option buttons like the following.
if (answerList[position] == 1) holder.optA.setBackgroundResource(R.drawable.button_border);
else holder.optA.setBackgroundResource(R.drawable.button_question_style);
if (answerList[position] == 2) holder.optB.setBackgroundResource(R.drawable.button_border);
else holder.optB.setBackgroundResource(R.drawable.button_question_style);
if (answerList[position] == 3) holder.optC.setBackgroundResource(R.drawable.button_border);
else holder.optC.setBackgroundResource(R.drawable.button_question_style);
if (answerList[position] == 4) holder.optD.setBackgroundResource(R.drawable.button_border);
else holder.optD.setBackgroundResource(R.drawable.button_question_style);
holder.optA.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
holder.optA.setBackgroundResource(R.drawable.button_border);
answerList[position] = 1; // Selected first option which is A
});
holder.optB.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
holder.optB.setBackgroundResource(R.drawable.button_border);
answerList[position] = 2; // Selected second option which is B
Toast.makeText(context, "Position :" + holder.getAdapterPosition(), Toast.LENGTH_SHORT).show();
}
});
holder.optC.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
holder.optC.setBackgroundResource(R.drawable.button_border);
answerList[position] = 3; // Selected third option which is C
Toast.makeText(context, "Position :" + holder.getAdapterPosition(), Toast.LENGTH_SHORT).show();
}
});
holder.optD.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
holder.optD.setBackgroundResource(R.drawable.button_border);
answerList[position] = 4; // Selected fourth option which is D
Toast.makeText(context, "Position :" + holder.getAdapterPosition(), Toast.LENGTH_SHORT).show();
}
});
holder.tvClear.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
holder.optA.setBackgroundResource(R.drawable.button_question_style);
holder.optB.setBackgroundResource(R.drawable.button_question_style);
holder.optC.setBackgroundResource(R.drawable.button_question_style);
holder.optD.setBackgroundResource(R.drawable.button_question_style);
answerList[position] = 0; // Clear the value in the answerList
}
});
}
// Use this function to set the question list in the adapter
public void setQuestionList(List<DmLiveQuiz> questionList) {
this.questionList = questionList;
this.answerList = new int[questionList.size()]; // This initializes the answer list having the same size as the question list
notifyDataSetChanged();
}
#Override
public int getItemCount() {
return questionList.size();
}
public class CustomViewHolder extends RecyclerView.ViewHolder {
TextView tvquestion, tvClear, tvQNo;
Button optA, optB, optC, optD;
public CustomViewHolder(View itemView) {
super(itemView);
tvQNo = (TextView) itemView.findViewById(R.id.tvLiveQuizQuestionNo);
tvquestion = (TextView) itemView.findViewById(R.id.tvLiveQuizQuestion);
optA = (Button) itemView.findViewById(R.id.buttonOptionA);
...///
}
}
}
And The Activity where Recyclerview is implemented is
recyclerView = (RecyclerView) findViewById(R.id.recyclerViewLiveTest);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
quizList = new ArrayList<>();
adapter = new LiveTestAdapter(quizList, getApplicationContext());
linearLayoutManager = new LinearLayoutManager(this);
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(), linearLayoutManager.getOrientation());
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(linearLayoutManager);
// recyclerView.addItemDecoration(dividerItemDecoration);
recyclerView.setAdapter(adapter);
getData();
......
The method for fetching JSON data is getdata() as given below which fetches data from server correctly...
private void getData() {
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(quiz_url, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
for (int i = 0; i < response.length(); i++) {
try {
JSONObject jsonObject = response.getJSONObject(i);
DmLiveQuiz liveQuiz = new DmLiveQuiz();
...
...
quizList.add(liveQuiz);
} catch (JSONException e) {
e.printStackTrace();
progressDialog.dismiss();
}
}
adapter.notifyDataSetChanged();
..........
}
Now When I run App, it shows index=0 i.e. ArrayOutOfIndexException is generated.. I am not able to call public void setQuestionList(List<DmLiveQuiz> questionList) method of LiveQuizAdapter class from my activity.. Please Help
Initially you are setting empty list in the adapter. After getting value from JsonArrayRequest then need to update adapter using new list.
Update onBindViewHolder:
#Override
public void onBindViewHolder(#NonNull final CustomViewHolder holder, int position) {
DmLiveQuiz dmLiveQuiz= questionList.get(position);
if(dmLiveQuiz!=null){
// do whatever you want. put all code here.}
}
Update your adapter:
#Override
public void onResponse(JSONArray response) {
for (int i = 0; i < response.length(); i++) {
// put all code here
quizList.add(liveQuiz);}
adapter.setQuestionList(quizList);
adapter.notifyDataSetChanged();
}
you have to add a boolean value in DmLiveQuiz model class :-
boolean isSelected ;
and then set a check in your adapter while your are showing the answer is selected or not :-
if(DmLiveQuiz.isSelectd){
// this is the selected answer
}else {
// in case don't selected
}
and change the boolean value on adapter item Click

Transferring data into a separate ArrayList and displaying in RecyclerView

I have two ArrayLists from which I am trying to insert data into separate static ArrayList in another class and display in RecyclerView, but the recycler is not getting populated though the same was being done with a dummy ArrayList.Please help me with this problem.
My Class where I am inserting data from phoneContactNos and phoneContactName in two separate ArrayList: Common.selectedContactNos and Common.selectedContactName.
public void displayMatchedContacts()
{
try {
for (int i = 1; i < phoneContactNos.size(); i++) {
if (phoneContactNos.contains(registeredContactNos.get(i))) {
if (registeredContactNos.get(i) != null) {
try {
indexOfRegNumber = phoneContactNos.indexOf(registeredContactNos.get(i));
//Common.indexPosition_contacts=indexOfRegNumber;
Toast.makeText(this, "index" + String.valueOf(indexOfRegNumber), Toast.LENGTH_LONG).show();
if ((phoneContactNos.get(indexOfRegNumber) != null) &&(phoneContactName.get(indexOfRegNumber) != null)) {
//String regName="";
//String regContact="";
Common.selectedContactNos.add(phoneContactNos.get(indexOfRegNumber));
//Toast.makeText(this,selectedContactNos.get(i).toString(),Toast.LENGTH_SHORT).show();
//Toast.makeText(this,phoneContactNos.get(indexOfRegNumber).toString(),Toast.LENGTH_SHORT).show();
Common.selectedContactName.add(phoneContactName.get(indexOfRegNumber));
//Toast.makeText(this,selectedContactName.get(i).toString(),Toast.LENGTH_SHORT).show();
//Toast.makeText(this, phoneContactName.get(indexOfRegNumber).toString(), Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "null index no", Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
Log.i("Contacts display error", e.getLocalizedMessage());
e.printStackTrace();
}
}
}
}
}catch (Exception e)
{
Log.i("Contacts error in loop", e.getLocalizedMessage());
e.printStackTrace();
}
}
My Common class
public final class Common {
public static ArrayList<String> selectedContactNos=new ArrayList<>();
public static ArrayList<String> selectedContactName=new ArrayList<>();
public static String fcmId="";
public static int position;
public static String contacts_list="";
public static int indexPosition_contacts;
}
My RecyclerView populating code
public void populateList() {
Log.i("Populate List","Entered");
LinearLayoutManager mLinearLayoutManager = new LinearLayoutManager(this);
recyclerView_contacts.setLayoutManager(mLinearLayoutManager);
displayRecyclerAdapter = new DisplayRecyclerAdapter(this);
recyclerView_contacts.setAdapter(displayRecyclerAdapter);
}
My Adapter Class
public class DisplayRecyclerAdapter extends RecyclerView.Adapter<DisplayRecyclerAdapter.displayViewHolder> {
private LayoutInflater mInflater;
private Context context;
Fragment fragment;
FragmentTransaction ft;
FrameLayout container;
public DisplayContacts displayContacts;
public DisplayRecyclerAdapter(Context context) {
this.mInflater = LayoutInflater.from(context);
this.context = context;
ft = ((AppCompatActivity) context).getSupportFragmentManager().beginTransaction();
//displayContacts = new DisplayContacts();
}
#Override
public displayViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflater.inflate(R.layout.contacts_row, parent, false);
displayViewHolder holder = new displayViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(displayViewHolder holder, int position) {
holder.setData(position);
//Common.position = position;
holder.setListeners();
//for(int i=0;i<((DisplayContacts)context).selectedContactName.size();i++)
for(int i=0;i<Common.selectedContactName.size();i++)
{
//String contactName=((DisplayContacts)context).selectedContactName.get(i);
String contactName=Common.selectedContactName.get(i);
//String contactNumber=((DisplayContacts)context).selectedContactNos.get(i);
String contactNumber=Common.selectedContactNos.get(i);
Toast.makeText(context,contactName+","+contactNumber,Toast.LENGTH_SHORT).show();
}
}
class displayViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
int position;
//ImageView productSearchImg;
TextView name_contactList;
Button call_contact;
public displayViewHolder(View itemView) {
super(itemView);
name_contactList = (TextView) itemView.findViewById(R.id.contactlist_name);
call_contact = (Button) itemView.findViewById(R.id.contactlist_call);
}
public void setData(int position) {
this.position = position;
//String displayContacts=((DisplayContacts) context).selectedContactName.get(position);
String displayContacts=Common.selectedContactName.get(position);
Toast.makeText(context,"name to display"+ displayContacts,Toast.LENGTH_SHORT).show();
//name_contactList.setText(((DisplayContacts) context).selectedContactName.get(position));
//name_contactList.setText(displayContacts);
name_contactList.setText("dummy text");
}
#Override
public void onClick(View v) {
//sendPushNotification();
startAudioCall();
}
public void setListeners() {
call_contact.setOnClickListener(displayViewHolder.this);
}
}
public void startAudioCall() {
Intent i = new Intent(context, AudioCallActivity.class).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
#Override
public int getItemCount() {
return ((DisplayContacts) context).selectedContactName.size();
}
}
can be one of two things:
1.you are not attaching the adapter with data,hence empty
2.or you are updating your data but not calling notifyDataSetChanged()
try to pass the list data in your Adapter class while you are creating it,then attach it to the recyelerview.
//to give a vary basic example
List dataList;
RvAdapter(Context c,List data){
this.dataList=data;
}
onBidViewHolder(Viewholder holder,int position){
holder.tvName.setText(dataList.get(position).getName());
.......
}
//in your activity/fragment
RvAdapter adapter=new RavAdapter(context,dataList);
recylerview.setAdapter(adapter);
//if you change your data
adapter.notifyDataSetChanged()

How to show date in between conversation in recyclerview or in listview

How to show date or today , yesterday like text in between conversation
like whatsapp
MainActivity
public class MainActivity extends AppCompatActivity {
private ChatAdapter chatAdapter;
private RecyclerView recyclerView;
private Context context;
private int loggedInUserID;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
bindRecyclerView();
// TODO get logged in user id and initialize into 'loggedInUserID'
}
#Override
protected void onResume() {
super.onResume();
getData();
}
private void getData() {
/**
*Your server call to get data and parse json to your appropriate model
* after parsing json to model simply call the
*/
List<ChatModel> chatModelList = ParseData.chatParser(jsonArray);
groupDataIntoHashMap(chatModelList);
}
private void bindRecyclerView() {
chatAdapter = new ChatAdapter(null);
chatAdapter.setUser(loggedInUserID);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(context);
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(chatAdapter);
}
private void groupDataIntoHashMap(List<ChatModel> chatModelList) {
LinkedHashMap<String, Set<ChatModel>> groupedHashMap = new LinkedHashMap<>();
Set<ChatModel> list = null;
for (ChatModel chatModel : chatModelList) {
//Log.d(TAG, travelActivityDTO.toString());
String hashMapKey = DateParser.convertDateToString(chatModel.getChatTime());
//Log.d(TAG, "start date: " + DateParser.convertDateToString(travelActivityDTO.getStartDate()));
if (groupedHashMap.containsKey(hashMapKey)) {
// The key is already in the HashMap; add the pojo object
// against the existing key.
groupedHashMap.get(hashMapKey).add(chatModel);
} else {
// The key is not there in the HashMap; create a new key-value pair
list = new LinkedHashSet<>();
list.add(chatModel);
groupedHashMap.put(hashMapKey, list);
}
}
//Generate list from map
generateListFromMap(groupedHashMap);
}
private List<ListObject> generateListFromMap(LinkedHashMap<String, Set<ChatModel>> groupedHashMap) {
// We linearly add every item into the consolidatedList.
List<ListObject> consolidatedList = new ArrayList<>();
for (String date : groupedHashMap.keySet()) {
DateObject dateItem = new DateObject();
dateItem.setDate(date);
consolidatedList.add(dateItem);
for (ChatModel chatModel : groupedHashMap.get(date)) {
ChatModelObject generalItem = new ChatModelObject();
generalItem.setChatModel(chatModel);
consolidatedList.add(generalItem);
}
}
chatAdapter.setDataChange(consolidatedList);
return consolidatedList;
}
}
ChatModel.java
public class ChatModel implements Serializable {
private String messageId;
private int userId;
private String firstName;
private String userName;
private String message;
private Date chatTime;
//TODO generate getter and setter
}
ListObject.java (to determind the type of message)
public abstract class ListObject {
public static final int TYPE_DATE = 0;
public static final int TYPE_GENERAL_RIGHT = 1;
public static final int TYPE_GENERAL_LEFT = 2;
abstract public int getType(int userId);
}
DateObject.java
public class DateObject extends ListObject {
private String date;
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
#Override
public int getType(int userId) {
return TYPE_DATE;
}
}
ChatModelObject.java
public class ChatModelObject extends ListObject {
private ChatModel chatModel;
public ChatModel getChatModel() {
return chatModel;
}
public void setChatModel(ChatModel chatModel) {
this.chatModel = chatModel;
}
#Override
public int getType(int userId) {
if (this.chatModel.getUserId() == userId) {
return TYPE_GENERAL_RIGHT;
} else
return TYPE_GENERAL_LEFT;
}
}
DateParse.java to parse date for grouping the chat
public class DateParser {
private static DateFormat dateFormat1 = new SimpleDateFormat("dd/MM/yyyy");
public static String convertDateToString(Date date) {
String strDate = "";
strDate = dateFormat1.format(date);
return strDate;
}
}
ChatAdapter.java
public class ChatAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<ListObject> listObjects;
private int loggedInUserId;
public ChatAdapter(List<ListObject> listObjects) {
this.listObjects = listObjects;
}
public void setUser(int userId) {
this.loggedInUserId = userId;
}
public void setDataChange(List<ListObject> asList) {
this.listObjects = asList;
//now, tell the adapter about the update
notifyDataSetChanged();
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
RecyclerView.ViewHolder viewHolder = null;
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
switch (viewType) {
case ListObject.TYPE_GENERAL_RIGHT:
View currentUserView = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_chat_list_row_right, parent, false);
viewHolder = new ChatRightViewHolder(currentUserView); // view holder for normal items
break;
case ListObject.TYPE_GENERAL_LEFT:
View otherUserView = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_chat_list_row_left, parent, false);
viewHolder = new ChatLeftViewHolder(otherUserView); // view holder for normal items
break;
case ListObject.TYPE_DATE:
View v2 = inflater.inflate(R.layout.date_row, parent, false);
viewHolder = new DateViewHolder(v2);
break;
}
return viewHolder;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
switch (viewHolder.getItemViewType()) {
case ListObject.TYPE_GENERAL_RIGHT:
ChatModelObject generalItem = (ChatModelObject) listObjects.get(position);
ChatRightViewHolder chatViewHolder = (ChatRightViewHolder) viewHolder;
chatViewHolder.bind(generalItem.getChatModel());
break;
case ListObject.TYPE_GENERAL_LEFT:
ChatModelObject generalItemLeft = (ChatModelObject) listObjects.get(position);
ChatLeftViewHolder chatLeftViewHolder = (ChatLeftViewHolder) viewHolder;
chatLeftViewHolder.bind(generalItemLeft.getChatModel());
break;
case ListObject.TYPE_DATE:
DateObject dateItem = (DateObject) listObjects.get(position);
DateViewHolder dateViewHolder = (DateViewHolder) viewHolder;
dateViewHolder.bind(dateItem.getDate());
break;
}
}
#Override
public int getItemCount() {
if (listObjects != null) {
return listObjects.size();
}
return 0;
}
#Override
public int getItemViewType(int position) {
return listObjects.get(position).getType(loggedInUserId);
}
public ListObject getItem(int position) {
return listObjects.get(position);
}
}
ChatRightViewHolder.java for current user message
public class ChatRightViewHolder extends RecyclerView.ViewHolder {
private final String TAG = ChatRightViewHolder.class.getSimpleName();
public ChatRightViewHolder(View itemView) {
super(itemView);
//TODO initialize your xml views
}
public void bind(final ChatModel chatModel) {
//TODO set data to xml view via textivew.setText();
}
}
ChatLeftViewHolder.java for display other user messages.
public class ChatLeftViewHolder extends RecyclerView.ViewHolder {
private final String TAG = ChatRightViewHolder.class.getSimpleName();
public ChatLeftViewHolder(View itemView) {
super(itemView);
//TODO initialize your xml views
}
public void bind(final ChatModel chatModel) {
//TODO set data to xml view via textivew.setText();
}
}
DateViewHolder.java to display date
public class DateViewHolder extends RecyclerView.ViewHolder {
public DateViewHolder(View itemView) {
super(itemView);
//TODO initialize your xml views
}
public void bind(final String date) {
//TODO set data to xml view via textivew.setText();
}
}
You need to create a new ViewHolder for that purpose
For example:
// Different types of rows
private static final int TYPE_ITEM_LEFT = 0;
private static final int TYPE_ITEM_RIGHT = 1;
private static final int TYPE_ITEM_DATE_CONTAINER = 2;
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
class ViewHolder0 extends RecyclerView.ViewHolder {
// Viewholder for row type 0
}
class ViewHolder1 extends RecyclerView.ViewHolder {
// Viewholder for row type 1
}
class ViewHolder2 extends RecyclerView.ViewHolder {
// Viewholder for row type 2
}
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder viewHolder, int position) {
if (viewHolder.getItemViewType() == TYPE_ITEM_LEFT) {
// Code to populate type 0 view here
} else if (viewHolder.getItemViewType() == TYPE_ITEM_RIGHT) {
// Code to populate type 1 view here
} else if (viewHolder.getItemViewType() == TYPE_ITEM_DATE_CONTAINER) {
// Code to populate type 2 view here
}
}
You just have to compare the date when scrolling and set the visibility of date view. The advantage of this is there's no hard-coded today/yesterday in data list and is able to refresh the correct date immediately (scrolling) after 12.00 a.m.
e.g. in your onBindViewHolder() in recycleview:
if (position != 0) {
processDate(holder.topDateTextView, myData.getDate()
, this.myDataList.get(position - 1).getDate()
, false)
;
} else {
processDate(holder.topDateTextView, data.getDay()
, null
, true)
;
}
Method to process that date view (Assume your list has format "dd/MM/yyyy"):
private void processDate(#NonNull TextView tv, String dateAPIStr
, String dateAPICompareStr
, boolean isFirstItem) {
SimpleDateFormat f = new SimpleDateFormat("dd/MM/yyyy");
if (isFirstItem) {
//first item always got date/today to shows
//and overkill to compare with next item flow
Date dateFromAPI = null;
try {
dateFromAPI = f.parse(dateAPIStr);
if (DateUtils.isToday(dateFromAPI.getTime())) tv.setText("today");
else if (DateUtils.isToday(dateFromAPI.getTime() + DateUtils.DAY_IN_MILLIS)) tv.setText("yesterday");
else tv.setText(dateAPIStr);
tv.setIncludeFontPadding(false);
tv.setVisibility(View.VISIBLE);
} catch (ParseException e) {
e.printStackTrace();
tv.setVisibility(View.GONE);
}
} else {
if (!dateAPIStr.equalsIgnoreCase(dateAPICompareStr)) {
try {
Date dateFromAPI = f.parse(dateAPIStr);
if (DateUtils.isToday(dateFromAPI.getTime())) tv.setText("today");
else if (DateUtils.isToday(dateFromAPI.getTime() + DateUtils.DAY_IN_MILLIS)) tv.setText("yesterday");
else tv.setText(dateAPIStr);
tv.setIncludeFontPadding(false);
tv.setVisibility(View.VISIBLE);
} catch (ParseException e) {
e.printStackTrace();
tv.setVisibility(View.GONE);
}
} else {
tv.setVisibility(View.GONE);
}
}
}
Note: You also need to do yourAdapter.notifyDataSetChanged(); if append new item to redraw to dismiss previous "today"/date after 12.00 a.m on the same page, not just rely on yourAdapter.notifyItemInserted(new_item_position) which doesn't redraw previous items.

Categories

Resources