From 39a5925e7c6843420a61fff90f951b09969d0053 Mon Sep 17 00:00:00 2001 From: Erik Johansson Date: Fri, 9 Mar 2018 21:15:26 +0100 Subject: [PATCH 1/4] Remove subpage view from table fragment --- .../gui/fragments/TableFragment.java | 120 +----------------- .../src/main/res/layout/fragment_table.xml | 38 ------ 2 files changed, 4 insertions(+), 154 deletions(-) diff --git a/android_app/app/src/main/java/com/health/openscale/gui/fragments/TableFragment.java b/android_app/app/src/main/java/com/health/openscale/gui/fragments/TableFragment.java index 294410a8..c1b5f000 100644 --- a/android_app/app/src/main/java/com/health/openscale/gui/fragments/TableFragment.java +++ b/android_app/app/src/main/java/com/health/openscale/gui/fragments/TableFragment.java @@ -17,11 +17,8 @@ package com.health.openscale.gui.fragments; import android.content.Intent; import android.content.res.Configuration; -import android.graphics.Color; -import android.graphics.Typeface; import android.os.Bundle; import android.support.v4.app.Fragment; -import android.support.v4.content.ContextCompat; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.view.Gravity; @@ -30,7 +27,6 @@ import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.BaseAdapter; -import android.widget.Button; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; @@ -54,13 +50,9 @@ public class TableFragment extends Fragment implements FragmentUpdateListener { private View tableView; private ListView tableDataView; private LinearLayout tableHeaderView; - private LinearLayout subpageView; private List measurementViews; - private int selectedSubpageNr; - private static final String SELECTED_SUBPAGE_NR_KEY = "selectedSubpageNr"; - public TableFragment() { } @@ -70,21 +62,12 @@ public class TableFragment extends Fragment implements FragmentUpdateListener { { tableView = inflater.inflate(R.layout.fragment_table, container, false); - subpageView = tableView.findViewById(R.id.subpageView); - tableDataView = tableView.findViewById(R.id.tableDataView); tableHeaderView = tableView.findViewById(R.id.tableHeaderView); tableDataView.setAdapter(new ListViewAdapter()); tableDataView.setOnItemClickListener(new onClickListenerRow()); - if (savedInstanceState == null) { - selectedSubpageNr = 0; - } - else { - selectedSubpageNr = savedInstanceState.getInt(SELECTED_SUBPAGE_NR_KEY); - } - measurementViews = MeasurementView.getMeasurementList( getContext(), MeasurementView.DateTimeOrder.FIRST); @@ -103,68 +86,9 @@ public class TableFragment extends Fragment implements FragmentUpdateListener { super.onDestroyView(); } - @Override - public void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - outState.putInt(SELECTED_SUBPAGE_NR_KEY, selectedSubpageNr); - } - @Override public void updateOnView(List scaleMeasurementList) { - final int maxSize = 25; - - final int subpageCount = (int)Math.ceil(scaleMeasurementList.size() / (double)maxSize); - if (selectedSubpageNr >= subpageCount) { - selectedSubpageNr = Math.max(0, subpageCount - 1); - } - - subpageView.removeAllViews(); - - Button moveSubpageLeft = new Button(tableView.getContext()); - moveSubpageLeft.setText("<"); - moveSubpageLeft.setPadding(0,0,0,0); - moveSubpageLeft.setTextColor(Color.WHITE); - moveSubpageLeft.setBackground(ContextCompat.getDrawable(tableView.getContext(), R.drawable.flat_selector)); - moveSubpageLeft.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)); - moveSubpageLeft.getLayoutParams().height = pxImageDp(20); - moveSubpageLeft.getLayoutParams().width = pxImageDp(50); - moveSubpageLeft.setOnClickListener(new onClickListenerMoveSubpageLeft()); - moveSubpageLeft.setEnabled(selectedSubpageNr > 0); - subpageView.addView(moveSubpageLeft); - - for (int i = 0; i < subpageCount; i++) { - TextView subpageNrView = new TextView(tableView.getContext()); - subpageNrView.setOnClickListener(new onClickListenerSubpageSelect()); - subpageNrView.setText(Integer.toString(i+1)); - subpageNrView.setTextColor(Color.GRAY); - subpageNrView.setPadding(10, 10, 20, 10); - - subpageView.addView(subpageNrView); - } - - if (subpageView.getChildCount() > 1) { - TextView selectedSubpageNrView = (TextView) subpageView.getChildAt(selectedSubpageNr + 1); - if (selectedSubpageNrView != null) { - selectedSubpageNrView.setTypeface(null, Typeface.BOLD); - selectedSubpageNrView.setTextColor(Color.WHITE); - } - } - - Button moveSubpageRight = new Button(tableView.getContext()); - moveSubpageRight.setText(">"); - moveSubpageRight.setPadding(0,0,0,0); - moveSubpageRight.setTextColor(Color.WHITE); - moveSubpageRight.setBackground(ContextCompat.getDrawable(tableView.getContext(), R.drawable.flat_selector)); - moveSubpageRight.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)); - moveSubpageRight.getLayoutParams().height = pxImageDp(20); - moveSubpageRight.getLayoutParams().width = pxImageDp(50); - moveSubpageRight.setOnClickListener(new onClickListenerMoveSubpageRight()); - moveSubpageRight.setEnabled(selectedSubpageNr + 1 < subpageCount); - subpageView.addView(moveSubpageRight); - - subpageView.setVisibility(subpageCount > 1 ? View.VISIBLE : View.GONE); - tableHeaderView.removeAllViews(); ArrayList visibleMeasurements = new ArrayList<>(); @@ -185,10 +109,7 @@ public class TableFragment extends Fragment implements FragmentUpdateListener { } ListViewAdapter adapter = (ListViewAdapter) tableDataView.getAdapter(); - - final int startOffset = maxSize * selectedSubpageNr; - final int endOffset = Math.min(startOffset + maxSize + 1, scaleMeasurementList.size()); - adapter.setMeasurements(visibleMeasurements, scaleMeasurementList.subList(startOffset, endOffset), maxSize); + adapter.setMeasurements(visibleMeasurements, scaleMeasurementList); } private int pxImageDp(float dp) { @@ -204,59 +125,26 @@ public class TableFragment extends Fragment implements FragmentUpdateListener { } } - private class onClickListenerMoveSubpageLeft implements View.OnClickListener { - @Override - public void onClick(View v) { - if (selectedSubpageNr > 0) { - selectedSubpageNr--; - updateOnView(OpenScale.getInstance().getScaleMeasurementList()); - } - } - } - - private class onClickListenerMoveSubpageRight implements View.OnClickListener { - @Override - public void onClick(View v) { - if (selectedSubpageNr < (subpageView.getChildCount() - 3)) { - selectedSubpageNr++; - updateOnView(OpenScale.getInstance().getScaleMeasurementList()); - } - } - } - - private class onClickListenerSubpageSelect implements View.OnClickListener { - @Override - public void onClick(View v) { - TextView nrView = (TextView)v; - - selectedSubpageNr = Integer.parseInt(nrView.getText().toString())-1; - updateOnView(OpenScale.getInstance().getScaleMeasurementList()); - } - } - private class ListViewAdapter extends BaseAdapter { private List visibleMeasurements; private List scaleMeasurements; - private int measurementsToShow = 0; private Spanned[][] stringCache; public void setMeasurements(List visibleMeasurements, - List scaleMeasurements, - int maxSize) { + List scaleMeasurements) { this.visibleMeasurements = visibleMeasurements; this.scaleMeasurements = scaleMeasurements; - measurementsToShow = Math.min(scaleMeasurements.size(), maxSize); - stringCache = new Spanned[measurementsToShow][visibleMeasurements.size()]; + stringCache = new Spanned[scaleMeasurements.size()][visibleMeasurements.size()]; notifyDataSetChanged(); } @Override public int getCount() { - return measurementsToShow; + return scaleMeasurements == null ? 0 : scaleMeasurements.size(); } @Override diff --git a/android_app/app/src/main/res/layout/fragment_table.xml b/android_app/app/src/main/res/layout/fragment_table.xml index bebd0020..19d391a7 100644 --- a/android_app/app/src/main/res/layout/fragment_table.xml +++ b/android_app/app/src/main/res/layout/fragment_table.xml @@ -4,44 +4,6 @@ android:layout_height="match_parent" android:orientation="vertical"> - - - - - - - - - - - - - Date: Sat, 10 Mar 2018 23:14:58 +0100 Subject: [PATCH 2/4] Replace ListView with RecyclerView --- android_app/app/build.gradle | 1 + .../gui/fragments/TableFragment.java | 130 +++++++++--------- .../src/main/res/layout/fragment_table.xml | 15 +- 3 files changed, 68 insertions(+), 78 deletions(-) diff --git a/android_app/app/build.gradle b/android_app/app/build.gradle index 07f03e8a..bda2825f 100644 --- a/android_app/app/build.gradle +++ b/android_app/app/build.gradle @@ -42,6 +42,7 @@ dependencies { implementation "com.android.support:design:${supportLibVersion}" implementation "com.android.support:support-v4:${supportLibVersion}" implementation "com.android.support:appcompat-v7:${supportLibVersion}" + implementation "com.android.support:recyclerview-v7:${supportLibVersion}" // HelloCharts implementation 'com.github.lecho:hellocharts-library:1.5.8@aar' diff --git a/android_app/app/src/main/java/com/health/openscale/gui/fragments/TableFragment.java b/android_app/app/src/main/java/com/health/openscale/gui/fragments/TableFragment.java index c1b5f000..86951b6b 100644 --- a/android_app/app/src/main/java/com/health/openscale/gui/fragments/TableFragment.java +++ b/android_app/app/src/main/java/com/health/openscale/gui/fragments/TableFragment.java @@ -19,17 +19,16 @@ import android.content.Intent; import android.content.res.Configuration; import android.os.Bundle; import android.support.v4.app.Fragment; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.LinearLayout; -import android.widget.ListView; import android.widget.TableLayout; import android.widget.TableRow; import android.widget.TextView; @@ -48,9 +47,12 @@ import static android.util.TypedValue.COMPLEX_UNIT_DIP; public class TableFragment extends Fragment implements FragmentUpdateListener { private View tableView; - private ListView tableDataView; private LinearLayout tableHeaderView; + private RecyclerView recyclerView; + private MeasurementsAdapter adapter; + private RecyclerView.LayoutManager layoutManager; + private List measurementViews; public TableFragment() { @@ -58,15 +60,19 @@ public class TableFragment extends Fragment implements FragmentUpdateListener { } @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) - { + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { tableView = inflater.inflate(R.layout.fragment_table, container, false); - tableDataView = tableView.findViewById(R.id.tableDataView); tableHeaderView = tableView.findViewById(R.id.tableHeaderView); + recyclerView = tableView.findViewById(R.id.tableDataView); - tableDataView.setAdapter(new ListViewAdapter()); - tableDataView.setOnItemClickListener(new onClickListenerRow()); + recyclerView.setHasFixedSize(true); + + layoutManager = new LinearLayoutManager(getContext()); + recyclerView.setLayoutManager(layoutManager); + + adapter = new MeasurementsAdapter(); + recyclerView.setAdapter(adapter); measurementViews = MeasurementView.getMeasurementList( getContext(), MeasurementView.DateTimeOrder.FIRST); @@ -108,7 +114,6 @@ public class TableFragment extends Fragment implements FragmentUpdateListener { } } - ListViewAdapter adapter = (ListViewAdapter) tableDataView.getAdapter(); adapter.setMeasurements(visibleMeasurements, scaleMeasurementList); } @@ -116,16 +121,15 @@ public class TableFragment extends Fragment implements FragmentUpdateListener { return (int)(dp * getResources().getDisplayMetrics().density + 0.5f); } - private class onClickListenerRow implements AdapterView.OnItemClickListener { - @Override - public void onItemClick(AdapterView parent, View view, int position, long id) { - Intent intent = new Intent(tableView.getContext(), DataEntryActivity.class); - intent.putExtra(DataEntryActivity.EXTRA_ID, (int)id); - startActivity(intent); - } - } + private class MeasurementsAdapter extends RecyclerView.Adapter { - private class ListViewAdapter extends BaseAdapter { + public class ViewHolder extends RecyclerView.ViewHolder { + public LinearLayout measurementView; + public ViewHolder(LinearLayout view) { + super(view); + measurementView = view; + } + } private List visibleMeasurements; private List scaleMeasurements; @@ -143,25 +147,42 @@ public class TableFragment extends Fragment implements FragmentUpdateListener { } @Override - public int getCount() { - return scaleMeasurements == null ? 0 : scaleMeasurements.size(); + public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + LinearLayout row = new LinearLayout(getContext()); + row.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT)); + + final int screenSize = getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK; + final boolean isSmallScreen = + screenSize != Configuration.SCREENLAYOUT_SIZE_XLARGE + && screenSize != Configuration.SCREENLAYOUT_SIZE_LARGE; + + for (int i = 0; i < visibleMeasurements.size(); ++i) { + TextView column = new TextView(getContext()); + LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.WRAP_CONTENT, + LinearLayout.LayoutParams.WRAP_CONTENT, + 1); + layoutParams.width = 0; + column.setLayoutParams(layoutParams); + column.setMinLines(2); + column.setGravity(Gravity.CENTER_HORIZONTAL); + + if (isSmallScreen) { + column.setTextSize(COMPLEX_UNIT_DIP, 9); + } + row.addView(column); + } + + return new ViewHolder(row); } @Override - public Object getItem(int position) { - return scaleMeasurements.get(position); - } + public void onBindViewHolder(ViewHolder holder, int position) { + final ScaleMeasurement measurement = scaleMeasurements.get(position); - @Override - public long getItemId(int position) { - return scaleMeasurements.get(position).getId(); - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { // Create entries in stringCache if needed if (stringCache[position][0] == null) { - ScaleMeasurement measurement = scaleMeasurements.get(position); ScaleMeasurement prevMeasurement = null; if (position + 1 < scaleMeasurements.size()) { prevMeasurement = scaleMeasurements.get(position + 1); @@ -178,49 +199,26 @@ public class TableFragment extends Fragment implements FragmentUpdateListener { } } - // Create view if needed - LinearLayout row; - if (convertView == null) { - row = new LinearLayout(getContext()); - - final int screenSize = getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK; - final boolean isSmallScreen = - screenSize != Configuration.SCREENLAYOUT_SIZE_XLARGE - && screenSize != Configuration.SCREENLAYOUT_SIZE_LARGE; - - for (int i = 0; i < visibleMeasurements.size(); ++i) { - TextView column = new TextView(getContext()); - LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( - LinearLayout.LayoutParams.WRAP_CONTENT, - LinearLayout.LayoutParams.WRAP_CONTENT, - 1); - layoutParams.width = 0; - column.setLayoutParams(layoutParams); - column.setMinLines(2); - column.setGravity(Gravity.CENTER_HORIZONTAL); - - if (isSmallScreen) { - column.setTextSize(COMPLEX_UNIT_DIP, 9); - } - row.addView(column); - } - } - else { - row = (LinearLayout) convertView; - } - // Fill view with data + LinearLayout row = holder.measurementView; for (int i = 0; i < visibleMeasurements.size(); ++i) { TextView column = (TextView) row.getChildAt(i); column.setText(stringCache[position][i]); } - return row; + row.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(getContext(), DataEntryActivity.class); + intent.putExtra(DataEntryActivity.EXTRA_ID, measurement.getId()); + startActivity(intent); + } + }); } @Override - public boolean hasStableIds() { - return true; + public int getItemCount() { + return scaleMeasurements == null ? 0 : scaleMeasurements.size(); } } } diff --git a/android_app/app/src/main/res/layout/fragment_table.xml b/android_app/app/src/main/res/layout/fragment_table.xml index 19d391a7..2eef277d 100644 --- a/android_app/app/src/main/res/layout/fragment_table.xml +++ b/android_app/app/src/main/res/layout/fragment_table.xml @@ -13,18 +13,9 @@ android:paddingTop="5dp"> - - - - - + android:scrollbars="vertical" /> From b94e3d8a78018f63fa59aacfd99c9ac6f167bb96 Mon Sep 17 00:00:00 2001 From: Erik Johansson Date: Tue, 19 Jun 2018 20:39:31 +0200 Subject: [PATCH 3/4] Add divider between items and header --- .../health/openscale/gui/fragments/TableFragment.java | 7 +++++-- android_app/app/src/main/res/layout/fragment_table.xml | 9 ++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/android_app/app/src/main/java/com/health/openscale/gui/fragments/TableFragment.java b/android_app/app/src/main/java/com/health/openscale/gui/fragments/TableFragment.java index 86951b6b..4491325f 100644 --- a/android_app/app/src/main/java/com/health/openscale/gui/fragments/TableFragment.java +++ b/android_app/app/src/main/java/com/health/openscale/gui/fragments/TableFragment.java @@ -19,6 +19,7 @@ import android.content.Intent; import android.content.res.Configuration; import android.os.Bundle; import android.support.v4.app.Fragment; +import android.support.v7.widget.DividerItemDecoration; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.text.SpannableStringBuilder; @@ -40,7 +41,6 @@ import com.health.openscale.gui.activities.DataEntryActivity; import com.health.openscale.gui.views.MeasurementView; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import static android.util.TypedValue.COMPLEX_UNIT_DIP; @@ -51,7 +51,7 @@ public class TableFragment extends Fragment implements FragmentUpdateListener { private RecyclerView recyclerView; private MeasurementsAdapter adapter; - private RecyclerView.LayoutManager layoutManager; + private LinearLayoutManager layoutManager; private List measurementViews; @@ -71,6 +71,9 @@ public class TableFragment extends Fragment implements FragmentUpdateListener { layoutManager = new LinearLayoutManager(getContext()); recyclerView.setLayoutManager(layoutManager); + recyclerView.addItemDecoration(new DividerItemDecoration( + recyclerView.getContext(), layoutManager.getOrientation())); + adapter = new MeasurementsAdapter(); recyclerView.setAdapter(adapter); diff --git a/android_app/app/src/main/res/layout/fragment_table.xml b/android_app/app/src/main/res/layout/fragment_table.xml index 2eef277d..0c5ac42f 100644 --- a/android_app/app/src/main/res/layout/fragment_table.xml +++ b/android_app/app/src/main/res/layout/fragment_table.xml @@ -1,5 +1,4 @@ @@ -10,8 +9,12 @@ android:layout_height="wrap_content" android:orientation="horizontal" android:paddingBottom="5dp" - android:paddingTop="5dp"> - + android:paddingTop="5dp" /> + + Date: Wed, 20 Jun 2018 21:29:26 +0200 Subject: [PATCH 4/4] Insert year divider in table When year changes between two measurements, insert a row that only displays the year as a visual divider between years. --- .../gui/fragments/TableFragment.java | 137 ++++++++++++------ 1 file changed, 90 insertions(+), 47 deletions(-) diff --git a/android_app/app/src/main/java/com/health/openscale/gui/fragments/TableFragment.java b/android_app/app/src/main/java/com/health/openscale/gui/fragments/TableFragment.java index 4491325f..22fbf4c4 100644 --- a/android_app/app/src/main/java/com/health/openscale/gui/fragments/TableFragment.java +++ b/android_app/app/src/main/java/com/health/openscale/gui/fragments/TableFragment.java @@ -23,14 +23,12 @@ import android.support.v7.widget.DividerItemDecoration; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.text.SpannableStringBuilder; -import android.text.Spanned; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.LinearLayout; -import android.widget.TableLayout; import android.widget.TableRow; import android.widget.TextView; @@ -41,6 +39,8 @@ import com.health.openscale.gui.activities.DataEntryActivity; import com.health.openscale.gui.views.MeasurementView; import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; import java.util.List; import static android.util.TypedValue.COMPLEX_UNIT_DIP; @@ -100,21 +100,21 @@ public class TableFragment extends Fragment implements FragmentUpdateListener { { tableHeaderView.removeAllViews(); + final int iconHeight = pxImageDp(20); ArrayList visibleMeasurements = new ArrayList<>(); + for (MeasurementView measurement : measurementViews) { - - if (measurement.isVisible()) { - ImageView headerIcon = new ImageView(tableView.getContext()); - headerIcon.setImageDrawable(measurement.getIcon()); - headerIcon.setLayoutParams(new TableRow.LayoutParams(TableLayout.LayoutParams.MATCH_PARENT, TableLayout.LayoutParams.MATCH_PARENT, 1)); - headerIcon.getLayoutParams().width = 0; - headerIcon.setScaleType(ImageView.ScaleType.CENTER_INSIDE); - headerIcon.getLayoutParams().height = pxImageDp(20); - - tableHeaderView.addView(headerIcon); - - visibleMeasurements.add(measurement); + if (!measurement.isVisible()) { + continue; } + ImageView headerIcon = new ImageView(tableView.getContext()); + headerIcon.setImageDrawable(measurement.getIcon()); + headerIcon.setLayoutParams(new TableRow.LayoutParams(0, iconHeight, 1)); + headerIcon.setScaleType(ImageView.ScaleType.CENTER_INSIDE); + + tableHeaderView.addView(headerIcon); + + visibleMeasurements.add(measurement); } adapter.setMeasurements(visibleMeasurements, scaleMeasurementList); @@ -125,6 +125,8 @@ public class TableFragment extends Fragment implements FragmentUpdateListener { } private class MeasurementsAdapter extends RecyclerView.Adapter { + public static final int VIEW_TYPE_MEASUREMENT = 0; + public static final int VIEW_TYPE_YEAR = 1; public class ViewHolder extends RecyclerView.ViewHolder { public LinearLayout measurementView; @@ -137,14 +139,35 @@ public class TableFragment extends Fragment implements FragmentUpdateListener { private List visibleMeasurements; private List scaleMeasurements; - private Spanned[][] stringCache; - public void setMeasurements(List visibleMeasurements, List scaleMeasurements) { this.visibleMeasurements = visibleMeasurements; - this.scaleMeasurements = scaleMeasurements; + this.scaleMeasurements = new ArrayList<>(scaleMeasurements.size() + 10); - stringCache = new Spanned[scaleMeasurements.size()][visibleMeasurements.size()]; + Calendar calendar = Calendar.getInstance(); + if (!scaleMeasurements.isEmpty()) { + calendar.setTime(scaleMeasurements.get(0).getDateTime()); + } + calendar.set(calendar.get(Calendar.YEAR), 0, 1, 0, 0, 0); + calendar.set(calendar.MILLISECOND, 0); + + // Copy all measurements from input parameter to member variable and insert + // an extra "null" entry when the year changes. + Date yearStart = calendar.getTime(); + for (int i = 0; i < scaleMeasurements.size(); ++i) { + final ScaleMeasurement measurement = scaleMeasurements.get(i); + + if (measurement.getDateTime().before(yearStart)) { + this.scaleMeasurements.add(null); + + Calendar newCalendar = Calendar.getInstance(); + newCalendar.setTime(measurement.getDateTime()); + calendar.set(Calendar.YEAR, newCalendar.get(Calendar.YEAR)); + yearStart = calendar.getTime(); + } + + this.scaleMeasurements.add(measurement); + } notifyDataSetChanged(); } @@ -152,28 +175,36 @@ public class TableFragment extends Fragment implements FragmentUpdateListener { @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { LinearLayout row = new LinearLayout(getContext()); - row.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, + row.setLayoutParams(new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)); - final int screenSize = getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK; + final int screenSize = getResources().getConfiguration() + .screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK; final boolean isSmallScreen = screenSize != Configuration.SCREENLAYOUT_SIZE_XLARGE && screenSize != Configuration.SCREENLAYOUT_SIZE_LARGE; - for (int i = 0; i < visibleMeasurements.size(); ++i) { + final int count = viewType == VIEW_TYPE_YEAR ? 1 : visibleMeasurements.size(); + for (int i = 0; i < count; ++i) { TextView column = new TextView(getContext()); - LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( - LinearLayout.LayoutParams.WRAP_CONTENT, - LinearLayout.LayoutParams.WRAP_CONTENT, - 1); - layoutParams.width = 0; - column.setLayoutParams(layoutParams); - column.setMinLines(2); - column.setGravity(Gravity.CENTER_HORIZONTAL); + column.setLayoutParams(new LinearLayout.LayoutParams( + 0, ViewGroup.LayoutParams.WRAP_CONTENT, 1)); - if (isSmallScreen) { - column.setTextSize(COMPLEX_UNIT_DIP, 9); + if (viewType == VIEW_TYPE_MEASUREMENT) { + column.setMinLines(2); + column.setGravity(Gravity.CENTER_HORIZONTAL); + + if (isSmallScreen) { + column.setTextSize(COMPLEX_UNIT_DIP, 9); + } } + else { + column.setPadding(0, 10, 0, 10); + column.setGravity(Gravity.CENTER); + column.setTextSize(COMPLEX_UNIT_DIP, 16); + } + row.addView(column); } @@ -182,31 +213,38 @@ public class TableFragment extends Fragment implements FragmentUpdateListener { @Override public void onBindViewHolder(ViewHolder holder, int position) { + LinearLayout row = holder.measurementView; + final ScaleMeasurement measurement = scaleMeasurements.get(position); + if (measurement == null) { + ScaleMeasurement nextMeasurement = scaleMeasurements.get(position + 1); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(nextMeasurement.getDateTime()); - // Create entries in stringCache if needed - if (stringCache[position][0] == null) { - ScaleMeasurement prevMeasurement = null; - if (position + 1 < scaleMeasurements.size()) { - prevMeasurement = scaleMeasurements.get(position + 1); - } + TextView column = (TextView) row.getChildAt(0); + column.setText(String.format("%d", calendar.get(Calendar.YEAR))); + return; + } - for (int i = 0; i < visibleMeasurements.size(); ++i) { - visibleMeasurements.get(i).loadFrom(measurement, prevMeasurement); - - SpannableStringBuilder string = new SpannableStringBuilder(); - string.append(visibleMeasurements.get(i).getValueAsString(false)); - visibleMeasurements.get(i).appendDiffValue(string, true); - - stringCache[position][i] = string; + ScaleMeasurement prevMeasurement = null; + if (position + 1 < scaleMeasurements.size()) { + prevMeasurement = scaleMeasurements.get(position + 1); + if (prevMeasurement == null) { + prevMeasurement = scaleMeasurements.get(position + 2); } } // Fill view with data - LinearLayout row = holder.measurementView; for (int i = 0; i < visibleMeasurements.size(); ++i) { + final MeasurementView view = visibleMeasurements.get(i); + view.loadFrom(measurement, prevMeasurement); + + SpannableStringBuilder string = new SpannableStringBuilder(); + string.append(view.getValueAsString(false)); + view.appendDiffValue(string, true); + TextView column = (TextView) row.getChildAt(i); - column.setText(stringCache[position][i]); + column.setText(string); } row.setOnClickListener(new View.OnClickListener() { @@ -223,5 +261,10 @@ public class TableFragment extends Fragment implements FragmentUpdateListener { public int getItemCount() { return scaleMeasurements == null ? 0 : scaleMeasurements.size(); } + + @Override + public int getItemViewType(int position) { + return scaleMeasurements.get(position) != null ? VIEW_TYPE_MEASUREMENT : VIEW_TYPE_YEAR; + } } }