From 980db1d17172d48e52263d6308ee51daaf0d5c33 Mon Sep 17 00:00:00 2001 From: Alinson Xavier Date: Fri, 22 Apr 2016 11:02:17 -0400 Subject: [PATCH] Add ring to check mark widget --- .../uhabits/fragments/ListHabitsFragment.java | 2 +- .../isoron/uhabits/helpers/ColorHelper.java | 26 +- .../uhabits/helpers/ListHabitsHelper.java | 2 +- .../org/isoron/uhabits/helpers/UIHelper.java | 15 +- .../isoron/uhabits/views/CheckmarkView.java | 240 +++++++++--------- .../org/isoron/uhabits/views/RingView.java | 29 ++- .../res/layout/widget_checkmark_inner.xml | 63 +++++ 7 files changed, 226 insertions(+), 151 deletions(-) create mode 100644 app/src/main/res/layout/widget_checkmark_inner.xml diff --git a/app/src/main/java/org/isoron/uhabits/fragments/ListHabitsFragment.java b/app/src/main/java/org/isoron/uhabits/fragments/ListHabitsFragment.java index 9d87c7282..9ab74a709 100644 --- a/app/src/main/java/org/isoron/uhabits/fragments/ListHabitsFragment.java +++ b/app/src/main/java/org/isoron/uhabits/fragments/ListHabitsFragment.java @@ -122,7 +122,7 @@ public class ListHabitsFragment extends Fragment loader.setCheckmarkCount(helper.getButtonCount()); llHint.setOnClickListener(this); - tvStarEmpty.setTypeface(UIHelper.getFontAwesome()); + tvStarEmpty.setTypeface(UIHelper.getFontAwesome(activity)); adapter = new HabitListAdapter(getActivity(), loader); adapter.setSelectedPositions(selectedPositions); diff --git a/app/src/main/java/org/isoron/uhabits/helpers/ColorHelper.java b/app/src/main/java/org/isoron/uhabits/helpers/ColorHelper.java index bafffd809..d64f4ac3d 100644 --- a/app/src/main/java/org/isoron/uhabits/helpers/ColorHelper.java +++ b/app/src/main/java/org/isoron/uhabits/helpers/ColorHelper.java @@ -29,19 +29,19 @@ public class ColorHelper { public static int CSV_PALETTE[] = { - Color.parseColor("#D32F2F"), // red - Color.parseColor("#E64A19"), // orange - Color.parseColor("#F9A825"), // yellow - Color.parseColor("#AFB42B"), // light green - Color.parseColor("#388E3C"), // dark green - Color.parseColor("#00897B"), // teal - Color.parseColor("#00ACC1"), // cyan - Color.parseColor("#039BE5"), // blue - Color.parseColor("#5E35B1"), // deep purple - Color.parseColor("#8E24AA"), // purple - Color.parseColor("#D81B60"), // pink - Color.parseColor("#303030"), // dark grey - Color.parseColor("#aaaaaa") // light grey + Color.parseColor("#D32F2F"), // 0 red + Color.parseColor("#E64A19"), // 1 orange + Color.parseColor("#F9A825"), // 2 yellow + Color.parseColor("#AFB42B"), // 3 light green + Color.parseColor("#388E3C"), // 4 dark green + Color.parseColor("#00897B"), // 5 teal + Color.parseColor("#00ACC1"), // 6 cyan + Color.parseColor("#039BE5"), // 7 blue + Color.parseColor("#5E35B1"), // 8 deep purple + Color.parseColor("#8E24AA"), // 9 purple + Color.parseColor("#D81B60"), // 10 pink + Color.parseColor("#303030"), // 11 dark grey + Color.parseColor("#aaaaaa") // 12 light grey }; public static int colorToPaletteIndex(Context context, int color) diff --git a/app/src/main/java/org/isoron/uhabits/helpers/ListHabitsHelper.java b/app/src/main/java/org/isoron/uhabits/helpers/ListHabitsHelper.java index a389bf827..af76e3199 100644 --- a/app/src/main/java/org/isoron/uhabits/helpers/ListHabitsHelper.java +++ b/app/src/main/java/org/isoron/uhabits/helpers/ListHabitsHelper.java @@ -198,7 +198,7 @@ public class ListHabitsHelper { View check = inflater.inflate(R.layout.list_habits_item_check, null); TextView btCheck = (TextView) check.findViewById(R.id.tvCheck); - btCheck.setTypeface(UIHelper.getFontAwesome()); + btCheck.setTypeface(UIHelper.getFontAwesome(context)); btCheck.setOnLongClickListener(onLongClickListener); btCheck.setOnClickListener(onClickListener); btCheck.setHapticFeedbackEnabled(false); diff --git a/app/src/main/java/org/isoron/uhabits/helpers/UIHelper.java b/app/src/main/java/org/isoron/uhabits/helpers/UIHelper.java index 301eca48a..184a2a4cc 100644 --- a/app/src/main/java/org/isoron/uhabits/helpers/UIHelper.java +++ b/app/src/main/java/org/isoron/uhabits/helpers/UIHelper.java @@ -57,15 +57,10 @@ public abstract class UIHelper void onSaved(Command command, Object savedObject); } - public static Typeface getFontAwesome() + public static Typeface getFontAwesome(Context context) { if(fontAwesome == null) - { - Context context = HabitsApplication.getContext(); - if(context == null) throw new RuntimeException("Could not find application context"); - fontAwesome = Typeface.createFromAsset(context.getAssets(), "fontawesome-webfont.ttf"); - } return fontAwesome; } @@ -107,6 +102,14 @@ public abstract class UIHelper else return defaultValue; } + public static Integer getColorAttribute(Context context, AttributeSet attrs, String name, + Integer defaultValue) + { + int resId = attrs.getAttributeResourceValue(ISORON_NAMESPACE, name, 0); + if (resId != 0) return context.getResources().getColor(resId); + else return defaultValue; + } + public static int getIntAttribute(Context context, AttributeSet attrs, String name, int defaultValue) { diff --git a/app/src/main/java/org/isoron/uhabits/views/CheckmarkView.java b/app/src/main/java/org/isoron/uhabits/views/CheckmarkView.java index 535c14cb6..dd40d218f 100644 --- a/app/src/main/java/org/isoron/uhabits/views/CheckmarkView.java +++ b/app/src/main/java/org/isoron/uhabits/views/CheckmarkView.java @@ -20,184 +20,180 @@ package org.isoron.uhabits.views; import android.content.Context; -import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; -import android.graphics.Rect; -import android.graphics.Typeface; -import android.os.Build; -import android.text.Layout; -import android.text.StaticLayout; -import android.text.TextPaint; +import android.graphics.drawable.InsetDrawable; +import android.graphics.drawable.ShapeDrawable; +import android.graphics.drawable.shapes.RoundRectShape; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.util.AttributeSet; -import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.TextView; import org.isoron.uhabits.R; import org.isoron.uhabits.helpers.ColorHelper; +import org.isoron.uhabits.helpers.UIHelper; +import org.isoron.uhabits.models.Checkmark; import org.isoron.uhabits.models.Habit; +import org.isoron.uhabits.models.Score; -public class CheckmarkView extends View implements HabitDataView +import java.util.Arrays; + +public class CheckmarkView extends FrameLayout implements HabitDataView { - private Paint pCard; - private Paint pIcon; + @Nullable + private InsetDrawable background; - private int primaryColor; - private int timesColor; - private int darkGrey; + @Nullable + private Paint backgroundPaint; - private int width; - private int height; - private float leftMargin; - private float topMargin; - private float padding; - private String label; + @Nullable + private Habit habit; - private String fa_check; - private String fa_times; + private int activeColor; + private float percentage; - private int check_status; + @Nullable + private String name; - private Rect rect; - private TextPaint textPaint; - private StaticLayout labelLayout; - private Habit habit; + @Nullable + private RingView ring; + private ViewGroup frame; + private TextView label; + private int checkmarkValue; + private int inactiveColor; public CheckmarkView(Context context) { super(context); - init(context); + init(); } public CheckmarkView(Context context, AttributeSet attrs) { super(context, attrs); - init(context); + init(); } - private void init(Context context) + private void init() { - Typeface fontawesome = - Typeface.createFromAsset(context.getAssets(), "fontawesome-webfont.ttf"); + inflate(getContext(), R.layout.widget_checkmark_inner, this); - pCard = new Paint(); - pCard.setAntiAlias(true); + int shadowRadius = (int) UIHelper.dpToPixels(getContext(), 2); + int shadowOffset = (int) UIHelper.dpToPixels(getContext(), 1); + int shadowColor = Color.argb(96, 0, 0, 0); - pIcon = new Paint(); - pIcon.setAntiAlias(true); - pIcon.setTypeface(fontawesome); - pIcon.setTextAlign(Paint.Align.CENTER); + float cornerRadius = UIHelper.dpToPixels(getContext(), 5); + float[] radii = new float[8]; + Arrays.fill(radii, cornerRadius); - textPaint = new TextPaint(); - textPaint.setColor(Color.WHITE); - textPaint.setAntiAlias(true); + RoundRectShape shape = new RoundRectShape(radii, null, null); + ShapeDrawable innerDrawable = new ShapeDrawable(shape); - fa_check = context.getString(R.string.fa_check); - fa_times = context.getString(R.string.fa_times); + int insetLeftTop = Math.max(shadowRadius - shadowOffset, 0); + int insetRightBottom = shadowRadius + shadowOffset; - primaryColor = ColorHelper.getColor(getContext(), 10); - timesColor = Color.argb(128, 255, 255, 255); - darkGrey = Color.argb(64, 0, 0, 0); + background = new InsetDrawable(innerDrawable, insetLeftTop, insetLeftTop, insetRightBottom, + insetRightBottom); + backgroundPaint = innerDrawable.getPaint(); + backgroundPaint.setAlpha(100); - rect = new Rect(); - check_status = 0; - label = "Habit"; - } - - public void setHabit(Habit habit) - { - this.habit = habit; - } + if (backgroundPaint != null) + backgroundPaint.setShadowLayer(shadowRadius, shadowOffset, shadowOffset, shadowColor); - @Override - protected void onDraw(Canvas canvas) - { - super.onDraw(canvas); + ring = (RingView) findViewById(R.id.scoreRing); + frame = (ViewGroup) findViewById(R.id.frame); + label = (TextView) findViewById(R.id.label); - drawBackground(canvas); - drawCheckmark(canvas); - drawLabel(canvas); - } + inactiveColor = ColorHelper.CSV_PALETTE[11]; - private void drawBackground(Canvas canvas) - { - int color = (check_status == 2 ? primaryColor : darkGrey); - - pCard.setColor(color); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) - canvas.drawRoundRect(leftMargin, topMargin, width - leftMargin, height - topMargin, padding, - padding, pCard); - else - canvas.drawRect(leftMargin, topMargin, width - leftMargin, height - topMargin, pCard); + if(isInEditMode()) + { + percentage = 0.75f; + name = "Wake up early"; + activeColor = ColorHelper.CSV_PALETTE[6]; + checkmarkValue = Checkmark.CHECKED_EXPLICITLY; + refresh(); + } } - private void drawCheckmark(Canvas canvas) + @Override + public void setHabit(@NonNull Habit habit) { - String text = (check_status == 0 ? fa_times : fa_check); - int color = (check_status == 2 ? Color.WHITE : timesColor); - - pIcon.setColor(color); - pIcon.setTextSize(width * 0.5f); - pIcon.getTextBounds(text, 0, 1, rect); - - int y = (int) ((0.67f * height - rect.bottom - rect.top) / 2); - canvas.drawText(text, width / 2, y, pIcon); + this.habit = habit; + this.activeColor = ColorHelper.getColor(getContext(), habit.color); + refresh(); + postInvalidate(); } - private void drawLabel(Canvas canvas) + public void refresh() { - canvas.save(); - float y; - int nLines = labelLayout.getLineCount(); - - if(nLines == 1) - y = height * 0.8f - padding; - else - y = height * 0.7f - padding; + if (backgroundPaint == null || frame == null || ring == null) return; + + String text; + int color; + switch (checkmarkValue) + { + case Checkmark.CHECKED_EXPLICITLY: + text = getResources().getString(R.string.fa_check); + color = activeColor; + break; + + case Checkmark.CHECKED_IMPLICITLY: + text = getResources().getString(R.string.fa_check); + color = inactiveColor; + break; + + case Checkmark.UNCHECKED: + default: + text = getResources().getString(R.string.fa_times); + color = inactiveColor; + break; + } + + backgroundPaint.setColor(color); + frame.setBackgroundDrawable(background); + + ring.setPercentage(percentage); + ring.setPrecision(0.125f); + ring.setColor(Color.WHITE); + ring.setBackgroundColor(color); + ring.setText(text); + + label.setText(name); - canvas.translate(leftMargin + padding, y); - - labelLayout.draw(canvas); - canvas.restore(); + postInvalidate(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = MeasureSpec.getSize(widthMeasureSpec); - setMeasuredDimension(width, (int) (width * 1.25)); - } + int height = MeasureSpec.getSize(heightMeasureSpec); - @Override - protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) - { - this.width = getMeasuredWidth(); - this.height = getMeasuredHeight(); + float w = width; + float h = width * 1.25f; + float scale = Math.min(width / w, height / h); - leftMargin = (width * 0.015f); - topMargin = (height * 0.015f); - padding = 8 * leftMargin; - textPaint.setTextSize(0.15f * width); + w *= scale; + h *= scale; - updateLabel(); + widthMeasureSpec = MeasureSpec.makeMeasureSpec((int) w, MeasureSpec.EXACTLY); + heightMeasureSpec = MeasureSpec.makeMeasureSpec((int) h, MeasureSpec.EXACTLY); + super.onMeasure(widthMeasureSpec, heightMeasureSpec); } + @Override public void refreshData() { - this.check_status = habit.checkmarks.getTodayValue(); - int color = ColorHelper.getColor(getContext(), habit.color); - this.primaryColor = Color.argb(230, Color.red(color), Color.green(color), - Color.blue(color)); - this.label = habit.name; + if(habit == null) return; + this.name = habit.name; + this.percentage = (float) habit.scores.getTodayValue() / Score.MAX_VALUE; + this.checkmarkValue = habit.checkmarks.getTodayValue(); - updateLabel(); + refresh(); postInvalidate(); } - - private void updateLabel() - { - textPaint.setColor(Color.WHITE); - labelLayout = new StaticLayout(label, textPaint, - (int) (width - 2 * leftMargin - 2 * padding), - Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); - } } diff --git a/app/src/main/java/org/isoron/uhabits/views/RingView.java b/app/src/main/java/org/isoron/uhabits/views/RingView.java index bdfe4a49d..0462feb83 100644 --- a/app/src/main/java/org/isoron/uhabits/views/RingView.java +++ b/app/src/main/java/org/isoron/uhabits/views/RingView.java @@ -48,8 +48,8 @@ public class RingView extends View private float thickness; - private int backgroundColor; - private int inactiveColor; + private Integer backgroundColor; + private Integer inactiveColor; private float em; private String text; @@ -66,6 +66,10 @@ public class RingView extends View percentage = UIHelper.getFloatAttribute(context, attrs, "percentage", 0); precision = UIHelper.getFloatAttribute(context, attrs, "precision", 0.01f); + color = UIHelper.getColorAttribute(context, attrs, "color", 0); + backgroundColor = UIHelper.getColorAttribute(context, attrs, "backgroundColor", null); + inactiveColor = UIHelper.getColorAttribute(context, attrs, "inactiveColor", null); + thickness = UIHelper.getFloatAttribute(context, attrs, "thickness", 0); thickness = UIHelper.dpToPixels(context, thickness); @@ -86,6 +90,13 @@ public class RingView extends View postInvalidate(); } + @Override + public void setBackgroundColor(int backgroundColor) + { + this.backgroundColor = backgroundColor; + postInvalidate(); + } + public void setPercentage(float percentage) { this.percentage = percentage; @@ -117,10 +128,12 @@ public class RingView extends View pRing.setColor(color); pRing.setTextAlign(Paint.Align.CENTER); - backgroundColor = UIHelper.getStyledColor(getContext(), R.attr.cardBackgroundColor); + if(backgroundColor == null) + backgroundColor = UIHelper.getStyledColor(getContext(), R.attr.cardBackgroundColor); + + if(inactiveColor == null) + inactiveColor = UIHelper.getStyledColor(getContext(), R.attr.highContrastTextColor); - color = ColorHelper.CSV_PALETTE[6]; - inactiveColor = UIHelper.getStyledColor(getContext(), R.attr.highContrastTextColor); inactiveColor = ColorHelper.setAlpha(inactiveColor, 0.1f); rect = new RectF(); @@ -161,12 +174,12 @@ public class RingView extends View { pRing.setColor(backgroundColor); rect.inset(thickness, thickness); - canvas.drawArc(rect, -90, 360, true, pRing); + canvas.drawArc(rect, 0, 360, true, pRing); pRing.setColor(color); pRing.setTextSize(textSize); - if(enableFontAwesome) pRing.setTypeface(UIHelper.getFontAwesome()); - canvas.drawText(text, rect.centerX(), rect.centerY() + 0.5f * em, pRing); + if(enableFontAwesome) pRing.setTypeface(UIHelper.getFontAwesome(getContext())); + canvas.drawText(text, rect.centerX(), rect.centerY() + 0.4f * em, pRing); } } } diff --git a/app/src/main/res/layout/widget_checkmark_inner.xml b/app/src/main/res/layout/widget_checkmark_inner.xml new file mode 100644 index 000000000..13509e5cc --- /dev/null +++ b/app/src/main/res/layout/widget_checkmark_inner.xml @@ -0,0 +1,63 @@ + + + + + + + + + + \ No newline at end of file