Added pie chart to statistics page
This commit is contained in:
parent
80de04a324
commit
6b03dce78b
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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>
|
Loading…
Reference in New Issue