After Width: | Height: | Size: 40 KiB |
@ -1,233 +1,233 @@
|
||||
package org.isoron.uhabits.views;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
|
||||
import org.isoron.helpers.ColorHelper;
|
||||
import org.isoron.helpers.DateHelper;
|
||||
import org.isoron.uhabits.R;
|
||||
import org.isoron.uhabits.models.Habit;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Paint.Align;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Typeface;
|
||||
import android.support.v4.view.MotionEventCompat;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
import org.isoron.helpers.ColorHelper;
|
||||
import org.isoron.helpers.DateHelper;
|
||||
import org.isoron.uhabits.R;
|
||||
import org.isoron.uhabits.models.Habit;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
|
||||
public class HabitHistoryView extends View
|
||||
{
|
||||
|
||||
private Habit habit;
|
||||
private int reps[];
|
||||
private Habit habit;
|
||||
private int reps[];
|
||||
|
||||
private Context context;
|
||||
private Paint pSquareBg, pSquareFg, pTextHeader;
|
||||
private Context context;
|
||||
private Paint pSquareBg, pSquareFg, pTextHeader;
|
||||
|
||||
private int squareSize, squareSpacing;
|
||||
private int nColumns, offsetWeeks;
|
||||
|
||||
private int colorPrimary, colorPrimaryBrighter, grey;
|
||||
|
||||
public HabitHistoryView(Context context, Habit habit, int squareSize)
|
||||
{
|
||||
super(context);
|
||||
this.habit = habit;
|
||||
this.context = context;
|
||||
this.squareSize = squareSize;
|
||||
|
||||
Typeface fontawesome = Typeface.createFromAsset(context.getAssets(),
|
||||
"fontawesome-webfont.ttf");
|
||||
|
||||
colorPrimary = habit.color;
|
||||
colorPrimaryBrighter = ColorHelper.mixColors(colorPrimary, Color.WHITE, 0.5f);
|
||||
grey = Color.rgb(230, 230, 230);
|
||||
squareSpacing = 2;
|
||||
|
||||
pTextHeader = new Paint();
|
||||
pTextHeader.setColor(Color.LTGRAY);
|
||||
pTextHeader.setTextAlign(Align.LEFT);
|
||||
pTextHeader.setTextSize(squareSize * 0.5f);
|
||||
pTextHeader.setAntiAlias(true);
|
||||
|
||||
pSquareBg = new Paint();
|
||||
pSquareBg.setColor(habit.color);
|
||||
|
||||
pSquareFg = new Paint();
|
||||
pSquareFg.setColor(Color.WHITE);
|
||||
pSquareFg.setAntiAlias(true);
|
||||
// pSquareFg.setTypeface(fontawesome);
|
||||
pSquareFg.setTextSize(squareSize * 0.5f);
|
||||
pSquareFg.setTextAlign(Align.CENTER);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
|
||||
{
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
setMeasuredDimension(getMeasuredWidth(), 8 * squareSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int w, int h, int oldw, int oldh)
|
||||
{
|
||||
private int nColumns, offsetWeeks;
|
||||
|
||||
private int colorPrimary, colorPrimaryBrighter, grey;
|
||||
private Float prevX, prevY;
|
||||
|
||||
public HabitHistoryView(Context context, Habit habit, int squareSize)
|
||||
{
|
||||
super(context);
|
||||
this.habit = habit;
|
||||
this.context = context;
|
||||
this.squareSize = squareSize;
|
||||
|
||||
colorPrimary = habit.color;
|
||||
colorPrimaryBrighter = ColorHelper.mixColors(colorPrimary, Color.WHITE, 0.5f);
|
||||
grey = Color.rgb(230, 230, 230);
|
||||
squareSpacing = 2;
|
||||
|
||||
pTextHeader = new Paint();
|
||||
pTextHeader.setColor(Color.LTGRAY);
|
||||
pTextHeader.setTextAlign(Align.LEFT);
|
||||
pTextHeader.setTextSize(squareSize * 0.5f);
|
||||
pTextHeader.setAntiAlias(true);
|
||||
|
||||
pSquareBg = new Paint();
|
||||
pSquareBg.setColor(habit.color);
|
||||
|
||||
pSquareFg = new Paint();
|
||||
pSquareFg.setColor(Color.WHITE);
|
||||
pSquareFg.setAntiAlias(true);
|
||||
pSquareFg.setTextSize(squareSize * 0.5f);
|
||||
pSquareFg.setTextAlign(Align.CENTER);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
|
||||
{
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
setMeasuredDimension(getMeasuredWidth(), 8 * squareSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int w, int h, int oldw, int oldh)
|
||||
{
|
||||
nColumns = (w / squareSize) - 1;
|
||||
fetchReps();
|
||||
}
|
||||
|
||||
private void fetchReps()
|
||||
{
|
||||
Calendar currentDate = new GregorianCalendar();
|
||||
currentDate.add(Calendar.DAY_OF_YEAR, -offsetWeeks * 7);
|
||||
int dayOfWeek = currentDate.get(Calendar.DAY_OF_WEEK) % 7;
|
||||
|
||||
long dateTo = DateHelper.getStartOfToday();
|
||||
for (int i = 0; i < 7 - dayOfWeek; i++)
|
||||
dateTo += DateHelper.millisecondsInOneDay;
|
||||
|
||||
for (int i = 0; i < offsetWeeks * 7; i++)
|
||||
dateTo -= DateHelper.millisecondsInOneDay;
|
||||
|
||||
long dateFrom = dateTo;
|
||||
for (int i = 0; i < nColumns * 7; i++)
|
||||
dateFrom -= DateHelper.millisecondsInOneDay;
|
||||
|
||||
reps = habit.getReps(dateFrom, dateTo);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas)
|
||||
{
|
||||
super.onDraw(canvas);
|
||||
|
||||
Rect square = new Rect(0, 0, squareSize - squareSpacing, squareSize - squareSpacing);
|
||||
|
||||
Calendar currentDate = new GregorianCalendar();
|
||||
currentDate.add(Calendar.DAY_OF_YEAR, -(offsetWeeks-1) * 7);
|
||||
|
||||
int nDays = nColumns * 7;
|
||||
int todayWeekday = new GregorianCalendar().get(Calendar.DAY_OF_WEEK) % 7;
|
||||
|
||||
currentDate.add(Calendar.DAY_OF_YEAR, -nDays);
|
||||
|
||||
SimpleDateFormat dfMonth = new SimpleDateFormat("MMM");
|
||||
SimpleDateFormat dfYear = new SimpleDateFormat("yyyy");
|
||||
|
||||
String previousMonth = "";
|
||||
String previousYear = "";
|
||||
|
||||
int colors[] = { grey, colorPrimaryBrighter, colorPrimary };
|
||||
String markers[] = { context.getString(R.string.fa_times),
|
||||
context.getString(R.string.fa_check), context.getString(R.string.fa_check) };
|
||||
|
||||
float squareTextOffset = pSquareFg.getFontSpacing() * 0.4f;
|
||||
float headerTextOffset = pTextHeader.getFontSpacing() * 0.3f;
|
||||
boolean justPrintedYear = false;
|
||||
|
||||
int k = nDays;
|
||||
for (int i = 0; i < nColumns; i++)
|
||||
{
|
||||
String month = dfMonth.format(currentDate.getTime());
|
||||
String year = dfYear.format(currentDate.getTime());
|
||||
|
||||
if(!month.equals(previousMonth))
|
||||
{
|
||||
int offset = 0;
|
||||
if(justPrintedYear)
|
||||
offset += squareSize;
|
||||
|
||||
canvas.drawText(month, square.left + offset, square.bottom - headerTextOffset,
|
||||
pTextHeader);
|
||||
previousMonth = month;
|
||||
justPrintedYear = false;
|
||||
}
|
||||
else if(!year.equals(previousYear))
|
||||
{
|
||||
canvas.drawText(year, square.left, square.bottom - headerTextOffset, pTextHeader);
|
||||
previousYear = year;
|
||||
justPrintedYear = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
justPrintedYear = false;
|
||||
}
|
||||
|
||||
|
||||
square.offset(0, squareSize);
|
||||
|
||||
for (int j = 0; j < 7; j++)
|
||||
{
|
||||
if(!(i == nColumns - 1 && offsetWeeks == 0 && j > todayWeekday))
|
||||
{
|
||||
pSquareBg.setColor(colors[reps[k]]);
|
||||
canvas.drawRect(square, pSquareBg);
|
||||
// canvas.drawText(markers[reps[k]], square.centerX(), square.centerY()
|
||||
// + squareTextOffset, pSquareFg);
|
||||
canvas.drawText(Integer.toString(currentDate.get(Calendar.DAY_OF_MONTH)),
|
||||
square.centerX(), square.centerY() + squareTextOffset, pSquareFg);
|
||||
}
|
||||
|
||||
currentDate.add(Calendar.DAY_OF_MONTH, 1);
|
||||
square.offset(0, squareSize);
|
||||
k--;
|
||||
}
|
||||
|
||||
square.offset(squareSize, -8 * squareSize);
|
||||
}
|
||||
|
||||
String wdays[] = { "Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri" };
|
||||
|
||||
for (int i = 0; i < 7; i++)
|
||||
{
|
||||
square.offset(0, squareSize);
|
||||
canvas.drawText(wdays[i], square.left + headerTextOffset, square.bottom
|
||||
- headerTextOffset, pTextHeader);
|
||||
}
|
||||
}
|
||||
|
||||
private Float prevX, prevY;
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event)
|
||||
{
|
||||
int action = event.getAction();
|
||||
|
||||
int pointerIndex = MotionEventCompat.getActionIndex(event);
|
||||
final float x = MotionEventCompat.getX(event, pointerIndex);
|
||||
final float y = MotionEventCompat.getY(event, pointerIndex);
|
||||
|
||||
if(action == MotionEvent.ACTION_DOWN)
|
||||
{
|
||||
prevX = x;
|
||||
prevY = y;
|
||||
}
|
||||
|
||||
if(action == MotionEvent.ACTION_MOVE)
|
||||
{
|
||||
float dx = x - prevX;
|
||||
float dy = y - prevY;
|
||||
|
||||
int newOffsetWeeks = offsetWeeks + (int) (dx / squareSize);
|
||||
newOffsetWeeks = Math.max(0, newOffsetWeeks);
|
||||
|
||||
if(newOffsetWeeks != offsetWeeks)
|
||||
{
|
||||
prevX = x;
|
||||
prevY = y;
|
||||
offsetWeeks = newOffsetWeeks;
|
||||
|
||||
fetchReps();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
fetchReps();
|
||||
}
|
||||
|
||||
private void fetchReps()
|
||||
{
|
||||
Calendar currentDate = new GregorianCalendar();
|
||||
currentDate.add(Calendar.DAY_OF_YEAR, -offsetWeeks * 7);
|
||||
int dayOfWeek = currentDate.get(Calendar.DAY_OF_WEEK) % 7;
|
||||
|
||||
long dateTo = DateHelper.getStartOfToday();
|
||||
for (int i = 0; i < 7 - dayOfWeek; i++)
|
||||
dateTo += DateHelper.millisecondsInOneDay;
|
||||
|
||||
for (int i = 0; i < offsetWeeks * 7; i++)
|
||||
dateTo -= DateHelper.millisecondsInOneDay;
|
||||
|
||||
long dateFrom = dateTo;
|
||||
for (int i = 0; i < nColumns * 7; i++)
|
||||
dateFrom -= DateHelper.millisecondsInOneDay;
|
||||
|
||||
reps = habit.getReps(dateFrom, dateTo);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas)
|
||||
{
|
||||
super.onDraw(canvas);
|
||||
|
||||
Rect square = new Rect(0, 0, squareSize - squareSpacing, squareSize - squareSpacing);
|
||||
|
||||
Calendar currentDate = new GregorianCalendar();
|
||||
currentDate.add(Calendar.DAY_OF_YEAR, - (offsetWeeks - 1) * 7);
|
||||
|
||||
int nDays = nColumns * 7;
|
||||
int todayWeekday = new GregorianCalendar().get(Calendar.DAY_OF_WEEK) % 7;
|
||||
|
||||
currentDate.add(Calendar.DAY_OF_YEAR, -nDays);
|
||||
currentDate.add(Calendar.DAY_OF_YEAR, -todayWeekday);
|
||||
|
||||
SimpleDateFormat dfMonth = new SimpleDateFormat("MMM");
|
||||
SimpleDateFormat dfYear = new SimpleDateFormat("yyyy");
|
||||
|
||||
String previousMonth = "";
|
||||
String previousYear = "";
|
||||
|
||||
int colors[] = {grey, colorPrimaryBrighter, colorPrimary};
|
||||
String markers[] =
|
||||
{context.getString(R.string.fa_times), context.getString(R.string.fa_check),
|
||||
context.getString(R.string.fa_check)};
|
||||
|
||||
float squareTextOffset = pSquareFg.getFontSpacing() * 0.4f;
|
||||
float headerTextOffset = pTextHeader.getFontSpacing() * 0.3f;
|
||||
boolean justPrintedYear = false;
|
||||
|
||||
int k = nDays;
|
||||
for (int i = 0; i < nColumns; i++)
|
||||
{
|
||||
String month = dfMonth.format(currentDate.getTime());
|
||||
String year = dfYear.format(currentDate.getTime());
|
||||
|
||||
if (!month.equals(previousMonth))
|
||||
{
|
||||
int offset = 0;
|
||||
if (justPrintedYear) offset += squareSize;
|
||||
|
||||
canvas.drawText(month, square.left + offset, square.bottom - headerTextOffset,
|
||||
pTextHeader);
|
||||
previousMonth = month;
|
||||
justPrintedYear = false;
|
||||
} else if (!year.equals(previousYear))
|
||||
{
|
||||
canvas.drawText(year, square.left, square.bottom - headerTextOffset, pTextHeader);
|
||||
previousYear = year;
|
||||
justPrintedYear = true;
|
||||
} else
|
||||
{
|
||||
justPrintedYear = false;
|
||||
}
|
||||
|
||||
|
||||
square.offset(0, squareSize);
|
||||
|
||||
for (int j = 0; j < 7; j++)
|
||||
{
|
||||
if (!(i == nColumns - 1 && offsetWeeks == 0 && j > todayWeekday))
|
||||
{
|
||||
pSquareBg.setColor(colors[reps[k]]);
|
||||
canvas.drawRect(square, pSquareBg);
|
||||
canvas.drawText(Integer.toString(currentDate.get(Calendar.DAY_OF_MONTH)),
|
||||
square.centerX(), square.centerY() + squareTextOffset, pSquareFg);
|
||||
}
|
||||
|
||||
currentDate.add(Calendar.DAY_OF_MONTH, 1);
|
||||
square.offset(0, squareSize);
|
||||
k--;
|
||||
}
|
||||
|
||||
square.offset(squareSize, -8 * squareSize);
|
||||
}
|
||||
|
||||
String wdays[] = {"Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri"};
|
||||
|
||||
for (int i = 0; i < 7; i++)
|
||||
{
|
||||
square.offset(0, squareSize);
|
||||
canvas.drawText(wdays[i], square.left + headerTextOffset,
|
||||
square.bottom - headerTextOffset, pTextHeader);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event)
|
||||
{
|
||||
int action = event.getAction();
|
||||
|
||||
int pointerIndex = MotionEventCompat.getActionIndex(event);
|
||||
final float x = MotionEventCompat.getX(event, pointerIndex);
|
||||
final float y = MotionEventCompat.getY(event, pointerIndex);
|
||||
|
||||
if (action == MotionEvent.ACTION_DOWN)
|
||||
{
|
||||
prevX = x;
|
||||
prevY = y;
|
||||
}
|
||||
|
||||
if (action == MotionEvent.ACTION_MOVE)
|
||||
{
|
||||
float dx = x - prevX;
|
||||
float dy = y - prevY;
|
||||
|
||||
if (Math.abs(dy) > Math.abs(dx)) return false;
|
||||
getParent().requestDisallowInterceptTouchEvent(true);
|
||||
if(move(dx))
|
||||
{
|
||||
prevX = x;
|
||||
prevY = y;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean move(float dx)
|
||||
{
|
||||
int newOffsetWeeks = offsetWeeks + (int) (dx / squareSize);
|
||||
newOffsetWeeks = Math.max(0, newOffsetWeeks);
|
||||
|
||||
if (newOffsetWeeks != offsetWeeks)
|
||||
{
|
||||
offsetWeeks = newOffsetWeeks;
|
||||
fetchReps();
|
||||
invalidate();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,252 @@
|
||||
package org.isoron.uhabits.views;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.RectF;
|
||||
import android.support.v4.view.MotionEventCompat;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
import org.isoron.helpers.ColorHelper;
|
||||
import org.isoron.helpers.DateHelper;
|
||||
import org.isoron.uhabits.models.Habit;
|
||||
import org.isoron.uhabits.models.Score;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.List;
|
||||
|
||||
public class HabitScoreView extends View
|
||||
{
|
||||
public static final int BUCKET_SIZE = 7;
|
||||
|
||||
private final Paint pGrid;
|
||||
private final float em;
|
||||
private Habit habit;
|
||||
private int columnWidth, columnHeight, nColumns;
|
||||
|
||||
private Paint pText, pGraph;
|
||||
private int dataOffset;
|
||||
|
||||
private int barHeaderHeight;
|
||||
|
||||
private int[] colors;
|
||||
private float prevX;
|
||||
private float prevY;
|
||||
private List<Score> scores;
|
||||
|
||||
public HabitScoreView(Context context, Habit habit, int columnWidth)
|
||||
{
|
||||
super(context);
|
||||
this.habit = habit;
|
||||
this.columnWidth = columnWidth;
|
||||
|
||||
pText = new Paint();
|
||||
pText.setColor(Color.LTGRAY);
|
||||
pText.setTextAlign(Paint.Align.LEFT);
|
||||
pText.setTextSize(columnWidth * 0.5f);
|
||||
pText.setAntiAlias(true);
|
||||
|
||||
pGraph = new Paint();
|
||||
pGraph.setTextAlign(Paint.Align.CENTER);
|
||||
pGraph.setTextSize(columnWidth * 0.5f);
|
||||
pGraph.setAntiAlias(true);
|
||||
pGraph.setStrokeWidth(columnWidth * 0.1f);
|
||||
|
||||
pGrid = new Paint();
|
||||
pGrid.setColor(Color.LTGRAY);
|
||||
pGrid.setAntiAlias(true);
|
||||
pGrid.setStrokeWidth(columnWidth * 0.05f);
|
||||
|
||||
columnHeight = 8 * columnWidth;
|
||||
barHeaderHeight = columnWidth;
|
||||
em = pText.getFontSpacing();
|
||||
|
||||
colors = new int[4];
|
||||
|
||||
colors[0] = Color.rgb(230, 230, 230);
|
||||
colors[3] = habit.color;
|
||||
colors[1] = ColorHelper.mixColors(colors[0], colors[3], 0.66f);
|
||||
colors[2] = ColorHelper.mixColors(colors[0], colors[3], 0.33f);
|
||||
}
|
||||
|
||||
private void fetchScores()
|
||||
{
|
||||
|
||||
long toTimestamp = DateHelper.getStartOfToday();
|
||||
for (int i = 0; i < dataOffset * BUCKET_SIZE; i++)
|
||||
toTimestamp -= DateHelper.millisecondsInOneDay;
|
||||
|
||||
long fromTimestamp = toTimestamp;
|
||||
for (int i = 0; i < nColumns * BUCKET_SIZE; i++)
|
||||
fromTimestamp -= DateHelper.millisecondsInOneDay;
|
||||
|
||||
scores = habit.getScores(fromTimestamp, toTimestamp, BUCKET_SIZE * DateHelper.millisecondsInOneDay,
|
||||
toTimestamp);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
|
||||
{
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
setMeasuredDimension(getMeasuredWidth(), columnHeight + 2 * barHeaderHeight);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int w, int h, int oldw, int oldh)
|
||||
{
|
||||
super.onSizeChanged(w, h, oldw, oldh);
|
||||
nColumns = w / columnWidth;
|
||||
fetchScores();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas)
|
||||
{
|
||||
super.onDraw(canvas);
|
||||
|
||||
float lineHeight = pText.getFontSpacing();
|
||||
float barHeaderOffset = lineHeight * 0.4f;
|
||||
|
||||
RectF rGrid = new RectF(0, 0, nColumns * columnWidth, columnHeight);
|
||||
rGrid.offset(0, barHeaderHeight);
|
||||
drawGrid(canvas, rGrid);
|
||||
|
||||
SimpleDateFormat dfMonth = new SimpleDateFormat("MMM");
|
||||
SimpleDateFormat dfDay = new SimpleDateFormat("d");
|
||||
|
||||
String previousMonth = "";
|
||||
|
||||
pGraph.setColor(habit.color);
|
||||
RectF prevR = null;
|
||||
|
||||
for (int offset = nColumns - scores.size(); offset < nColumns; offset++)
|
||||
{
|
||||
Score score = scores.get(offset - nColumns + scores.size());
|
||||
String month = dfMonth.format(score.timestamp);
|
||||
String day = dfDay.format(score.timestamp);
|
||||
|
||||
long s = score.score;
|
||||
double sRelative = ((double) s) / Habit.MAX_SCORE;
|
||||
|
||||
int height = (int) (columnHeight * sRelative);
|
||||
|
||||
RectF r = new RectF(0, 0, columnWidth, columnWidth);
|
||||
r.offset(offset * columnWidth,
|
||||
barHeaderHeight + columnHeight - height - columnWidth / 2);
|
||||
|
||||
if (prevR != null)
|
||||
{
|
||||
drawLine(canvas, prevR, r);
|
||||
drawMarker(canvas, prevR);
|
||||
}
|
||||
|
||||
if (offset == nColumns - 1) drawMarker(canvas, r);
|
||||
|
||||
prevR = r;
|
||||
|
||||
r = new RectF(0, 0, columnWidth, columnHeight);
|
||||
r.offset(offset * columnWidth, barHeaderHeight);
|
||||
if (!month.equals(previousMonth))
|
||||
{
|
||||
canvas.drawText(month, r.centerX(), r.bottom + lineHeight * 1.2f, pText);
|
||||
} else
|
||||
{
|
||||
canvas.drawText(day, r.centerX(), r.bottom + lineHeight * 1.2f, pText);
|
||||
}
|
||||
|
||||
previousMonth = month;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void drawGrid(Canvas canvas, RectF rGrid)
|
||||
{
|
||||
// pGrid.setColor(Color.rgb(230, 230, 230));
|
||||
// pGrid.setStyle(Paint.Style.STROKE);
|
||||
// canvas.drawRect(rGrid, pGrid);
|
||||
|
||||
int nRows = 5;
|
||||
float rowHeight = rGrid.height() / nRows;
|
||||
|
||||
pGrid.setColor(Color.rgb(240, 240, 240));
|
||||
for (int i = 0; i < nRows; i++)
|
||||
{
|
||||
canvas.drawText(String.format("%d%%", (100 - i * 100 / nRows)), rGrid.left + 0.5f * em,
|
||||
rGrid.top + 1f * em, pText);
|
||||
canvas.drawLine(rGrid.left, rGrid.top, rGrid.right, rGrid.top, pGrid);
|
||||
rGrid.offset(0, rowHeight);
|
||||
}
|
||||
|
||||
canvas.drawLine(rGrid.left, rGrid.top, rGrid.right, rGrid.top, pGrid);
|
||||
}
|
||||
|
||||
private void drawLine(Canvas canvas, RectF rectFrom, RectF rectTo)
|
||||
{
|
||||
pGraph.setColor(habit.color);
|
||||
canvas.drawLine(rectFrom.centerX(), rectFrom.centerY(), rectTo.centerX(), rectTo.centerY(),
|
||||
pGraph);
|
||||
}
|
||||
|
||||
private void drawMarker(Canvas canvas, RectF rect)
|
||||
{
|
||||
rect.inset(columnWidth * 0.15f, columnWidth * 0.15f);
|
||||
pGraph.setColor(Color.WHITE);
|
||||
canvas.drawOval(rect, pGraph);
|
||||
|
||||
rect.inset(columnWidth * 0.1f, columnWidth * 0.1f);
|
||||
pGraph.setColor(habit.color);
|
||||
canvas.drawOval(rect, pGraph);
|
||||
|
||||
rect.inset(columnWidth * 0.1f, columnWidth * 0.1f);
|
||||
pGraph.setColor(Color.WHITE);
|
||||
canvas.drawOval(rect, pGraph);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event)
|
||||
{
|
||||
int action = event.getAction();
|
||||
|
||||
int pointerIndex = MotionEventCompat.getActionIndex(event);
|
||||
final float x = MotionEventCompat.getX(event, pointerIndex);
|
||||
final float y = MotionEventCompat.getY(event, pointerIndex);
|
||||
|
||||
if (action == MotionEvent.ACTION_DOWN)
|
||||
{
|
||||
prevX = x;
|
||||
prevY = y;
|
||||
}
|
||||
|
||||
if (action == MotionEvent.ACTION_MOVE)
|
||||
{
|
||||
float dx = x - prevX;
|
||||
float dy = y - prevY;
|
||||
|
||||
if (Math.abs(dy) > Math.abs(dx)) return false;
|
||||
getParent().requestDisallowInterceptTouchEvent(true);
|
||||
if (move(dx))
|
||||
{
|
||||
prevX = x;
|
||||
prevY = y;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean move(float dx)
|
||||
{
|
||||
int newDataOffset = dataOffset + (int) (dx / columnWidth);
|
||||
newDataOffset = Math.max(0, newDataOffset);
|
||||
|
||||
if (newDataOffset != dataOffset)
|
||||
{
|
||||
dataOffset = newDataOffset;
|
||||
fetchScores();
|
||||
invalidate();
|
||||
return true;
|
||||
} else return false;
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 5.4 KiB |
Before Width: | Height: | Size: 9.2 KiB |
After Width: | Height: | Size: 344 B |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 7.1 KiB |
After Width: | Height: | Size: 11 KiB |
@ -1,20 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<style name="habitsListHeaderStyle">
|
||||
<item name="android:layout_width">match_parent</item>
|
||||
<item name="android:layout_height">wrap_content</item>
|
||||
<item name="android:layout_alignParentTop">true</item>
|
||||
<style name="habitsListHeaderStyle" parent="habitsListHeaderBasicStyle">
|
||||
<item name="android:background">#f0f0f0</item>
|
||||
<item name="android:elevation">2dp</item>
|
||||
<item name="android:paddingRight">4dp</item>
|
||||
</style>
|
||||
|
||||
<style name="habitsListCheckStyle">
|
||||
<item name="android:focusable">false</item>
|
||||
<item name="android:minHeight">42dp</item>
|
||||
<item name="android:minWidth">42dp</item>
|
||||
<item name="android:gravity">center</item>
|
||||
<style name="habitsListCheckStyle" parent="habitsListCheckBasicStyle">
|
||||
<item name="android:background">@drawable/ripple_background</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<declare-styleable name="DragSortListView">
|
||||
<attr name="collapsed_height" format="dimension"/>
|
||||
<attr name="drag_scroll_start" format="float"/>
|
||||
<attr name="max_drag_scroll_speed" format="float"/>
|
||||
<attr name="float_background_color" format="color"/>
|
||||
<attr name="remove_mode">
|
||||
<enum name="clickRemove" value="0"/>
|
||||
<enum name="flingRemove" value="1"/>
|
||||
</attr>
|
||||
<attr name="track_drag_sort" format="boolean"/>
|
||||
<attr name="float_alpha" format="float"/>
|
||||
<attr name="slide_shuffle_speed" format="float"/>
|
||||
<attr name="remove_animation_duration" format="integer"/>
|
||||
<attr name="drop_animation_duration" format="integer"/>
|
||||
<attr name="drag_enabled" format="boolean"/>
|
||||
<attr name="sort_enabled" format="boolean"/>
|
||||
<attr name="remove_enabled" format="boolean"/>
|
||||
<attr name="drag_start_mode">
|
||||
<enum name="onDown" value="0"/>
|
||||
<enum name="onMove" value="1"/>
|
||||
<enum name="onLongPress" value="2"/>
|
||||
</attr>
|
||||
<attr name="drag_handle_id" format="integer"/>
|
||||
<attr name="fling_handle_id" format="integer"/>
|
||||
<attr name="click_remove_id" format="integer"/>
|
||||
<attr name="use_default_controller" format="boolean"/>
|
||||
</declare-styleable>
|
||||
</resources>
|
@ -1,54 +1,6 @@
|
||||
<resources>
|
||||
|
||||
<!-- Default screen margins, per the Android Design guidelines. -->
|
||||
<dimen name="activity_horizontal_margin">16dp</dimen>
|
||||
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||
|
||||
<dimen name="square_size">20dp</dimen>
|
||||
|
||||
<!-- Color picker -->
|
||||
<dimen name="color_swatch_large">64dip</dimen>
|
||||
<dimen name="color_swatch_small">48dip</dimen>
|
||||
<dimen name="color_swatch_margins_large">8dip</dimen>
|
||||
<dimen name="color_swatch_margins_small">4dip</dimen>
|
||||
|
||||
<!-- Date and time picker -->
|
||||
<item name="circle_radius_multiplier" format="float" type="string">0.82</item>
|
||||
<item name="circle_radius_multiplier_24HourMode" format="float" type="string">0.85</item>
|
||||
<item name="selection_radius_multiplier" format="float" type="string">0.16</item>
|
||||
<item name="ampm_circle_radius_multiplier" format="float" type="string">0.19</item>
|
||||
<item name="numbers_radius_multiplier_normal" format="float" type="string">0.81</item>
|
||||
<item name="numbers_radius_multiplier_inner" format="float" type="string">0.60</item>
|
||||
<item name="numbers_radius_multiplier_outer" format="float" type="string">0.83</item>
|
||||
<item name="text_size_multiplier_normal" format="float" type="string">0.17</item>
|
||||
<item name="text_size_multiplier_inner" format="float" type="string">0.14</item>
|
||||
<item name="text_size_multiplier_outer" format="float" type="string">0.11</item>
|
||||
<dimen name="time_label_size">60sp</dimen>
|
||||
<dimen name="extra_time_label_margin">-30dp</dimen>
|
||||
<dimen name="ampm_label_size">16sp</dimen>
|
||||
<dimen name="done_label_size">14sp</dimen>
|
||||
<dimen name="ampm_left_padding">6dip</dimen>
|
||||
<dimen name="separator_padding">4dip</dimen>
|
||||
<dimen name="header_height">96dip</dimen>
|
||||
<dimen name="footer_height">48dip</dimen>
|
||||
<dimen name="minimum_margin_sides">48dip</dimen>
|
||||
<dimen name="minimum_margin_top_bottom">24dip</dimen>
|
||||
<dimen name="picker_dimen">270dip</dimen>
|
||||
<dimen name="date_picker_component_width">270dp</dimen>
|
||||
<dimen name="date_picker_header_height">30dp</dimen>
|
||||
<dimen name="selected_calendar_layout_height">155dp</dimen>
|
||||
<dimen name="date_picker_view_animator_height">270dp</dimen>
|
||||
<dimen name="done_button_height">42dp</dimen>
|
||||
<dimen name="month_list_item_header_height">50dp</dimen>
|
||||
<dimen name="month_day_label_text_size">10sp</dimen>
|
||||
<dimen name="day_number_select_circle_radius">16dp</dimen>
|
||||
<dimen name="month_select_circle_radius">45dp</dimen>
|
||||
<dimen name="selected_date_year_size">30dp</dimen>
|
||||
<dimen name="selected_date_day_size">75dp</dimen>
|
||||
<dimen name="selected_date_month_size">30dp</dimen>
|
||||
<dimen name="date_picker_header_text_size">14dp</dimen>
|
||||
<dimen name="month_label_size">16sp</dimen>
|
||||
<dimen name="day_number_size">16sp</dimen>
|
||||
<dimen name="year_label_height">64dp</dimen>
|
||||
<dimen name="year_label_text_size">22dp</dimen>
|
||||
<dimen name="small_square_size">20dp</dimen>
|
||||
<dimen name="check_square_size">42dp</dimen>
|
||||
</resources>
|
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<dimen name="color_swatch_large">64dip</dimen>
|
||||
<dimen name="color_swatch_small">48dip</dimen>
|
||||
<dimen name="color_swatch_margins_large">8dip</dimen>
|
||||
<dimen name="color_swatch_margins_small">4dip</dimen>
|
||||
</resources>
|
@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<item name="circle_radius_multiplier" format="float" type="string">0.82</item>
|
||||
<item name="circle_radius_multiplier_24HourMode" format="float" type="string">0.85</item>
|
||||
<item name="selection_radius_multiplier" format="float" type="string">0.16</item>
|
||||
<item name="ampm_circle_radius_multiplier" format="float" type="string">0.19</item>
|
||||
<item name="numbers_radius_multiplier_normal" format="float" type="string">0.81</item>
|
||||
<item name="numbers_radius_multiplier_inner" format="float" type="string">0.60</item>
|
||||
<item name="numbers_radius_multiplier_outer" format="float" type="string">0.83</item>
|
||||
<item name="text_size_multiplier_normal" format="float" type="string">0.17</item>
|
||||
<item name="text_size_multiplier_inner" format="float" type="string">0.14</item>
|
||||
<item name="text_size_multiplier_outer" format="float" type="string">0.11</item>
|
||||
|
||||
<dimen name="time_label_size">60sp</dimen>
|
||||
<dimen name="extra_time_label_margin">-30dp</dimen>
|
||||
<dimen name="ampm_label_size">16sp</dimen>
|
||||
<dimen name="done_label_size">14sp</dimen>
|
||||
<dimen name="ampm_left_padding">6dip</dimen>
|
||||
<dimen name="separator_padding">4dip</dimen>
|
||||
<dimen name="header_height">96dip</dimen>
|
||||
<dimen name="footer_height">48dip</dimen>
|
||||
<dimen name="minimum_margin_sides">48dip</dimen>
|
||||
<dimen name="minimum_margin_top_bottom">24dip</dimen>
|
||||
<dimen name="picker_dimen">270dip</dimen>
|
||||
<dimen name="date_picker_component_width">270dp</dimen>
|
||||
<dimen name="date_picker_header_height">30dp</dimen>
|
||||
<dimen name="selected_calendar_layout_height">155dp</dimen>
|
||||
<dimen name="date_picker_view_animator_height">270dp</dimen>
|
||||
<dimen name="done_button_height">42dp</dimen>
|
||||
<dimen name="month_list_item_header_height">50dp</dimen>
|
||||
<dimen name="month_day_label_text_size">10sp</dimen>
|
||||
<dimen name="day_number_select_circle_radius">16dp</dimen>
|
||||
<dimen name="month_select_circle_radius">45dp</dimen>
|
||||
<dimen name="selected_date_year_size">30dp</dimen>
|
||||
<dimen name="selected_date_day_size">75dp</dimen>
|
||||
<dimen name="selected_date_month_size">30dp</dimen>
|
||||
<dimen name="date_picker_header_text_size">14dp</dimen>
|
||||
<dimen name="month_label_size">16sp</dimen>
|
||||
<dimen name="day_number_size">16sp</dimen>
|
||||
<dimen name="year_label_height">64dp</dimen>
|
||||
<dimen name="year_label_text_size">22dp</dimen>
|
||||
</resources>
|