My goal is to create an application that display a list of data that are grouped by the days. Please refer to the below for actual screenshot.
In order to achieve this design, I have used custom arraylist adapter to make this design happen. Below is my class file for DiaryListAdapter
public class DiaryListAdapter extends ArrayAdapter<Records> {
/**
* Adapter context
*/
Context mContext;
/**
* Adapter View layout
*/
int mLayoutResourceId;
int selectedItem = -1;
private Records _records;
public DiaryListAdapter(Context context, int layoutResourceId, ArrayList<Records> recordItems) {
super(context, layoutResourceId, recordItems);
this.mContext = context;
this.mLayoutResourceId = layoutResourceId;
}
private static class ViewHolder {
TextView diaryTime, diarySysDia, diaryPul, itemDate, itemToday;
LinearLayout llDiaryHead;
}
/**
* Returns the view for a specific item on the list
*/
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// Declare the new object
ViewHolder viewHolder;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.lv_diarycontent_adapter, null);
// Instantiate the object
viewHolder = new ViewHolder();
viewHolder.itemDate = (TextView) convertView.findViewById(R.id.itemDate);
viewHolder.itemToday = (TextView) convertView.findViewById(R.id.itemToday);
viewHolder.diaryTime = (TextView) convertView.findViewById(R.id.itemTime);
viewHolder.diarySysDia = (TextView) convertView.findViewById(R.id.itemSysDia);
viewHolder.diaryPul = (TextView) convertView.findViewById(R.id.itemPulse);
viewHolder.llDiaryHead = (LinearLayout) convertView.findViewById(R.id.ll_diaryhead);
convertView.setTag(R.id.TAG_DIARY_VIEWHOLDER_ID, viewHolder);
} else {
// Instantiate the new object
viewHolder = (ViewHolder) convertView.getTag(R.id.TAG_DIARY_VIEWHOLDER_ID);
}
// Declare the reminder object
_records = getItem(position);
if (_records.getIsDateHead()) {
// Hide the layout header
viewHolder.llDiaryHead.setVisibility(View.VISIBLE);
// Display the value on textview
viewHolder.itemDate.setText(FormatterMgr.DSPLY_DATE_LSTVIEW.format(_records.getRecordCreatedOn()));
// Display the value inside the content
viewHolder.diaryTime.setText(_records.getRecordCreatedOn().toString());
viewHolder.diarySysDia.setText(_records.getSys() + "/" + _records.getDia());
viewHolder.diaryPul.setText(Float.toString(_records.getHr()));
} else {
// Hide the layout header
viewHolder.llDiaryHead.setVisibility(View.GONE);
// Display the value inside the content
viewHolder.diaryTime.setText(_records.getRecordCreatedOn().toString());
viewHolder.diarySysDia.setText(_records.getSys() + "/" + _records.getDia());
viewHolder.diaryPul.setText(Float.toString(_records.getHr()));
}
convertView.setTag(R.id.TAG_DIARY_LIST_ID, _records);
return convertView;
}
public void setSelectedItem(int selectedItem) {
this.selectedItem = selectedItem;
}
Next class would be, DiaryFragment. This is the UI code behind file for me to program the listview to be displayed inside the page. This is the code where I have difficulty attempting to display the listview and grouped by the days accordingly.
public class DiaryFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_DIARY = "diary";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
RecordsTableHelper rth;
HashSet<String> uniqueSet;
ArrayList<Records> mRecordsArrayList;
ListView mDiaryListView;
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment DiaryFragment.
*/
// TODO: Rename and change types and number of parameters
public static DiaryFragment newInstance(String param1, String param2) {
DiaryFragment fragment = new DiaryFragment();
Bundle args = new Bundle();
args.putString(ARG_DIARY, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
public DiaryFragment() {
// Required empty public constructor
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_DIARY);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_diary, container, false);
// Declare the database to retrieve all the data from the table
DatabaseHelper _dbHelper = DBMgr.openConnection(getContext());
rth = new RecordsTableHelper(_dbHelper.getDatabase());
// Get all the records value and store inside an array list
mRecordsArrayList = new ArrayList<Records>(rth.getAllRecords());
Collections.sort(mRecordsArrayList, new RecordsComparator()); // Sort all the arraylist according to its date time
//mRecordsArrayListSize = mRecordsArrayList.size();
mDiaryListView = (ListView)view.findViewById(R.id.listViewDiary);
mDiaryListView.setOnItemClickListener(new OnPlandetailsitemClickListener());
setHasOptionsMenu(true);
return view;
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_diary, menu);
super.onCreateOptionsMenu(menu,inflater);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_adddiary) {
Intent intent = new Intent(getActivity(), NewDiaryActivity.class);
startActivityForResult(intent, ActivityResults.newdiaryactivityresult);
// Create Animation
getActivity().overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left);
}
return super.onOptionsItemSelected(item);
}
@Override
public void onResume() {
super.onResume();
// Get the total day sum from the database
int totalUniqueDays = getTotalUniqueDays();
/* Declare the database to retrieve all the data from the table
DatabaseHelper _dbHelper = DBMgr.openConnection(getContext());
rth = new RecordsTableHelper(_dbHelper.getDatabase());
*/
// 1) Create a for loop
for (int i = 0; i<mRecordsArrayList.size(); i++) {
Log.d("NON REPEATED DAYS", FormatterMgr.DB_DATE.format(mRecordsArrayList.get(i).getRecordCreatedOn()));
// Set the first column header
if (i==0) {
// Add it into the arraylist
mRecordsArrayList.get(i).setDateHead(true);
}
// 2) Inside the for loop, set the comparison of unique value occurs in the record array list method by checking the getUniqueDaysPos method
// 3) If the unique value occurred, set the date head inside the arraylist
// 4) Store the arraylist into the adapter
/*
// Get the total number of repeated days
int totalRepeatedDays = getTotalRepeatedDays(mRecordsArrayList.get(i).getRecordCreatedOn());
for (int j = 0; j<totalRepeatedDays; j++) {
if (j==0) {
// Add it into the arraylist
mRecordsArrayList.get(j).setDateHead(true);
}
}
*/
}
DiaryListAdapter adapter = new DiaryListAdapter(getActivity(),
R.layout.lv_diarycontent_adapter, mRecordsArrayList);
mDiaryListView.setAdapter(adapter);
}
//response the click on listview
//the click listener for pastplan listview
private class OnPlandetailsitemClickListener implements ListView.OnItemClickListener {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
DiaryListAdapter adapter = (DiaryListAdapter) mDiaryListView.getAdapter();
adapter.setSelectedItem(position);
mDiaryListView.setAdapter(adapter);
// Get the ID
Records _records = (Records)view.getTag(R.id.TAG_DIARY_LIST_ID);
//Direct to the reminder info activity
Intent intent = new Intent(getActivity(), NewDiaryActivity.class);
intent.putExtra(IntentResults.newDiary_id_val, _records.getRecord_id());
startActivityForResult(intent, ActivityResults.inforeminderactivityresult);
// Create Animation
getActivity().overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left);
}
}
// Get the overall number of non repeated days inside record database
public int getTotalUniqueDays() {
// Declare the current date and next date as 0
String currentDate, nextDate = null;
// Declare the result as 0. The result will be produce the outcome of the final result
int result = 0;
ArrayList<String> tempRecordsArrayList = new ArrayList<String>();
// Declare the database to retrieve all the data from the table
for (int i = 0; i<mRecordsArrayList.size(); i++) {
// Convert the date time to date
currentDate = FormatterMgr.DB_DATE.format(mRecordsArrayList.get(i).getRecordCreatedOn());
tempRecordsArrayList.add(currentDate);
}
uniqueSet = new HashSet<String>();
uniqueSet.addAll(tempRecordsArrayList);
return uniqueSet.size();
}
public ArrayList<Integer> getUniqueDaysPos() {
// 1) Get the unique set and store into arraylist
ArrayList<String> tempUniqueSet = new ArrayList<String>(uniqueSet);
// 2) Get the full set of record array list
ArrayList<Records> tempRecordsSet = mRecordsArrayList;
// 3) Create the object of null arraylist integer
ArrayList<Integer> uniqueDaysPos = new ArrayList<Integer>();
// 4) Loop through the fullset arraylist and produce the result of the position of unique dates inside the full set of array list
for (int i = 0; i<tempRecordsSet.size(); i++) {
// 5) Store the unique dates position inside the set of integer arraylist
uniqueDaysPos.add(tempRecordsSet.indexOf(tempUniqueSet));
}
return uniqueDaysPos;
}
public int getTotalRepeatedDays(Date dateValue) {
// Declare the database to retrieve all the data from the table
DatabaseHelper _dbHelper = DBMgr.openConnection(getContext());
rth = new RecordsTableHelper(_dbHelper.getDatabase());
// Get all the records value and store inside an array list
ArrayList<Records> mRecordsDateRepeatedList = rth.getAllRecordsByDate(dateValue);
return mRecordsDateRepeatedList.size();
}
}
Below is the lv_diarycontent_adapter XML file for the list adapter. In this case, the code behind of DiaryListAdapter will toggle the header based on the condition of each record.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!-- START OF HEAD LAYOUT -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="15dp"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:orientation="horizontal"
android:id="@+id/ll_diaryhead"
android:background="@color/colorPrimary">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.3">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Mon 1, 1976"
android:id="@+id/itemDate"
android:layout_alignParentLeft="true"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
android:textStyle="bold"
android:textColor="@color/font_color_white"
android:layout_marginBottom="5dp" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.7">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:id="@+id/itemToday"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
android:textStyle="bold"
android:textColor="@color/font_color_white" />
</LinearLayout>
</LinearLayout>
<!-- END OF HEAD LAYOUT -->
<!-- START OF BODY LAYOUT -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.25"
android:gravity="center_horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="10:30"
android:id="@+id/itemTime"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
android:layout_marginBottom="5dp" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.5"
android:gravity="center_horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="120/75"
android:id="@+id/itemSysDia"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
></TextView>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.25"
android:gravity="center_horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="80"
android:id="@+id/itemPulse"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
></TextView>
</LinearLayout>
</LinearLayout>
<!-- END OF BODY LAYOUT -->
I am now stuck to create the listview and grouped the records into date. My attempts so far, is to sort the records by date in ascending order, and populate the listview with the data. I have tried using nested for loop with the number of unique days and loop the duplicate days inside. But, it doesn't work.
Thank you for your time reading this, and will be glad to answer all your question if you have any doubts!