summaryrefslogtreecommitdiff
path: root/ui
diff options
context:
space:
mode:
Diffstat (limited to 'ui')
-rw-r--r--ui/statistics/src/main/java/de/danoeh/antennapod/ui/statistics/years/BarChartView.java135
-rw-r--r--ui/statistics/src/main/java/de/danoeh/antennapod/ui/statistics/years/LineChartView.java138
-rw-r--r--ui/statistics/src/main/java/de/danoeh/antennapod/ui/statistics/years/YearStatisticsListAdapter.java37
-rw-r--r--ui/statistics/src/main/res/layout/statistics_listitem_barchart.xml (renamed from ui/statistics/src/main/res/layout/statistics_listitem_linechart.xml)8
4 files changed, 157 insertions, 161 deletions
diff --git a/ui/statistics/src/main/java/de/danoeh/antennapod/ui/statistics/years/BarChartView.java b/ui/statistics/src/main/java/de/danoeh/antennapod/ui/statistics/years/BarChartView.java
new file mode 100644
index 000000000..eadbb29ee
--- /dev/null
+++ b/ui/statistics/src/main/java/de/danoeh/antennapod/ui/statistics/years/BarChartView.java
@@ -0,0 +1,135 @@
+package de.danoeh.antennapod.ui.statistics.years;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.DashPathEffect;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.widget.AppCompatImageView;
+import de.danoeh.antennapod.core.storage.DBReader;
+import de.danoeh.antennapod.ui.common.ThemeUtils;
+import de.danoeh.antennapod.ui.statistics.R;
+
+import java.util.List;
+
+public class BarChartView extends AppCompatImageView {
+ private BarChartDrawable drawable;
+
+ public BarChartView(Context context) {
+ super(context);
+ setup();
+ }
+
+ public BarChartView(Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ setup();
+ }
+
+ public BarChartView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ setup();
+ }
+
+ @SuppressLint("ClickableViewAccessibility")
+ private void setup() {
+ drawable = new BarChartDrawable();
+ setImageDrawable(drawable);
+ }
+
+ /**
+ * Set of data values to display.
+ */
+ public void setData(List<DBReader.MonthlyStatisticsItem> data) {
+ drawable.data = data;
+ drawable.maxValue = 1;
+ for (DBReader.MonthlyStatisticsItem item : data) {
+ drawable.maxValue = Math.max(drawable.maxValue, item.timePlayed);
+ }
+ }
+
+ private class BarChartDrawable extends Drawable {
+ private static final long ONE_HOUR = 3600000L;
+ private List<DBReader.MonthlyStatisticsItem> data;
+ private long maxValue = 1;
+ private final Paint paintBars;
+ private final Paint paintGridLines;
+ private final Paint paintGridText;
+ private final int[] colors = {0, 0xff9c27b0};
+
+ private BarChartDrawable() {
+ colors[0] = ThemeUtils.getColorFromAttr(getContext(), R.attr.colorAccent);
+ paintBars = new Paint();
+ paintBars.setStyle(Paint.Style.FILL);
+ paintBars.setAntiAlias(true);
+ paintGridLines = new Paint();
+ paintGridLines.setStyle(Paint.Style.STROKE);
+ paintGridLines.setPathEffect(new DashPathEffect(new float[] {10f, 10f}, 0f));
+ paintGridLines.setColor(ThemeUtils.getColorFromAttr(getContext(), android.R.attr.textColorSecondary));
+ paintGridText = new Paint();
+ paintGridText.setAntiAlias(true);
+ paintGridText.setColor(ThemeUtils.getColorFromAttr(getContext(), android.R.attr.textColorSecondary));
+ }
+
+ @Override
+ public void draw(@NonNull Canvas canvas) {
+ final float width = getBounds().width();
+ final float height = getBounds().height();
+ final float barHeight = height * 0.9f;
+ final float textPadding = width * 0.05f;
+ final float stepSize = (width - textPadding) / (data.size() + 2);
+ final float textSize = height * 0.06f;
+ paintGridText.setTextSize(textSize);
+
+ paintBars.setStrokeWidth(height * 0.015f);
+ paintBars.setColor(colors[0]);
+ int colorIndex = 0;
+ int lastYear = data.size() > 0 ? data.get(0).year : 0;
+ for (int i = 0; i < data.size(); i++) {
+ float x = textPadding + (i + 1) * stepSize;
+ if (lastYear != data.get(i).year) {
+ lastYear = data.get(i).year;
+ colorIndex++;
+ paintBars.setColor(colors[colorIndex % 2]);
+ if (i < data.size() - 2) {
+ canvas.drawText(String.valueOf(data.get(i).year), x + stepSize,
+ barHeight + (height - barHeight + textSize) / 2, paintGridText);
+ }
+ canvas.drawLine(x, height, x, barHeight, paintGridText);
+ }
+
+ float valuePercentage = (float) Math.max(0.005, (float) data.get(i).timePlayed / maxValue);
+ float y = (1 - valuePercentage) * barHeight;
+ canvas.drawRect(x, y, x + stepSize * 0.95f, barHeight, paintBars);
+ }
+
+ float maxLine = (float) (Math.floor(maxValue / (10.0 * ONE_HOUR)) * 10 * ONE_HOUR);
+ float y = (1 - (maxLine / maxValue)) * barHeight;
+ canvas.drawLine(0, y, width, y, paintGridLines);
+ canvas.drawText(String.valueOf((long) maxLine / ONE_HOUR), 0, y + 1.2f * textSize, paintGridText);
+
+ float midLine = maxLine / 2;
+ y = (1 - (midLine / maxValue)) * barHeight;
+ canvas.drawLine(0, y, width, y, paintGridLines);
+ canvas.drawText(String.valueOf((long) midLine / ONE_HOUR), 0, y + 1.2f * textSize, paintGridText);
+ }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter cf) {
+ }
+ }
+}
diff --git a/ui/statistics/src/main/java/de/danoeh/antennapod/ui/statistics/years/LineChartView.java b/ui/statistics/src/main/java/de/danoeh/antennapod/ui/statistics/years/LineChartView.java
deleted file mode 100644
index e56bb4f56..000000000
--- a/ui/statistics/src/main/java/de/danoeh/antennapod/ui/statistics/years/LineChartView.java
+++ /dev/null
@@ -1,138 +0,0 @@
-package de.danoeh.antennapod.ui.statistics.years;
-
-import android.annotation.SuppressLint;
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.ColorFilter;
-import android.graphics.DashPathEffect;
-import android.graphics.LinearGradient;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.PixelFormat;
-import android.graphics.Shader;
-import android.graphics.drawable.Drawable;
-import android.util.AttributeSet;
-import androidx.annotation.NonNull;
-import androidx.appcompat.widget.AppCompatImageView;
-import de.danoeh.antennapod.ui.common.ThemeUtils;
-import de.danoeh.antennapod.ui.statistics.R;
-import io.reactivex.annotations.Nullable;
-
-public class LineChartView extends AppCompatImageView {
- private LineChartDrawable drawable;
-
- public LineChartView(Context context) {
- super(context);
- setup();
- }
-
- public LineChartView(Context context, @Nullable AttributeSet attrs) {
- super(context, attrs);
- setup();
- }
-
- public LineChartView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- setup();
- }
-
- @SuppressLint("ClickableViewAccessibility")
- private void setup() {
- drawable = new LineChartDrawable();
- setImageDrawable(drawable);
- }
-
- /**
- * Set of data values to display.
- */
- public void setData(LineChartData data) {
- drawable.data = data;
- }
-
- public static class LineChartData {
- private final long valueMax;
- private final long[] values;
- private final long[] verticalLines;
-
- public LineChartData(long[] values, long[] verticalLines) {
- this.values = values;
- long valueMax = 0;
- for (long datum : values) {
- valueMax = Math.max(datum, valueMax);
- }
- this.valueMax = valueMax;
- this.verticalLines = verticalLines;
- }
-
- public float getHeight(int item) {
- return (float) values[item] / valueMax;
- }
- }
-
- private class LineChartDrawable extends Drawable {
- private LineChartData data;
- private final Paint paintLine;
- private final Paint paintBackground;
- private final Paint paintVerticalLines;
-
- private LineChartDrawable() {
- paintLine = new Paint();
- paintLine.setFlags(Paint.ANTI_ALIAS_FLAG);
- paintLine.setStyle(Paint.Style.STROKE);
- paintLine.setStrokeJoin(Paint.Join.ROUND);
- paintLine.setStrokeCap(Paint.Cap.ROUND);
- paintLine.setColor(ThemeUtils.getColorFromAttr(getContext(), R.attr.colorAccent));
- paintBackground = new Paint();
- paintBackground.setStyle(Paint.Style.FILL);
- paintVerticalLines = new Paint();
- paintVerticalLines.setStyle(Paint.Style.STROKE);
- paintVerticalLines.setPathEffect(new DashPathEffect(new float[] {10f, 10f}, 0f));
- paintVerticalLines.setColor(0x66777777);
- }
-
- @Override
- public void draw(@NonNull Canvas canvas) {
- float width = getBounds().width();
- float height = getBounds().height();
- float usableHeight = height * 0.9f;
- float stepSize = width / (data.values.length + 1);
-
- paintVerticalLines.setStrokeWidth(height * 0.005f);
- for (long line : data.verticalLines) {
- canvas.drawLine((line + 1) * stepSize, 0, (line + 1) * stepSize, height, paintVerticalLines);
- }
-
- paintLine.setStrokeWidth(height * 0.015f);
- Path path = new Path();
- for (int i = 0; i < data.values.length; i++) {
- if (i == 0) {
- path.moveTo((i + 1) * stepSize, (1 - data.getHeight(i)) * usableHeight + height * 0.05f);
- } else {
- path.lineTo((i + 1) * stepSize, (1 - data.getHeight(i)) * usableHeight + height * 0.05f);
- }
- }
- canvas.drawPath(path, paintLine);
-
- path.lineTo(data.values.length * stepSize, height);
- path.lineTo(stepSize, height);
- paintBackground.setShader(new LinearGradient(0, 0, 0, height,
- (ThemeUtils.getColorFromAttr(getContext(), R.attr.colorAccent) & 0xffffff) + 0x66000000,
- Color.TRANSPARENT, Shader.TileMode.CLAMP));
- canvas.drawPath(path, paintBackground);
- }
-
- @Override
- public int getOpacity() {
- return PixelFormat.TRANSLUCENT;
- }
-
- @Override
- public void setAlpha(int alpha) {
- }
-
- @Override
- public void setColorFilter(ColorFilter cf) {
- }
- }
-}
diff --git a/ui/statistics/src/main/java/de/danoeh/antennapod/ui/statistics/years/YearStatisticsListAdapter.java b/ui/statistics/src/main/java/de/danoeh/antennapod/ui/statistics/years/YearStatisticsListAdapter.java
index ed5a7a4f1..e3251a96b 100644
--- a/ui/statistics/src/main/java/de/danoeh/antennapod/ui/statistics/years/YearStatisticsListAdapter.java
+++ b/ui/statistics/src/main/java/de/danoeh/antennapod/ui/statistics/years/YearStatisticsListAdapter.java
@@ -8,7 +8,6 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import de.danoeh.antennapod.core.storage.DBReader;
-import de.danoeh.antennapod.core.util.LongList;
import de.danoeh.antennapod.ui.statistics.R;
import java.util.ArrayList;
@@ -23,8 +22,8 @@ public class YearStatisticsListAdapter extends RecyclerView.Adapter<RecyclerView
private static final int TYPE_HEADER = 0;
private static final int TYPE_FEED = 1;
final Context context;
- private List<DBReader.MonthlyStatisticsItem> statisticsData = new ArrayList<>();
- LineChartView.LineChartData lineChartData;
+ private final List<DBReader.MonthlyStatisticsItem> statisticsData = new ArrayList<>();
+ private final List<DBReader.MonthlyStatisticsItem> yearlyAggregate = new ArrayList<>();
public YearStatisticsListAdapter(Context context) {
this.context = context;
@@ -32,7 +31,7 @@ public class YearStatisticsListAdapter extends RecyclerView.Adapter<RecyclerView
@Override
public int getItemCount() {
- return statisticsData.size() + 1;
+ return yearlyAggregate.size() + 1;
}
@Override
@@ -45,7 +44,7 @@ public class YearStatisticsListAdapter extends RecyclerView.Adapter<RecyclerView
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
if (viewType == TYPE_HEADER) {
- return new HeaderHolder(inflater.inflate(R.layout.statistics_listitem_linechart, parent, false));
+ return new HeaderHolder(inflater.inflate(R.layout.statistics_listitem_barchart, parent, false));
}
return new StatisticsHolder(inflater.inflate(R.layout.statistics_year_listitem, parent, false));
}
@@ -54,10 +53,10 @@ public class YearStatisticsListAdapter extends RecyclerView.Adapter<RecyclerView
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder h, int position) {
if (getItemViewType(position) == TYPE_HEADER) {
HeaderHolder holder = (HeaderHolder) h;
- holder.lineChart.setData(lineChartData);
+ holder.barChart.setData(statisticsData);
} else {
StatisticsHolder holder = (StatisticsHolder) h;
- DBReader.MonthlyStatisticsItem statsItem = statisticsData.get(position - 1);
+ DBReader.MonthlyStatisticsItem statsItem = yearlyAggregate.get(position - 1);
holder.year.setText(String.format(Locale.getDefault(), "%d ", statsItem.year));
holder.hours.setText(String.format(Locale.getDefault(), "%.1f ", statsItem.timePlayed / 3600000.0f)
+ context.getString(R.string.time_hours));
@@ -68,42 +67,44 @@ public class YearStatisticsListAdapter extends RecyclerView.Adapter<RecyclerView
int lastYear = statistics.size() > 0 ? statistics.get(0).year : 0;
int lastDataPoint = statistics.size() > 0 ? (statistics.get(0).month - 1) + lastYear * 12 : 0;
long yearSum = 0;
+ yearlyAggregate.clear();
statisticsData.clear();
- LongList lineChartValues = new LongList();
- LongList lineChartHorizontalLines = new LongList();
for (DBReader.MonthlyStatisticsItem statistic : statistics) {
if (statistic.year != lastYear) {
DBReader.MonthlyStatisticsItem yearAggregate = new DBReader.MonthlyStatisticsItem();
yearAggregate.year = lastYear;
yearAggregate.timePlayed = yearSum;
- statisticsData.add(yearAggregate);
+ yearlyAggregate.add(yearAggregate);
yearSum = 0;
lastYear = statistic.year;
- lineChartHorizontalLines.add(lineChartValues.size());
}
yearSum += statistic.timePlayed;
while (lastDataPoint + 1 < (statistic.month - 1) + statistic.year * 12) {
- lineChartValues.add(0); // Compensate for months without playback
lastDataPoint++;
+ DBReader.MonthlyStatisticsItem item = new DBReader.MonthlyStatisticsItem();
+ item.year = lastDataPoint / 12;
+ item.month = lastDataPoint % 12 + 1;
+ statisticsData.add(item); // Compensate for months without playback
+ System.out.println("aaaaa extra:" + item.month + "/" + item.year);
}
- lineChartValues.add(statistic.timePlayed);
+ System.out.println("aaaaa add:" + statistic.month + "/" + statistic.year);
+ statisticsData.add(statistic);
lastDataPoint = (statistic.month - 1) + statistic.year * 12;
}
DBReader.MonthlyStatisticsItem yearAggregate = new DBReader.MonthlyStatisticsItem();
yearAggregate.year = lastYear;
yearAggregate.timePlayed = yearSum;
- statisticsData.add(yearAggregate);
- Collections.reverse(statisticsData);
- lineChartData = new LineChartView.LineChartData(lineChartValues.toArray(), lineChartHorizontalLines.toArray());
+ yearlyAggregate.add(yearAggregate);
+ Collections.reverse(yearlyAggregate);
notifyDataSetChanged();
}
static class HeaderHolder extends RecyclerView.ViewHolder {
- LineChartView lineChart;
+ BarChartView barChart;
HeaderHolder(View itemView) {
super(itemView);
- lineChart = itemView.findViewById(R.id.lineChart);
+ barChart = itemView.findViewById(R.id.barChart);
}
}
diff --git a/ui/statistics/src/main/res/layout/statistics_listitem_linechart.xml b/ui/statistics/src/main/res/layout/statistics_listitem_barchart.xml
index e7d4052de..d70e1da07 100644
--- a/ui/statistics/src/main/res/layout/statistics_listitem_linechart.xml
+++ b/ui/statistics/src/main/res/layout/statistics_listitem_barchart.xml
@@ -6,12 +6,10 @@
android:orientation="vertical"
android:padding="16dp">
- <de.danoeh.antennapod.ui.statistics.years.LineChartView
- android:id="@+id/lineChart"
+ <de.danoeh.antennapod.ui.statistics.years.BarChartView
+ android:id="@+id/barChart"
android:layout_width="match_parent"
- android:layout_height="200dp"
- android:layout_marginStart="8dp"
- android:layout_marginEnd="8dp" />
+ android:layout_height="200dp" />
<View
android:layout_width="match_parent"