diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 00d4a5506..358d18fab 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -64,7 +64,7 @@ android:label="" android:theme="@style/Theme.AppCompat.Light.NoActionBar"/> - + diff --git a/app/src/main/java/org/isoron/helpers/DialogHelper.java b/app/src/main/java/org/isoron/helpers/DialogHelper.java index a8215f846..680ca04f2 100644 --- a/app/src/main/java/org/isoron/helpers/DialogHelper.java +++ b/app/src/main/java/org/isoron/helpers/DialogHelper.java @@ -18,10 +18,12 @@ package org.isoron.helpers; import android.content.Context; import android.content.SharedPreferences; +import android.content.res.Resources; import android.graphics.Typeface; import android.os.Vibrator; import android.preference.PreferenceManager; import android.util.AttributeSet; +import android.util.DisplayMetrics; import android.view.View; import android.view.inputmethod.InputMethodManager; @@ -72,4 +74,11 @@ public abstract class DialogHelper else return attrs.getAttributeValue(ISORON_NAMESPACE, name); } + + public static float dpToPixels(Context context, float dp) + { + Resources resources = context.getResources(); + DisplayMetrics metrics = resources.getDisplayMetrics(); + return dp * (metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT); + } } diff --git a/app/src/main/java/org/isoron/uhabits/HabitWidgetConfigure.java b/app/src/main/java/org/isoron/uhabits/HabitWidgetConfigure.java index 8aa15caed..0a7275bdd 100644 --- a/app/src/main/java/org/isoron/uhabits/HabitWidgetConfigure.java +++ b/app/src/main/java/org/isoron/uhabits/HabitWidgetConfigure.java @@ -27,7 +27,6 @@ import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ListView; -import org.isoron.helpers.DialogHelper; import org.isoron.uhabits.models.Habit; import java.util.ArrayList; @@ -78,7 +77,7 @@ public class HabitWidgetConfigure extends Activity implements AdapterView.OnItem Long habitId = habitIds.get(position); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences( getApplicationContext()); - prefs.edit().putLong(SmallWidgetProvider.getWidgetPrefKey(widgetId), habitId).commit(); + prefs.edit().putLong(HabitWidgetProvider.getWidgetPrefKey(widgetId), habitId).commit(); MainActivity.updateWidgets(this); diff --git a/app/src/main/java/org/isoron/uhabits/SmallWidgetProvider.java b/app/src/main/java/org/isoron/uhabits/HabitWidgetProvider.java similarity index 55% rename from app/src/main/java/org/isoron/uhabits/SmallWidgetProvider.java rename to app/src/main/java/org/isoron/uhabits/HabitWidgetProvider.java index ac5ebef41..d062f3b63 100644 --- a/app/src/main/java/org/isoron/uhabits/SmallWidgetProvider.java +++ b/app/src/main/java/org/isoron/uhabits/HabitWidgetProvider.java @@ -21,25 +21,39 @@ import android.appwidget.AppWidgetProvider; import android.content.Context; import android.content.SharedPreferences; import android.graphics.Bitmap; +import android.os.Bundle; import android.preference.PreferenceManager; +import android.util.Log; import android.widget.RemoteViews; +import org.isoron.helpers.DialogHelper; import org.isoron.uhabits.models.Habit; -import org.isoron.uhabits.views.SmallWidgetView; +import org.isoron.uhabits.views.HabitHistoryView; -public class SmallWidgetProvider extends AppWidgetProvider +public class HabitWidgetProvider extends AppWidgetProvider { @Override public void onUpdate(Context context, AppWidgetManager manager, int[] appWidgetIds) { for(int id : appWidgetIds) - updateWidget(context, manager, id); + { + Bundle options = manager.getAppWidgetOptions(id); + updateWidget(context, manager, id, options); + } } - private void updateWidget(Context context, AppWidgetManager manager, int widgetId) + private void updateWidget(Context context, AppWidgetManager manager, int widgetId, Bundle options) { - RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.small_widget); + int max_height = (int) DialogHelper.dpToPixels(context, options.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT)); + int min_height = (int) DialogHelper.dpToPixels(context, options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT)); + int max_width = (int) DialogHelper.dpToPixels(context, options.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH)); + int min_width = (int) DialogHelper.dpToPixels(context, options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH)); + + Log.d("HabitWidgetProvider", String.format("max_h=%d min_h=%d max_w=%d min_w=%d", + max_height, min_height, max_width, min_width)); + + RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_graph); Context appContext = context.getApplicationContext(); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(appContext); @@ -48,13 +62,23 @@ public class SmallWidgetProvider extends AppWidgetProvider Habit habit = Habit.get(habitId); - SmallWidgetView widgetView = new SmallWidgetView(context); - widgetView.setDrawingCacheEnabled(true); - widgetView.measure(180, 200); - widgetView.layout(0, 0, 180, 200); - widgetView.buildDrawingCache(true); +// SmallWidgetView widgetView = new SmallWidgetView(context); + HabitHistoryView widgetView = new HabitHistoryView(context, null); +// HabitScoreView widgetView = new HabitScoreView(context, null); +// HabitStreakView widgetView = new HabitStreakView(context, null); widgetView.setHabit(habit); + widgetView.setDrawingCacheEnabled(true); + widgetView.measure(max_width, max_height); + widgetView.layout(0, 0, max_width, max_height); + + int width = widgetView.getMeasuredWidth(); + int height = widgetView.getMeasuredHeight(); + Log.d("SmallWidgetProvider", String.format("width=%d height=%d\n", width, height)); + height -= DialogHelper.dpToPixels(context, 12f); + widgetView.measure(width, height); + widgetView.layout(0, 0, width, height); + widgetView.buildDrawingCache(true); Bitmap drawingCache = widgetView.getDrawingCache(); remoteViews.setTextViewText(R.id.tvName, habit.name); @@ -78,4 +102,11 @@ public class SmallWidgetProvider extends AppWidgetProvider for(Integer id : appWidgetIds) prefs.edit().remove(getWidgetPrefKey(id)); } + + @Override + public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, + int appWidgetId, Bundle newOptions) + { + updateWidget(context, appWidgetManager, appWidgetId, newOptions); + } } diff --git a/app/src/main/java/org/isoron/uhabits/MainActivity.java b/app/src/main/java/org/isoron/uhabits/MainActivity.java index b2a960d3c..a65b7c8d0 100644 --- a/app/src/main/java/org/isoron/uhabits/MainActivity.java +++ b/app/src/main/java/org/isoron/uhabits/MainActivity.java @@ -127,9 +127,9 @@ public class MainActivity extends ReplayableActivity public static void updateWidgets(Context context) { - ComponentName provider = new ComponentName(context, SmallWidgetProvider.class); + ComponentName provider = new ComponentName(context, HabitWidgetProvider.class); - Intent intent = new Intent(context, SmallWidgetProvider.class); + Intent intent = new Intent(context, HabitWidgetProvider.class); intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE); int ids[] = AppWidgetManager.getInstance(context).getAppWidgetIds(provider); 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 3bcbabe09..e9b0a4f33 100644 --- a/app/src/main/java/org/isoron/uhabits/views/HabitHistoryView.java +++ b/app/src/main/java/org/isoron/uhabits/views/HabitHistoryView.java @@ -54,14 +54,12 @@ public class HabitHistoryView extends ScrollableDataView private int todayWeekday; private int colors[]; private Rect baseLocation; - private int baseSize; private int primaryColor; public HabitHistoryView(Context context, AttributeSet attrs) { super(context, attrs); this.primaryColor = ColorHelper.palette[7]; - this.baseSize = (int) context.getResources().getDimension(R.dimen.small_square_size); init(); } @@ -76,9 +74,9 @@ public class HabitHistoryView extends ScrollableDataView private void init() { - setDimensions(this.baseSize); createPaints(); createColors(); + updateDimensions(); wdays = DateHelper.getShortDayNames(); dfMonth = new SimpleDateFormat("MMM", Locale.getDefault()); @@ -108,8 +106,9 @@ public class HabitHistoryView extends ScrollableDataView private void createColors() { - int primaryColorBright = ColorHelper.mixColors(primaryColor, Color.WHITE, 0.5f); - int grey = Color.rgb(230, 230, 230); + int primaryColorBright = Color.argb(127, Color.red(primaryColor), Color.green(primaryColor), + Color.blue(primaryColor)); + int grey = Color.argb(25, 0, 0, 0); colors = new int[3]; colors[0] = grey; @@ -117,19 +116,20 @@ public class HabitHistoryView extends ScrollableDataView colors[2] = primaryColor; } - private void setDimensions(int baseSize) + protected void updateDimensions() { - columnWidth = baseSize; - columnHeight = 8 * baseSize; - squareSpacing = 2; + squareSpacing = columnWidth / 10; + pSquareFg.setTextSize(columnWidth * 0.5f); + pTextHeader.setTextSize(columnWidth * 0.5f); + squareTextOffset = pSquareFg.getFontSpacing() * 0.4f; + headerTextOffset = pTextHeader.getFontSpacing() * 0.3f; } - private void createPaints() + protected void createPaints() { pTextHeader = new Paint(); pTextHeader.setColor(Color.LTGRAY); pTextHeader.setTextAlign(Align.LEFT); - pTextHeader.setTextSize(columnWidth * 0.5f); pTextHeader.setAntiAlias(true); pSquareBg = new Paint(); @@ -138,11 +138,7 @@ public class HabitHistoryView extends ScrollableDataView pSquareFg = new Paint(); pSquareFg.setColor(Color.WHITE); pSquareFg.setAntiAlias(true); - pSquareFg.setTextSize(columnWidth * 0.5f); pSquareFg.setTextAlign(Align.CENTER); - - squareTextOffset = pSquareFg.getFontSpacing() * 0.4f; - headerTextOffset = pTextHeader.getFontSpacing() * 0.3f; } protected void fetchData() @@ -203,7 +199,7 @@ public class HabitHistoryView extends ScrollableDataView for (int column = 0; column < nColumns - 1; column++) { drawColumn(canvas, baseLocation, currentDate, column); - baseLocation.offset(columnWidth, -columnHeight); + baseLocation.offset(columnWidth, - columnHeight); } drawAxis(canvas, baseLocation); @@ -248,6 +244,8 @@ public class HabitHistoryView extends ScrollableDataView } } + private boolean justSkippedColumn = false; + private void drawColumnHeader(Canvas canvas, Rect location, GregorianCalendar date) { String month = dfMonth.format(date.getTime()); @@ -256,21 +254,32 @@ public class HabitHistoryView extends ScrollableDataView if (!month.equals(previousMonth)) { int offset = 0; - if (justPrintedYear) offset += columnWidth; + if (justPrintedYear) + { + offset += columnWidth; + justSkippedColumn = true; + } canvas.drawText(month, location.left + offset, location.bottom - headerTextOffset, pTextHeader); + previousMonth = month; justPrintedYear = false; } else if (!year.equals(previousYear)) { - canvas.drawText(year, location.left, location.bottom - headerTextOffset, pTextHeader); - previousYear = year; - justPrintedYear = true; + if(!justSkippedColumn) + { + canvas.drawText(year, location.left, location.bottom - headerTextOffset, pTextHeader); + previousYear = year; + justPrintedYear = true; + } + + justSkippedColumn = false; } else { + justSkippedColumn = false; justPrintedYear = false; } } 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 579cee894..ddab70d7a 100644 --- a/app/src/main/java/org/isoron/uhabits/views/HabitScoreView.java +++ b/app/src/main/java/org/isoron/uhabits/views/HabitScoreView.java @@ -20,6 +20,8 @@ import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; import android.graphics.RectF; import android.util.AttributeSet; @@ -69,8 +71,8 @@ public class HabitScoreView extends ScrollableDataView private void init() { createPaints(); - setDimensions(); createColors(); + updateDimensions(); dfMonth = new SimpleDateFormat("MMM", Locale.getDefault()); dfDay = new SimpleDateFormat("d", Locale.getDefault()); @@ -79,15 +81,6 @@ public class HabitScoreView extends ScrollableDataView prevRect = new RectF(); } - private void setDimensions() - { - this.columnWidth = baseSize; - columnHeight = 8 * baseSize; - headerHeight = baseSize; - footerHeight = baseSize; - em = pText.getFontSpacing(); - } - private void createColors() { colors = new int[4]; @@ -98,23 +91,35 @@ public class HabitScoreView extends ScrollableDataView colors[2] = ColorHelper.mixColors(colors[0], colors[3], 0.33f); } - private void createPaints() + protected void createPaints() { pText = new Paint(); pText.setColor(Color.LTGRAY); pText.setTextAlign(Paint.Align.LEFT); - pText.setTextSize(baseSize * 0.5f); pText.setAntiAlias(true); pGraph = new Paint(); pGraph.setTextAlign(Paint.Align.CENTER); - pGraph.setTextSize(baseSize * 0.5f); pGraph.setAntiAlias(true); - pGraph.setStrokeWidth(baseSize * 0.1f); pGrid = new Paint(); pGrid.setColor(Color.LTGRAY); pGrid.setAntiAlias(true); + + } + + @Override + protected void updateDimensions() + { + this.columnWidth = baseSize; + columnHeight = 8 * baseSize; + headerHeight = baseSize; + footerHeight = baseSize; + em = pText.getFontSpacing(); + + pText.setTextSize(baseSize * 0.5f); + pGraph.setTextSize(baseSize * 0.5f); + pGraph.setStrokeWidth(baseSize * 0.1f); pGrid.setStrokeWidth(baseSize * 0.05f); } @@ -235,15 +240,18 @@ public class HabitScoreView extends ScrollableDataView private void drawMarker(Canvas canvas, RectF rect) { rect.inset(columnWidth * 0.15f, columnWidth * 0.15f); - pGraph.setColor(Color.WHITE); + pGraph.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); canvas.drawOval(rect, pGraph); rect.inset(columnWidth * 0.1f, columnWidth * 0.1f); pGraph.setColor(primaryColor); + pGraph.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC)); canvas.drawOval(rect, pGraph); rect.inset(columnWidth * 0.1f, columnWidth * 0.1f); - pGraph.setColor(Color.WHITE); + pGraph.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); canvas.drawOval(rect, pGraph); + + pGraph.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC)); } } 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 6f8223f41..96f83fd04 100644 --- a/app/src/main/java/org/isoron/uhabits/views/HabitStreakView.java +++ b/app/src/main/java/org/isoron/uhabits/views/HabitStreakView.java @@ -88,13 +88,15 @@ public class HabitStreakView extends ScrollableDataView private void createColors() { colors = new int[4]; - colors[0] = Color.rgb(230, 230, 230); colors[3] = primaryColor; - colors[1] = ColorHelper.mixColors(colors[0], colors[3], 0.66f); - colors[2] = ColorHelper.mixColors(colors[0], colors[3], 0.33f); + 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[0] = Color.argb(30, 0, 0, 0); } - private void createPaints() + protected void createPaints() { pText = new Paint(); pText.setColor(Color.LTGRAY); 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 8c0ad9dab..d9f28d1c8 100644 --- a/app/src/main/java/org/isoron/uhabits/views/ScrollableDataView.java +++ b/app/src/main/java/org/isoron/uhabits/views/ScrollableDataView.java @@ -22,17 +22,20 @@ 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; + protected int nColumns, nRows; protected int columnWidth, columnHeight; protected int headerHeight, footerHeight; @@ -54,6 +57,7 @@ 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,7 +76,25 @@ public abstract class ScrollableDataView extends View implements GestureDetector protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); - setMeasuredDimension(getMeasuredWidth(), columnHeight + headerHeight + footerHeight); + + 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 diff --git a/app/src/main/res/drawable/widget_background.xml b/app/src/main/res/drawable/widget_background.xml new file mode 100644 index 000000000..5814c0b2f --- /dev/null +++ b/app/src/main/res/drawable/widget_background.xml @@ -0,0 +1,7 @@ + + + + + + \ 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 820567e0b..6ffb27fa5 100644 --- a/app/src/main/res/layout/show_habit.xml +++ b/app/src/main/res/layout/show_habit.xml @@ -41,7 +41,7 @@ + android:layout_height="180dp"/> @@ -61,7 +61,7 @@ + android:layout_height="180dp"/> @@ -81,7 +81,7 @@ + android:layout_height="180dp"/> \ No newline at end of file diff --git a/app/src/main/res/layout/widget_graph.xml b/app/src/main/res/layout/widget_graph.xml new file mode 100644 index 000000000..f0d1fca8c --- /dev/null +++ b/app/src/main/res/layout/widget_graph.xml @@ -0,0 +1,30 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/small_widget.xml b/app/src/main/res/layout/widget_small.xml similarity index 100% rename from app/src/main/res/layout/small_widget.xml rename to app/src/main/res/layout/widget_small.xml diff --git a/app/src/main/res/xml/small_widget_info.xml b/app/src/main/res/xml/small_widget_info.xml index 4ffc0e993..5a2f1585b 100644 --- a/app/src/main/res/xml/small_widget_info.xml +++ b/app/src/main/res/xml/small_widget_info.xml @@ -2,9 +2,9 @@