Added pie chart to statistics page

This commit is contained in:
ByteHamster 2019-10-03 12:30:34 +02:00
parent 80de04a324
commit 6b03dce78b
3 changed files with 161 additions and 30 deletions

View File

@ -15,6 +15,7 @@ import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.glide.ApGlideSettings; import de.danoeh.antennapod.core.glide.ApGlideSettings;
import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.util.Converter; import de.danoeh.antennapod.core.util.Converter;
import de.danoeh.antennapod.view.PieChartView;
/** /**
* Adapter for the statistics list * Adapter for the statistics list
@ -67,6 +68,12 @@ public class StatisticsListAdapter extends RecyclerView.Adapter<RecyclerView.Vie
HeaderHolder holder = (HeaderHolder) h; HeaderHolder holder = (HeaderHolder) h;
long time = countAll ? statisticsData.totalTimeCountAll : statisticsData.totalTime; long time = countAll ? statisticsData.totalTimeCountAll : statisticsData.totalTime;
holder.totalTime.setText(Converter.shortLocalizedDuration(context, time)); holder.totalTime.setText(Converter.shortLocalizedDuration(context, time));
float[] dataValues = new float[statisticsData.feedTime.size()];
for (int i = 0; i < statisticsData.feedTime.size(); i++) {
DBReader.StatisticsItem item = statisticsData.feedTime.get(i);
dataValues[i] = countAll ? item.timePlayedCountAll : item.timePlayed;
}
holder.pieChart.setData(dataValues);
} else { } else {
StatisticsHolder holder = (StatisticsHolder) h; StatisticsHolder holder = (StatisticsHolder) h;
DBReader.StatisticsItem statsItem = statisticsData.feedTime.get(position - 1); DBReader.StatisticsItem statsItem = statisticsData.feedTime.get(position - 1);
@ -105,10 +112,12 @@ public class StatisticsListAdapter extends RecyclerView.Adapter<RecyclerView.Vie
static class HeaderHolder extends RecyclerView.ViewHolder { static class HeaderHolder extends RecyclerView.ViewHolder {
TextView totalTime; TextView totalTime;
PieChartView pieChart;
HeaderHolder(View itemView) { HeaderHolder(View itemView) {
super(itemView); super(itemView);
totalTime = itemView.findViewById(R.id.total_time); totalTime = itemView.findViewById(R.id.total_time);
pieChart = itemView.findViewById(R.id.pie_chart);
} }
} }

View File

@ -0,0 +1,120 @@
package de.danoeh.antennapod.view;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.support.v7.widget.AppCompatImageView;
import android.util.AttributeSet;
import io.reactivex.annotations.Nullable;
public class PieChartView extends AppCompatImageView {
private PieChartDrawable drawable;
public PieChartView(Context context) {
super(context);
setup();
}
public PieChartView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
setup();
}
public PieChartView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setup();
}
@SuppressLint("ClickableViewAccessibility")
private void setup() {
drawable = new PieChartDrawable();
setImageDrawable(drawable);
}
/**
* Set array od names, array of values and array of colors.
*/
public void setData(float[] dataValues) {
drawable.dataValues = dataValues;
drawable.valueSum = 0;
for (float datum : dataValues) {
drawable.valueSum += datum;
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = getMeasuredWidth();
setMeasuredDimension(width, width / 2);
}
private static class PieChartDrawable extends Drawable {
private static final float MIN_DEGREES = 10f;
private static final float PADDING_DEGREES = 3f;
private static final float STROKE_SIZE = 15f;
private static final int[] COLOR_VALUES = {0xFF3775E6,0xffe51c23,0xffff9800,0xff259b24,0xff9c27b0,
0xff0099c6,0xffdd4477,0xff66aa00,0xffb82e2e,0xff316395,
0xff994499,0xff22aa99,0xffaaaa11,0xff6633cc,0xff0073e6};
private float[] dataValues;
private float valueSum;
private final Paint linePaint;
private PieChartDrawable() {
linePaint = new Paint();
linePaint.setStyle(Paint.Style.STROKE);
linePaint.setStrokeJoin(Paint.Join.ROUND);
linePaint.setStrokeCap(Paint.Cap.ROUND);
linePaint.setStrokeWidth(STROKE_SIZE);
}
@Override
public void draw(@NonNull Canvas canvas) {
if (valueSum == 0) {
return;
}
float radius = getBounds().height() - STROKE_SIZE;
float center = getBounds().width() / 2.f;
RectF arc_bounds = new RectF(center - radius, STROKE_SIZE, center + radius, STROKE_SIZE + radius * 2);
float startAngle = 180;
for (int i = 0; i < dataValues.length; i++) {
float datum = dataValues[i];
float sweepAngle = 180 * datum / valueSum;
if (sweepAngle < MIN_DEGREES) {
break;
}
linePaint.setColor(COLOR_VALUES[i % COLOR_VALUES.length]);
float padding = i == 0 ? PADDING_DEGREES / 2 : PADDING_DEGREES;
canvas.drawArc(arc_bounds, startAngle + padding, sweepAngle - padding, false, linePaint);
startAngle = startAngle + sweepAngle;
}
linePaint.setColor(Color.GRAY);
float sweepAngle = 360 - startAngle - PADDING_DEGREES / 2;
if (sweepAngle > PADDING_DEGREES) {
canvas.drawArc(arc_bounds, startAngle + PADDING_DEGREES, sweepAngle - PADDING_DEGREES, false, linePaint);
}
}
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
@Override
public void setAlpha(int alpha) {
}
@Override
public void setColorFilter(ColorFilter cf) {
}
}
}

View File

@ -1,22 +1,25 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp"> android:padding="16dp">
<de.danoeh.antennapod.view.PieChartView
android:id="@+id/pie_chart"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:id="@+id/total_time_description"
android:textSize="14sp" android:textSize="14sp"
android:text="@string/total_time_listened_to_podcasts" android:text="@string/total_time_listened_to_podcasts"
android:gravity="center_horizontal"/> android:gravity="center_horizontal"
android:layout_above="@+id/total_time"/>
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -25,16 +28,15 @@
android:textColor="?android:attr/textColorPrimary" android:textColor="?android:attr/textColorPrimary"
android:gravity="center_horizontal" android:gravity="center_horizontal"
android:textSize="28sp" android:textSize="28sp"
android:layout_marginBottom="16dp"
android:layout_alignBottom="@id/pie_chart"
tools:text="10.0 hours"/> tools:text="10.0 hours"/>
</LinearLayout>
<View <View
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginBottom="8dp"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="1dp" android:layout_height="1dp"
android:background="?android:attr/dividerVertical"/> android:layout_marginTop="16dp"
android:background="?android:attr/dividerVertical"
android:layout_below="@+id/pie_chart"/>
</LinearLayout> </RelativeLayout>