I'm using room db and I've a table from where I get a list of LiveData. In that table there is a column of Date where I store current date. Current date is selected by default, but user can also change the date when inserting data in the database.
I want to show this data in a recyclerview in this manner
https://i.sstatic.net/KBASl.jpg
I want to section this data according to the month and year as header and all entries of that month year below it.
For example, user inserted data in October 2019, I want this "October 2019" as a header in recyclerview and all entries of this month below it. Just like this all months entries should be shown with same manner as every next month becomes header and the entries of that month below it.
I've tried to achieve this by doing
if (!thisDate.equals(dBDate))
{
holder.transMonthWrapper.setVisibility(View.VISIBLE);
if (IEList.getType().equalsIgnoreCase("income"))
{
String amount = ""+IEList.getAmount();
holder.tvTransAmount.setText(amount);
holder.tvTransAmount.setTextColor(Color.GREEN);
holder.tvTransCategory.setText(IEList.getCategory());
holder.tvTransCategory.setTextColor(Color.GREEN);
}
else
{
String amount = ""+IEList.getAmount();
holder.tvTransAmount.setText(amount);
holder.tvTransAmount.setTextColor(Color.RED);
holder.tvTransCategory.setText(IEList.getCategory());
holder.tvTransCategory.setTextColor(Color.RED);
}
thisDate = dBDate;
holder.tvTransMonth.setText(thisDate);
}
else
{
holder.transMonthWrapper.setVisibility(View.GONE);
if (IEList.getType().equalsIgnoreCase("income"))
{
String amount = ""+IEList.getAmount();
holder.tvTransAmount.setText(amount);
holder.tvTransAmount.setTextColor(Color.GREEN);
holder.tvTransCategory.setText(IEList.getCategory());
holder.tvTransCategory.setTextColor(Color.GREEN);
}
else
{
String amount = ""+IEList.getAmount();
holder.tvTransAmount.setText(amount);
holder.tvTransAmount.setTextColor(Color.RED);
holder.tvTransCategory.setText(IEList.getCategory());
holder.tvTransCategory.setTextColor(Color.RED);
}
}
But the problem in this code is that when user change the month from settings and put some entries into database and that year's month entries are already present in the recyclerview. It creates another header of that existing month in recyclerview. But I want this to put those entries in existing month header, not to create new header of that month.
What will be the best approach to achieve this without using external libraries, because I don't want to be dependent on external libraries in this case.
I'm fairly new in programming.
Updated
In activity
public void getTransactionData()
{
adapter = new TransactionAdapter();
recyclerView.setAdapter(adapter);
incomeExpenseModel = ViewModelProviders.of(AllTransaction.this).get(IncomeExpenseViewModel.class);
incomeExpenseModel.getIncomeExpenseData().observe(this, new Observer<List<IncomeExpense>>() {
@Override
public void onChanged(List<IncomeExpense> incomeExpenses) {
adapter.setIncomeExpenseList(incomeExpenses);
}
});
In recyclerAdapter
public void onBindViewHolder(@NonNull TransactionViewHolder holder, int position) {
IncomeExpense IEList = incomeExpenseList.get(position);
preferences = context.getSharedPreferences(settingPref, Context.MODE_PRIVATE);
String dateFormat = preferences.getString("Date_Format", "MM.dd.yy");
int lastIndex = incomeExpenseList.size() - 1;
IncomeExpense IELastIndex = incomeExpenseList.get(lastIndex);
String dateFrmDb= IELastIndex.getDate();
DateFormat df=new SimpleDateFormat(dateFormat);
Date d;
try {
d = df.parse(dateFrmDb);
df=new SimpleDateFormat("MMMM yyyy");
if (d != null) {
dBDate = df.format(d);
}
} catch (ParseException e) {
Toast.makeText(context, "Error" +e, Toast.LENGTH_SHORT).show();
}
if (!thisDate.equals(dBDate))
{
holder.transMonthWrapper.setVisibility(View.VISIBLE);
if (IEList.getType().equalsIgnoreCase("income"))
{
String amount = ""+IEList.getAmount();
holder.tvTransAmount.setText(amount);
holder.tvTransAmount.setTextColor(Color.GREEN);
holder.tvTransCategory.setText(IEList.getCategory());
holder.tvTransCategory.setTextColor(Color.GREEN);
}
else
{
String amount = ""+IEList.getAmount();
holder.tvTransAmount.setText(amount);
holder.tvTransAmount.setTextColor(Color.RED);
holder.tvTransCategory.setText(IEList.getCategory());
holder.tvTransCategory.setTextColor(Color.RED);
}
thisDate = dBDate;
holder.tvTransMonth.setText(thisDate);
}
else
{
holder.transMonthWrapper.setVisibility(View.GONE);
if (IEList.getType().equalsIgnoreCase("income"))
{
String amount = ""+IEList.getAmount();
holder.tvTransAmount.setText(amount);
holder.tvTransAmount.setTextColor(Color.GREEN);
holder.tvTransCategory.setText(IEList.getCategory());
holder.tvTransCategory.setTextColor(Color.GREEN);
}
else
{
String amount = ""+IEList.getAmount();
holder.tvTransAmount.setText(amount);
holder.tvTransAmount.setTextColor(Color.RED);
holder.tvTransCategory.setText(IEList.getCategory());
holder.tvTransCategory.setTextColor(Color.RED);
}
}
}
@Override
public int getItemCount() {
return incomeExpenseList.size();
}
public void setIncomeExpenseList(List<IncomeExpense> incomeExpenseList)
{
this.incomeExpenseList = incomeExpenseList;
notifyDataSetChanged();
}
You don't need to use any third party libraries. You can make use of ExpandableListView
without actually making it "expand and collapse" to do the exact same thing which you need. See my answer for this post. The advantage here is that you can deal with this as easily as you deal with an ExpandableListView
, with no custom code. You only need to add one line to what is otherwise a standard ExpandableListView
adapter.
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
...
((ExpandableListView) parent).expandGroup(groupPosition);
...
}
Your section headers, you can set as a group view and the list items as children. Your data structure need to be updated before being passed on to the adapter. It need to be a grouped data, not a plain list which you have to pass to the expandable adapter(for example an array of classes, each instance that contain a String
property for group header and an ArrayList
of IncomeExpense
objects). And when you update the data, make the update in the corresponding group, instead of the entire data.