diff --git a/app/src/main/java/org/isoron/uhabits/HabitWidgetProvider.java b/app/src/main/java/org/isoron/uhabits/HabitWidgetProvider.java index d062f3b63..cc8ab43f1 100644 --- a/app/src/main/java/org/isoron/uhabits/HabitWidgetProvider.java +++ b/app/src/main/java/org/isoron/uhabits/HabitWidgetProvider.java @@ -28,7 +28,7 @@ import android.widget.RemoteViews; import org.isoron.helpers.DialogHelper; import org.isoron.uhabits.models.Habit; -import org.isoron.uhabits.views.HabitHistoryView; +import org.isoron.uhabits.views.HabitScoreView; public class HabitWidgetProvider extends AppWidgetProvider { @@ -63,9 +63,10 @@ public class HabitWidgetProvider extends AppWidgetProvider Habit habit = Habit.get(habitId); // SmallWidgetView widgetView = new SmallWidgetView(context); - HabitHistoryView widgetView = new HabitHistoryView(context, null); -// HabitScoreView widgetView = new HabitScoreView(context, null); +// HabitHistoryView widgetView = new HabitHistoryView(context, null); + HabitScoreView widgetView = new HabitScoreView(context, null); // HabitStreakView widgetView = new HabitStreakView(context, null); + widgetView.setIsBackgroundTransparent(true); widgetView.setHabit(habit); widgetView.setDrawingCacheEnabled(true); widgetView.measure(max_width, max_height); diff --git a/app/src/main/java/org/isoron/uhabits/views/HabitHistoryView.java b/app/src/main/java/org/isoron/uhabits/views/HabitHistoryView.java index e9b0a4f33..40252b1ef 100644 --- a/app/src/main/java/org/isoron/uhabits/views/HabitHistoryView.java +++ b/app/src/main/java/org/isoron/uhabits/views/HabitHistoryView.java @@ -26,7 +26,6 @@ import android.util.AttributeSet; 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; @@ -45,6 +44,11 @@ public class HabitHistoryView extends ScrollableDataView private float squareTextOffset; private float headerTextOffset; + private int columnWidth; + private int columnHeight; + private int nColumns; + private int baseSize; + private String wdays[]; private SimpleDateFormat dfMonth; private SimpleDateFormat dfYear; @@ -76,7 +80,6 @@ public class HabitHistoryView extends ScrollableDataView { createPaints(); createColors(); - updateDimensions(); wdays = DateHelper.getShortDayNames(); dfMonth = new SimpleDateFormat("MMM", Locale.getDefault()); @@ -88,7 +91,7 @@ public class HabitHistoryView extends ScrollableDataView private void updateDate() { 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; todayWeekday = new GregorianCalendar().get(Calendar.DAY_OF_WEEK) % 7; @@ -98,9 +101,34 @@ public class HabitHistoryView extends ScrollableDataView } @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(); } @@ -116,15 +144,6 @@ public class HabitHistoryView extends ScrollableDataView 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() { pTextHeader = new Paint(); @@ -212,9 +231,9 @@ public class HabitHistoryView extends ScrollableDataView 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); } diff --git a/app/src/main/java/org/isoron/uhabits/views/HabitScoreView.java b/app/src/main/java/org/isoron/uhabits/views/HabitScoreView.java index ddab70d7a..87ff35083 100644 --- a/app/src/main/java/org/isoron/uhabits/views/HabitScoreView.java +++ b/app/src/main/java/org/isoron/uhabits/views/HabitScoreView.java @@ -27,7 +27,6 @@ import android.util.AttributeSet; 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; @@ -37,6 +36,10 @@ import java.util.Random; public class HabitScoreView extends ScrollableDataView { 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 float em; @@ -48,14 +51,18 @@ public class HabitScoreView extends ScrollableDataView private RectF rect, prevRect; private int baseSize; + private int columnWidth; + private int columnHeight; + private int nColumns; + private int[] colors; private int[] scores; private int primaryColor; + private boolean isBackgroundTransparent; public HabitScoreView(Context context, AttributeSet attrs) { super(context, attrs); - this.baseSize = (int) context.getResources().getDimension(R.dimen.small_square_size); this.primaryColor = ColorHelper.palette[7]; init(); } @@ -72,7 +79,6 @@ public class HabitScoreView extends ScrollableDataView { createPaints(); createColors(); - updateDimensions(); dfMonth = new SimpleDateFormat("MMM", Locale.getDefault()); dfDay = new SimpleDateFormat("d", Locale.getDefault()); @@ -109,18 +115,33 @@ public class HabitScoreView extends ScrollableDataView } @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; - headerHeight = baseSize; - footerHeight = baseSize; - em = pText.getFontSpacing(); + nColumns = width / baseSize; pText.setTextSize(baseSize * 0.5f); pGraph.setTextSize(baseSize * 0.5f); pGraph.setStrokeWidth(baseSize * 0.1f); pGrid.setStrokeWidth(baseSize * 0.05f); + em = pText.getFontSpacing(); } protected void fetchData() @@ -162,7 +183,6 @@ public class HabitScoreView extends ScrollableDataView float lineHeight = pText.getFontSpacing(); rect.set(0, 0, nColumns * columnWidth, columnHeight); - rect.offset(0, headerHeight); drawGrid(canvas, rect); String previousMonth = ""; @@ -172,7 +192,7 @@ public class HabitScoreView extends ScrollableDataView 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; for (int k = 0; k < nColumns; k++) @@ -181,15 +201,14 @@ public class HabitScoreView extends ScrollableDataView String day = dfDay.format(currentDate); int score = 0; - int offset = nColumns - k - 1 + dataOffset; + int offset = nColumns - k - 1 + getDataOffset(); if(offset < scores.length) score = scores[offset]; double sRelative = ((double) score) / Habit.MAX_SCORE; int height = (int) (columnHeight * sRelative); - rect.set(0, 0, columnWidth, columnWidth); - rect.offset(k * columnWidth, - headerHeight + columnHeight - height - columnWidth / 2); + rect.set(0, 0, baseSize, baseSize); + rect.offset(k * columnWidth, columnHeight - height - columnWidth / 2); if (!prevRect.isEmpty()) { @@ -202,7 +221,7 @@ public class HabitScoreView extends ScrollableDataView prevRect.set(rect); rect.set(0, 0, columnWidth, columnHeight); - rect.offset(k * columnWidth, headerHeight); + rect.offset(k * columnWidth, 0); if (!month.equals(previousMonth)) canvas.drawText(month, rect.centerX(), rect.bottom + lineHeight * 1.2f, pText); else @@ -240,18 +259,31 @@ public class HabitScoreView extends ScrollableDataView private void drawMarker(Canvas canvas, RectF rect) { 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); rect.inset(columnWidth * 0.1f, columnWidth * 0.1f); - pGraph.setColor(primaryColor); - pGraph.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC)); + setModeOrColor(pGraph, XFERMODE_SRC, primaryColor); canvas.drawOval(rect, pGraph); 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); - 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); } } diff --git a/app/src/main/java/org/isoron/uhabits/views/HabitStreakView.java b/app/src/main/java/org/isoron/uhabits/views/HabitStreakView.java index 96f83fd04..453ac4879 100644 --- a/app/src/main/java/org/isoron/uhabits/views/HabitStreakView.java +++ b/app/src/main/java/org/isoron/uhabits/views/HabitStreakView.java @@ -43,6 +43,11 @@ public class HabitStreakView extends ScrollableDataView private long[] endTimes; private long[] lengths; + private int columnWidth; + private int columnHeight; + private int headerHeight; + private int nColumns; + private long maxStreakLength; private int[] colors; private SimpleDateFormat dfMonth; @@ -53,7 +58,6 @@ public class HabitStreakView extends ScrollableDataView public HabitStreakView(Context context, AttributeSet attrs) { super(context, attrs); - this.baseSize = (int) context.getResources().getDimension(R.dimen.small_square_size); this.primaryColor = ColorHelper.palette[7]; init(); } @@ -62,6 +66,7 @@ public class HabitStreakView extends ScrollableDataView { this.habit = habit; this.primaryColor = habit.color; + createColors(); fetchData(); postInvalidate(); @@ -69,7 +74,6 @@ public class HabitStreakView extends ScrollableDataView private void init() { - setDimensions(baseSize); createPaints(); createColors(); @@ -77,12 +81,32 @@ public class HabitStreakView extends ScrollableDataView rect = new Rect(); } - private void setDimensions(int baseSize) + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) + { + 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) { - this.columnWidth = baseSize; + baseSize = height / 10; + setScrollerBucketSize(baseSize); + + columnWidth = baseSize; columnHeight = 8 * baseSize; headerHeight = baseSize; - footerHeight = baseSize; + nColumns = width / baseSize; + + pText.setTextSize(baseSize * 0.5f); + pBar.setTextSize(baseSize * 0.5f); } private void createColors() @@ -91,8 +115,8 @@ public class HabitStreakView extends ScrollableDataView colors[3] = primaryColor; colors[1] = Color.argb(80, Color.red(primaryColor), Color.green(primaryColor), Color.blue( primaryColor)); - colors[2] = Color.argb(170, Color.red(primaryColor), Color.green(primaryColor), Color.blue( - primaryColor)); + colors[2] = Color.argb(170, Color.red(primaryColor), Color.green(primaryColor), + Color.blue(primaryColor)); colors[0] = Color.argb(30, 0, 0, 0); } @@ -101,12 +125,10 @@ public class HabitStreakView extends ScrollableDataView pText = new Paint(); pText.setColor(Color.LTGRAY); pText.setTextAlign(Paint.Align.CENTER); - pText.setTextSize(columnWidth * 0.5f); pText.setAntiAlias(true); pBar = new Paint(); pBar.setTextAlign(Paint.Align.CENTER); - pBar.setTextSize(columnWidth * 0.5f); pBar.setAntiAlias(true); } @@ -175,7 +197,7 @@ public class HabitStreakView extends ScrollableDataView float barHeaderOffset = lineHeight * 0.4f; int nStreaks = startTimes.length; - int start = nStreaks - nColumns - dataOffset; + int start = nStreaks - nColumns - getDataOffset(); String previousMonth = ""; diff --git a/app/src/main/java/org/isoron/uhabits/views/ScrollableDataView.java b/app/src/main/java/org/isoron/uhabits/views/ScrollableDataView.java index d9f28d1c8..7360456da 100644 --- a/app/src/main/java/org/isoron/uhabits/views/ScrollableDataView.java +++ b/app/src/main/java/org/isoron/uhabits/views/ScrollableDataView.java @@ -22,22 +22,17 @@ package org.isoron.uhabits.views; import android.animation.ValueAnimator; import android.content.Context; import android.util.AttributeSet; -import android.util.Log; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.View; import android.widget.Scroller; -import org.isoron.uhabits.R; - public abstract class ScrollableDataView extends View implements GestureDetector.OnGestureListener, ValueAnimator.AnimatorUpdateListener { - protected int dataOffset; - protected int nColumns, nRows; - protected int columnWidth, columnHeight; - protected int headerHeight, footerHeight; + private int dataOffset; + private int scrollerBucketSize; private GestureDetector detector; private Scroller scroller; @@ -57,7 +52,6 @@ public abstract class ScrollableDataView extends View implements GestureDetector private void init(Context context) { - this.columnWidth = (int) context.getResources().getDimension(R.dimen.small_square_size); detector = new GestureDetector(context, this); scroller = new Scroller(context, null, true); scrollAnimator = ValueAnimator.ofFloat(0, 1); @@ -72,39 +66,6 @@ public abstract class ScrollableDataView extends View implements GestureDetector 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 public boolean onDown(MotionEvent e) { @@ -126,13 +87,17 @@ public abstract class ScrollableDataView extends View implements GestureDetector @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float dx, float dy) { + if(scrollerBucketSize == 0) + return false; + if(Math.abs(dx) > Math.abs(dy)) getParent().requestDisallowInterceptTouchEvent(true); scroller.startScroll(scroller.getCurrX(), scroller.getCurrY(), (int) -dx, (int) dy, 0); scroller.computeScrollOffset(); - dataOffset = Math.max(0, scroller.getCurrX() / columnWidth); + dataOffset = Math.max(0, scroller.getCurrX() / scrollerBucketSize); postInvalidate(); + return true; } @@ -161,7 +126,7 @@ public abstract class ScrollableDataView extends View implements GestureDetector if (!scroller.isFinished()) { scroller.computeScrollOffset(); - dataOffset = Math.max(0, scroller.getCurrX() / columnWidth); + dataOffset = Math.max(0, scroller.getCurrX() / scrollerBucketSize); postInvalidate(); } else @@ -169,4 +134,14 @@ public abstract class ScrollableDataView extends View implements GestureDetector scrollAnimator.cancel(); } } + + public int getDataOffset() + { + return dataOffset; + } + + public void setScrollerBucketSize(int scrollerBucketSize) + { + this.scrollerBucketSize = scrollerBucketSize; + } } diff --git a/app/src/main/res/drawable/widget_background.xml b/app/src/main/res/drawable/widget_background.xml index 5814c0b2f..3fb27a0b0 100644 --- a/app/src/main/res/drawable/widget_background.xml +++ b/app/src/main/res/drawable/widget_background.xml @@ -2,6 +2,6 @@ - + \ No newline at end of file diff --git a/app/src/main/res/layout/show_habit.xml b/app/src/main/res/layout/show_habit.xml index 6ffb27fa5..aff070c78 100644 --- a/app/src/main/res/layout/show_habit.xml +++ b/app/src/main/res/layout/show_habit.xml @@ -11,7 +11,6 @@ tools:context="org.isoron.uhabits.ShowHabitActivity"> @@ -28,10 +27,7 @@ - + + android:layout_height="200dp"/> @@ -81,7 +77,7 @@ + android:layout_height="200dp"/> \ No newline at end of file