mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-06 01:08:50 -06:00
Refactor custom views; fix rendering issues
This commit is contained in:
@@ -28,7 +28,7 @@ import android.widget.RemoteViews;
|
|||||||
|
|
||||||
import org.isoron.helpers.DialogHelper;
|
import org.isoron.helpers.DialogHelper;
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.Habit;
|
||||||
import org.isoron.uhabits.views.HabitHistoryView;
|
import org.isoron.uhabits.views.HabitScoreView;
|
||||||
|
|
||||||
public class HabitWidgetProvider extends AppWidgetProvider
|
public class HabitWidgetProvider extends AppWidgetProvider
|
||||||
{
|
{
|
||||||
@@ -63,9 +63,10 @@ public class HabitWidgetProvider extends AppWidgetProvider
|
|||||||
Habit habit = Habit.get(habitId);
|
Habit habit = Habit.get(habitId);
|
||||||
|
|
||||||
// SmallWidgetView widgetView = new SmallWidgetView(context);
|
// SmallWidgetView widgetView = new SmallWidgetView(context);
|
||||||
HabitHistoryView widgetView = new HabitHistoryView(context, null);
|
// HabitHistoryView widgetView = new HabitHistoryView(context, null);
|
||||||
// HabitScoreView widgetView = new HabitScoreView(context, null);
|
HabitScoreView widgetView = new HabitScoreView(context, null);
|
||||||
// HabitStreakView widgetView = new HabitStreakView(context, null);
|
// HabitStreakView widgetView = new HabitStreakView(context, null);
|
||||||
|
widgetView.setIsBackgroundTransparent(true);
|
||||||
widgetView.setHabit(habit);
|
widgetView.setHabit(habit);
|
||||||
widgetView.setDrawingCacheEnabled(true);
|
widgetView.setDrawingCacheEnabled(true);
|
||||||
widgetView.measure(max_width, max_height);
|
widgetView.measure(max_width, max_height);
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ import android.util.AttributeSet;
|
|||||||
|
|
||||||
import org.isoron.helpers.ColorHelper;
|
import org.isoron.helpers.ColorHelper;
|
||||||
import org.isoron.helpers.DateHelper;
|
import org.isoron.helpers.DateHelper;
|
||||||
import org.isoron.uhabits.R;
|
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.Habit;
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
@@ -45,6 +44,11 @@ public class HabitHistoryView extends ScrollableDataView
|
|||||||
private float squareTextOffset;
|
private float squareTextOffset;
|
||||||
private float headerTextOffset;
|
private float headerTextOffset;
|
||||||
|
|
||||||
|
private int columnWidth;
|
||||||
|
private int columnHeight;
|
||||||
|
private int nColumns;
|
||||||
|
private int baseSize;
|
||||||
|
|
||||||
private String wdays[];
|
private String wdays[];
|
||||||
private SimpleDateFormat dfMonth;
|
private SimpleDateFormat dfMonth;
|
||||||
private SimpleDateFormat dfYear;
|
private SimpleDateFormat dfYear;
|
||||||
@@ -76,7 +80,6 @@ public class HabitHistoryView extends ScrollableDataView
|
|||||||
{
|
{
|
||||||
createPaints();
|
createPaints();
|
||||||
createColors();
|
createColors();
|
||||||
updateDimensions();
|
|
||||||
|
|
||||||
wdays = DateHelper.getShortDayNames();
|
wdays = DateHelper.getShortDayNames();
|
||||||
dfMonth = new SimpleDateFormat("MMM", Locale.getDefault());
|
dfMonth = new SimpleDateFormat("MMM", Locale.getDefault());
|
||||||
@@ -88,7 +91,7 @@ public class HabitHistoryView extends ScrollableDataView
|
|||||||
private void updateDate()
|
private void updateDate()
|
||||||
{
|
{
|
||||||
baseDate = new GregorianCalendar();
|
baseDate = new GregorianCalendar();
|
||||||
baseDate.add(Calendar.DAY_OF_YEAR, -(dataOffset - 1) * 7);
|
baseDate.add(Calendar.DAY_OF_YEAR, -(getDataOffset() - 1) * 7);
|
||||||
|
|
||||||
nDays = (nColumns - 1) * 7;
|
nDays = (nColumns - 1) * 7;
|
||||||
todayWeekday = new GregorianCalendar().get(Calendar.DAY_OF_WEEK) % 7;
|
todayWeekday = new GregorianCalendar().get(Calendar.DAY_OF_WEEK) % 7;
|
||||||
@@ -98,9 +101,34 @@ public class HabitHistoryView extends ScrollableDataView
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onSizeChanged(int w, int h, int oldw, int oldh)
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
|
||||||
{
|
{
|
||||||
super.onSizeChanged(w, h, oldw, oldh);
|
int width = MeasureSpec.getSize(widthMeasureSpec);
|
||||||
|
int height = MeasureSpec.getSize(heightMeasureSpec);
|
||||||
|
|
||||||
|
int b = height / 8;
|
||||||
|
height = b * 8;
|
||||||
|
width = (width / b) * b;
|
||||||
|
|
||||||
|
setMeasuredDimension(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight)
|
||||||
|
{
|
||||||
|
baseSize = height / 8;
|
||||||
|
setScrollerBucketSize(baseSize);
|
||||||
|
|
||||||
|
columnWidth = baseSize;
|
||||||
|
columnHeight = 8 * baseSize;
|
||||||
|
nColumns = width / baseSize;
|
||||||
|
|
||||||
|
squareSpacing = baseSize / 10;
|
||||||
|
pSquareFg.setTextSize(baseSize * 0.5f);
|
||||||
|
pTextHeader.setTextSize(baseSize * 0.5f);
|
||||||
|
squareTextOffset = pSquareFg.getFontSpacing() * 0.4f;
|
||||||
|
headerTextOffset = pTextHeader.getFontSpacing() * 0.3f;
|
||||||
|
|
||||||
updateDate();
|
updateDate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,15 +144,6 @@ public class HabitHistoryView extends ScrollableDataView
|
|||||||
colors[2] = primaryColor;
|
colors[2] = primaryColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void updateDimensions()
|
|
||||||
{
|
|
||||||
squareSpacing = columnWidth / 10;
|
|
||||||
pSquareFg.setTextSize(columnWidth * 0.5f);
|
|
||||||
pTextHeader.setTextSize(columnWidth * 0.5f);
|
|
||||||
squareTextOffset = pSquareFg.getFontSpacing() * 0.4f;
|
|
||||||
headerTextOffset = pTextHeader.getFontSpacing() * 0.3f;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void createPaints()
|
protected void createPaints()
|
||||||
{
|
{
|
||||||
pTextHeader = new Paint();
|
pTextHeader = new Paint();
|
||||||
@@ -212,9 +231,9 @@ public class HabitHistoryView extends ScrollableDataView
|
|||||||
|
|
||||||
for (int j = 0; j < 7; j++)
|
for (int j = 0; j < 7; j++)
|
||||||
{
|
{
|
||||||
if (!(column == nColumns - 2 && dataOffset == 0 && j > todayWeekday))
|
if (!(column == nColumns - 2 && getDataOffset() == 0 && j > todayWeekday))
|
||||||
{
|
{
|
||||||
int checkmarkOffset = dataOffset * 7 + nDays - 7 * (column + 1) + todayWeekday - j;
|
int checkmarkOffset = getDataOffset() * 7 + nDays - 7 * (column + 1) + todayWeekday - j;
|
||||||
drawSquare(canvas, location, date, checkmarkOffset);
|
drawSquare(canvas, location, date, checkmarkOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ import android.util.AttributeSet;
|
|||||||
|
|
||||||
import org.isoron.helpers.ColorHelper;
|
import org.isoron.helpers.ColorHelper;
|
||||||
import org.isoron.helpers.DateHelper;
|
import org.isoron.helpers.DateHelper;
|
||||||
import org.isoron.uhabits.R;
|
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.Habit;
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
@@ -37,6 +36,10 @@ import java.util.Random;
|
|||||||
public class HabitScoreView extends ScrollableDataView
|
public class HabitScoreView extends ScrollableDataView
|
||||||
{
|
{
|
||||||
public static final int BUCKET_SIZE = 7;
|
public static final int BUCKET_SIZE = 7;
|
||||||
|
public static final PorterDuffXfermode XFERMODE_CLEAR =
|
||||||
|
new PorterDuffXfermode(PorterDuff.Mode.CLEAR);
|
||||||
|
public static final PorterDuffXfermode XFERMODE_SRC =
|
||||||
|
new PorterDuffXfermode(PorterDuff.Mode.SRC);
|
||||||
|
|
||||||
private Paint pGrid;
|
private Paint pGrid;
|
||||||
private float em;
|
private float em;
|
||||||
@@ -48,14 +51,18 @@ public class HabitScoreView extends ScrollableDataView
|
|||||||
private RectF rect, prevRect;
|
private RectF rect, prevRect;
|
||||||
private int baseSize;
|
private int baseSize;
|
||||||
|
|
||||||
|
private int columnWidth;
|
||||||
|
private int columnHeight;
|
||||||
|
private int nColumns;
|
||||||
|
|
||||||
private int[] colors;
|
private int[] colors;
|
||||||
private int[] scores;
|
private int[] scores;
|
||||||
private int primaryColor;
|
private int primaryColor;
|
||||||
|
private boolean isBackgroundTransparent;
|
||||||
|
|
||||||
public HabitScoreView(Context context, AttributeSet attrs)
|
public HabitScoreView(Context context, AttributeSet attrs)
|
||||||
{
|
{
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
this.baseSize = (int) context.getResources().getDimension(R.dimen.small_square_size);
|
|
||||||
this.primaryColor = ColorHelper.palette[7];
|
this.primaryColor = ColorHelper.palette[7];
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
@@ -72,7 +79,6 @@ public class HabitScoreView extends ScrollableDataView
|
|||||||
{
|
{
|
||||||
createPaints();
|
createPaints();
|
||||||
createColors();
|
createColors();
|
||||||
updateDimensions();
|
|
||||||
|
|
||||||
dfMonth = new SimpleDateFormat("MMM", Locale.getDefault());
|
dfMonth = new SimpleDateFormat("MMM", Locale.getDefault());
|
||||||
dfDay = new SimpleDateFormat("d", Locale.getDefault());
|
dfDay = new SimpleDateFormat("d", Locale.getDefault());
|
||||||
@@ -109,18 +115,33 @@ public class HabitScoreView extends ScrollableDataView
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void updateDimensions()
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
|
||||||
{
|
{
|
||||||
this.columnWidth = baseSize;
|
int width = MeasureSpec.getSize(widthMeasureSpec);
|
||||||
|
int height = MeasureSpec.getSize(heightMeasureSpec);
|
||||||
|
|
||||||
|
int b = height / 9;
|
||||||
|
height = b * 9;
|
||||||
|
width = (width / b) * b;
|
||||||
|
|
||||||
|
setMeasuredDimension(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight)
|
||||||
|
{
|
||||||
|
baseSize = height / 9;
|
||||||
|
setScrollerBucketSize(baseSize);
|
||||||
|
|
||||||
|
columnWidth = baseSize;
|
||||||
columnHeight = 8 * baseSize;
|
columnHeight = 8 * baseSize;
|
||||||
headerHeight = baseSize;
|
nColumns = width / baseSize;
|
||||||
footerHeight = baseSize;
|
|
||||||
em = pText.getFontSpacing();
|
|
||||||
|
|
||||||
pText.setTextSize(baseSize * 0.5f);
|
pText.setTextSize(baseSize * 0.5f);
|
||||||
pGraph.setTextSize(baseSize * 0.5f);
|
pGraph.setTextSize(baseSize * 0.5f);
|
||||||
pGraph.setStrokeWidth(baseSize * 0.1f);
|
pGraph.setStrokeWidth(baseSize * 0.1f);
|
||||||
pGrid.setStrokeWidth(baseSize * 0.05f);
|
pGrid.setStrokeWidth(baseSize * 0.05f);
|
||||||
|
em = pText.getFontSpacing();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void fetchData()
|
protected void fetchData()
|
||||||
@@ -162,7 +183,6 @@ public class HabitScoreView extends ScrollableDataView
|
|||||||
float lineHeight = pText.getFontSpacing();
|
float lineHeight = pText.getFontSpacing();
|
||||||
|
|
||||||
rect.set(0, 0, nColumns * columnWidth, columnHeight);
|
rect.set(0, 0, nColumns * columnWidth, columnHeight);
|
||||||
rect.offset(0, headerHeight);
|
|
||||||
drawGrid(canvas, rect);
|
drawGrid(canvas, rect);
|
||||||
|
|
||||||
String previousMonth = "";
|
String previousMonth = "";
|
||||||
@@ -172,7 +192,7 @@ public class HabitScoreView extends ScrollableDataView
|
|||||||
|
|
||||||
long currentDate = DateHelper.getStartOfToday();
|
long currentDate = DateHelper.getStartOfToday();
|
||||||
|
|
||||||
for(int k = 0; k < nColumns + dataOffset - 1; k++)
|
for(int k = 0; k < nColumns + getDataOffset() - 1; k++)
|
||||||
currentDate -= 7 * DateHelper.millisecondsInOneDay;
|
currentDate -= 7 * DateHelper.millisecondsInOneDay;
|
||||||
|
|
||||||
for (int k = 0; k < nColumns; k++)
|
for (int k = 0; k < nColumns; k++)
|
||||||
@@ -181,15 +201,14 @@ public class HabitScoreView extends ScrollableDataView
|
|||||||
String day = dfDay.format(currentDate);
|
String day = dfDay.format(currentDate);
|
||||||
|
|
||||||
int score = 0;
|
int score = 0;
|
||||||
int offset = nColumns - k - 1 + dataOffset;
|
int offset = nColumns - k - 1 + getDataOffset();
|
||||||
if(offset < scores.length) score = scores[offset];
|
if(offset < scores.length) score = scores[offset];
|
||||||
|
|
||||||
double sRelative = ((double) score) / Habit.MAX_SCORE;
|
double sRelative = ((double) score) / Habit.MAX_SCORE;
|
||||||
int height = (int) (columnHeight * sRelative);
|
int height = (int) (columnHeight * sRelative);
|
||||||
|
|
||||||
rect.set(0, 0, columnWidth, columnWidth);
|
rect.set(0, 0, baseSize, baseSize);
|
||||||
rect.offset(k * columnWidth,
|
rect.offset(k * columnWidth, columnHeight - height - columnWidth / 2);
|
||||||
headerHeight + columnHeight - height - columnWidth / 2);
|
|
||||||
|
|
||||||
if (!prevRect.isEmpty())
|
if (!prevRect.isEmpty())
|
||||||
{
|
{
|
||||||
@@ -202,7 +221,7 @@ public class HabitScoreView extends ScrollableDataView
|
|||||||
prevRect.set(rect);
|
prevRect.set(rect);
|
||||||
|
|
||||||
rect.set(0, 0, columnWidth, columnHeight);
|
rect.set(0, 0, columnWidth, columnHeight);
|
||||||
rect.offset(k * columnWidth, headerHeight);
|
rect.offset(k * columnWidth, 0);
|
||||||
if (!month.equals(previousMonth))
|
if (!month.equals(previousMonth))
|
||||||
canvas.drawText(month, rect.centerX(), rect.bottom + lineHeight * 1.2f, pText);
|
canvas.drawText(month, rect.centerX(), rect.bottom + lineHeight * 1.2f, pText);
|
||||||
else
|
else
|
||||||
@@ -240,18 +259,31 @@ public class HabitScoreView extends ScrollableDataView
|
|||||||
private void drawMarker(Canvas canvas, RectF rect)
|
private void drawMarker(Canvas canvas, RectF rect)
|
||||||
{
|
{
|
||||||
rect.inset(columnWidth * 0.15f, columnWidth * 0.15f);
|
rect.inset(columnWidth * 0.15f, columnWidth * 0.15f);
|
||||||
pGraph.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
|
setModeOrColor(pGraph, XFERMODE_CLEAR, Color.WHITE);
|
||||||
canvas.drawOval(rect, pGraph);
|
canvas.drawOval(rect, pGraph);
|
||||||
|
|
||||||
rect.inset(columnWidth * 0.1f, columnWidth * 0.1f);
|
rect.inset(columnWidth * 0.1f, columnWidth * 0.1f);
|
||||||
pGraph.setColor(primaryColor);
|
setModeOrColor(pGraph, XFERMODE_SRC, primaryColor);
|
||||||
pGraph.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
|
|
||||||
canvas.drawOval(rect, pGraph);
|
canvas.drawOval(rect, pGraph);
|
||||||
|
|
||||||
rect.inset(columnWidth * 0.1f, columnWidth * 0.1f);
|
rect.inset(columnWidth * 0.1f, columnWidth * 0.1f);
|
||||||
pGraph.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
|
setModeOrColor(pGraph, XFERMODE_CLEAR, Color.WHITE);
|
||||||
canvas.drawOval(rect, pGraph);
|
canvas.drawOval(rect, pGraph);
|
||||||
|
|
||||||
pGraph.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
|
if(isBackgroundTransparent)
|
||||||
|
pGraph.setXfermode(XFERMODE_SRC);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsBackgroundTransparent(boolean isBackgroundTransparent)
|
||||||
|
{
|
||||||
|
this.isBackgroundTransparent = isBackgroundTransparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setModeOrColor(Paint p, PorterDuffXfermode mode, int color)
|
||||||
|
{
|
||||||
|
if(isBackgroundTransparent)
|
||||||
|
p.setXfermode(mode);
|
||||||
|
else
|
||||||
|
p.setColor(color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,11 @@ public class HabitStreakView extends ScrollableDataView
|
|||||||
private long[] endTimes;
|
private long[] endTimes;
|
||||||
private long[] lengths;
|
private long[] lengths;
|
||||||
|
|
||||||
|
private int columnWidth;
|
||||||
|
private int columnHeight;
|
||||||
|
private int headerHeight;
|
||||||
|
private int nColumns;
|
||||||
|
|
||||||
private long maxStreakLength;
|
private long maxStreakLength;
|
||||||
private int[] colors;
|
private int[] colors;
|
||||||
private SimpleDateFormat dfMonth;
|
private SimpleDateFormat dfMonth;
|
||||||
@@ -53,7 +58,6 @@ public class HabitStreakView extends ScrollableDataView
|
|||||||
public HabitStreakView(Context context, AttributeSet attrs)
|
public HabitStreakView(Context context, AttributeSet attrs)
|
||||||
{
|
{
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
this.baseSize = (int) context.getResources().getDimension(R.dimen.small_square_size);
|
|
||||||
this.primaryColor = ColorHelper.palette[7];
|
this.primaryColor = ColorHelper.palette[7];
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
@@ -62,6 +66,7 @@ public class HabitStreakView extends ScrollableDataView
|
|||||||
{
|
{
|
||||||
this.habit = habit;
|
this.habit = habit;
|
||||||
this.primaryColor = habit.color;
|
this.primaryColor = habit.color;
|
||||||
|
|
||||||
createColors();
|
createColors();
|
||||||
fetchData();
|
fetchData();
|
||||||
postInvalidate();
|
postInvalidate();
|
||||||
@@ -69,7 +74,6 @@ public class HabitStreakView extends ScrollableDataView
|
|||||||
|
|
||||||
private void init()
|
private void init()
|
||||||
{
|
{
|
||||||
setDimensions(baseSize);
|
|
||||||
createPaints();
|
createPaints();
|
||||||
createColors();
|
createColors();
|
||||||
|
|
||||||
@@ -77,12 +81,32 @@ public class HabitStreakView extends ScrollableDataView
|
|||||||
rect = new Rect();
|
rect = new Rect();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setDimensions(int baseSize)
|
@Override
|
||||||
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
|
||||||
{
|
{
|
||||||
this.columnWidth = baseSize;
|
int width = MeasureSpec.getSize(widthMeasureSpec);
|
||||||
|
int height = MeasureSpec.getSize(heightMeasureSpec);
|
||||||
|
|
||||||
|
int b = height / 10;
|
||||||
|
height = b * 10;
|
||||||
|
width = (width / b) * b;
|
||||||
|
|
||||||
|
setMeasuredDimension(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight)
|
||||||
|
{
|
||||||
|
baseSize = height / 10;
|
||||||
|
setScrollerBucketSize(baseSize);
|
||||||
|
|
||||||
|
columnWidth = baseSize;
|
||||||
columnHeight = 8 * baseSize;
|
columnHeight = 8 * baseSize;
|
||||||
headerHeight = baseSize;
|
headerHeight = baseSize;
|
||||||
footerHeight = baseSize;
|
nColumns = width / baseSize;
|
||||||
|
|
||||||
|
pText.setTextSize(baseSize * 0.5f);
|
||||||
|
pBar.setTextSize(baseSize * 0.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createColors()
|
private void createColors()
|
||||||
@@ -91,8 +115,8 @@ public class HabitStreakView extends ScrollableDataView
|
|||||||
colors[3] = primaryColor;
|
colors[3] = primaryColor;
|
||||||
colors[1] = Color.argb(80, Color.red(primaryColor), Color.green(primaryColor), Color.blue(
|
colors[1] = Color.argb(80, Color.red(primaryColor), Color.green(primaryColor), Color.blue(
|
||||||
primaryColor));
|
primaryColor));
|
||||||
colors[2] = Color.argb(170, Color.red(primaryColor), Color.green(primaryColor), Color.blue(
|
colors[2] = Color.argb(170, Color.red(primaryColor), Color.green(primaryColor),
|
||||||
primaryColor));
|
Color.blue(primaryColor));
|
||||||
colors[0] = Color.argb(30, 0, 0, 0);
|
colors[0] = Color.argb(30, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,12 +125,10 @@ public class HabitStreakView extends ScrollableDataView
|
|||||||
pText = new Paint();
|
pText = new Paint();
|
||||||
pText.setColor(Color.LTGRAY);
|
pText.setColor(Color.LTGRAY);
|
||||||
pText.setTextAlign(Paint.Align.CENTER);
|
pText.setTextAlign(Paint.Align.CENTER);
|
||||||
pText.setTextSize(columnWidth * 0.5f);
|
|
||||||
pText.setAntiAlias(true);
|
pText.setAntiAlias(true);
|
||||||
|
|
||||||
pBar = new Paint();
|
pBar = new Paint();
|
||||||
pBar.setTextAlign(Paint.Align.CENTER);
|
pBar.setTextAlign(Paint.Align.CENTER);
|
||||||
pBar.setTextSize(columnWidth * 0.5f);
|
|
||||||
pBar.setAntiAlias(true);
|
pBar.setAntiAlias(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,7 +197,7 @@ public class HabitStreakView extends ScrollableDataView
|
|||||||
float barHeaderOffset = lineHeight * 0.4f;
|
float barHeaderOffset = lineHeight * 0.4f;
|
||||||
|
|
||||||
int nStreaks = startTimes.length;
|
int nStreaks = startTimes.length;
|
||||||
int start = nStreaks - nColumns - dataOffset;
|
int start = nStreaks - nColumns - getDataOffset();
|
||||||
|
|
||||||
String previousMonth = "";
|
String previousMonth = "";
|
||||||
|
|
||||||
|
|||||||
@@ -22,22 +22,17 @@ package org.isoron.uhabits.views;
|
|||||||
import android.animation.ValueAnimator;
|
import android.animation.ValueAnimator;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.GestureDetector;
|
import android.view.GestureDetector;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Scroller;
|
import android.widget.Scroller;
|
||||||
|
|
||||||
import org.isoron.uhabits.R;
|
|
||||||
|
|
||||||
public abstract class ScrollableDataView extends View implements GestureDetector.OnGestureListener,
|
public abstract class ScrollableDataView extends View implements GestureDetector.OnGestureListener,
|
||||||
ValueAnimator.AnimatorUpdateListener
|
ValueAnimator.AnimatorUpdateListener
|
||||||
{
|
{
|
||||||
|
|
||||||
protected int dataOffset;
|
private int dataOffset;
|
||||||
protected int nColumns, nRows;
|
private int scrollerBucketSize;
|
||||||
protected int columnWidth, columnHeight;
|
|
||||||
protected int headerHeight, footerHeight;
|
|
||||||
|
|
||||||
private GestureDetector detector;
|
private GestureDetector detector;
|
||||||
private Scroller scroller;
|
private Scroller scroller;
|
||||||
@@ -57,7 +52,6 @@ public abstract class ScrollableDataView extends View implements GestureDetector
|
|||||||
|
|
||||||
private void init(Context context)
|
private void init(Context context)
|
||||||
{
|
{
|
||||||
this.columnWidth = (int) context.getResources().getDimension(R.dimen.small_square_size);
|
|
||||||
detector = new GestureDetector(context, this);
|
detector = new GestureDetector(context, this);
|
||||||
scroller = new Scroller(context, null, true);
|
scroller = new Scroller(context, null, true);
|
||||||
scrollAnimator = ValueAnimator.ofFloat(0, 1);
|
scrollAnimator = ValueAnimator.ofFloat(0, 1);
|
||||||
@@ -72,39 +66,6 @@ public abstract class ScrollableDataView extends View implements GestureDetector
|
|||||||
return detector.onTouchEvent(event);
|
return detector.onTouchEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
|
|
||||||
{
|
|
||||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
|
||||||
|
|
||||||
int width = MeasureSpec.getSize(widthMeasureSpec);
|
|
||||||
int height = MeasureSpec.getSize(heightMeasureSpec);
|
|
||||||
|
|
||||||
Log.d("ScrollableDataView", String.format("onMeasure width=%d height=%d", width, height));
|
|
||||||
|
|
||||||
columnWidth = height / 8;
|
|
||||||
columnHeight = columnWidth * 8 + footerHeight + headerHeight;
|
|
||||||
|
|
||||||
height = columnHeight;
|
|
||||||
width = (width / columnWidth) * columnWidth;
|
|
||||||
|
|
||||||
setMeasuredDimension(width, height);
|
|
||||||
updateDimensions();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void updateDimensions()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onSizeChanged(int w, int h, int oldw, int oldh)
|
|
||||||
{
|
|
||||||
super.onSizeChanged(w, h, oldw, oldh);
|
|
||||||
nColumns = w / columnWidth;
|
|
||||||
fetchData();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onDown(MotionEvent e)
|
public boolean onDown(MotionEvent e)
|
||||||
{
|
{
|
||||||
@@ -126,13 +87,17 @@ public abstract class ScrollableDataView extends View implements GestureDetector
|
|||||||
@Override
|
@Override
|
||||||
public boolean onScroll(MotionEvent e1, MotionEvent e2, float dx, float dy)
|
public boolean onScroll(MotionEvent e1, MotionEvent e2, float dx, float dy)
|
||||||
{
|
{
|
||||||
|
if(scrollerBucketSize == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
if(Math.abs(dx) > Math.abs(dy))
|
if(Math.abs(dx) > Math.abs(dy))
|
||||||
getParent().requestDisallowInterceptTouchEvent(true);
|
getParent().requestDisallowInterceptTouchEvent(true);
|
||||||
|
|
||||||
scroller.startScroll(scroller.getCurrX(), scroller.getCurrY(), (int) -dx, (int) dy, 0);
|
scroller.startScroll(scroller.getCurrX(), scroller.getCurrY(), (int) -dx, (int) dy, 0);
|
||||||
scroller.computeScrollOffset();
|
scroller.computeScrollOffset();
|
||||||
dataOffset = Math.max(0, scroller.getCurrX() / columnWidth);
|
dataOffset = Math.max(0, scroller.getCurrX() / scrollerBucketSize);
|
||||||
postInvalidate();
|
postInvalidate();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,7 +126,7 @@ public abstract class ScrollableDataView extends View implements GestureDetector
|
|||||||
if (!scroller.isFinished())
|
if (!scroller.isFinished())
|
||||||
{
|
{
|
||||||
scroller.computeScrollOffset();
|
scroller.computeScrollOffset();
|
||||||
dataOffset = Math.max(0, scroller.getCurrX() / columnWidth);
|
dataOffset = Math.max(0, scroller.getCurrX() / scrollerBucketSize);
|
||||||
postInvalidate();
|
postInvalidate();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -169,4 +134,14 @@ public abstract class ScrollableDataView extends View implements GestureDetector
|
|||||||
scrollAnimator.cancel();
|
scrollAnimator.cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getDataOffset()
|
||||||
|
{
|
||||||
|
return dataOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setScrollerBucketSize(int scrollerBucketSize)
|
||||||
|
{
|
||||||
|
this.scrollerBucketSize = scrollerBucketSize;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,6 @@
|
|||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:shape="rectangle">
|
android:shape="rectangle">
|
||||||
|
|
||||||
<solid android:color="#30000000" />
|
<solid android:color="#7f000000" />
|
||||||
<corners android:radius="10dp" />
|
<corners android:radius="10dp" />
|
||||||
</shape>
|
</shape>
|
||||||
@@ -11,7 +11,6 @@
|
|||||||
tools:context="org.isoron.uhabits.ShowHabitActivity">
|
tools:context="org.isoron.uhabits.ShowHabitActivity">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/llOverview"
|
|
||||||
style="@style/cardStyle"
|
style="@style/cardStyle"
|
||||||
android:gravity="center">
|
android:gravity="center">
|
||||||
|
|
||||||
@@ -28,10 +27,7 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout style="@style/cardStyle">
|
||||||
android:id="@+id/llStrength"
|
|
||||||
style="@style/cardStyle"
|
|
||||||
android:gravity="center">
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvStrength"
|
android:id="@+id/tvStrength"
|
||||||
@@ -41,7 +37,7 @@
|
|||||||
<org.isoron.uhabits.views.HabitScoreView
|
<org.isoron.uhabits.views.HabitScoreView
|
||||||
android:id="@+id/scoreView"
|
android:id="@+id/scoreView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="180dp"/>
|
android:layout_height="200dp"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@@ -81,7 +77,7 @@
|
|||||||
<org.isoron.uhabits.views.HabitStreakView
|
<org.isoron.uhabits.views.HabitStreakView
|
||||||
android:id="@+id/streakView"
|
android:id="@+id/streakView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="180dp"/>
|
android:layout_height="200dp"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
Reference in New Issue
Block a user