Replace star by ring

pull/84/merge
Alinson S. Xavier 10 years ago
parent e2bb4371d3
commit aee5d975db

@ -42,10 +42,10 @@ public class RingViewTest extends ViewTest
super.setup(); super.setup();
view = new RingView(targetContext); view = new RingView(targetContext);
view.setLabel("Hello world"); // view.setLabel("Hello world");
view.setPercentage(0.6f); view.setPercentage(0.6f);
view.setColor(ColorHelper.CSV_PALETTE[0]); view.setColor(ColorHelper.CSV_PALETTE[0]);
view.setMaxDiameter(dpToPixels(100)); // view.setMaxDiameter(dpToPixels(100));
} }
@Test @Test
@ -58,7 +58,7 @@ public class RingViewTest extends ViewTest
@Test @Test
public void testRender_withLongLabel() throws IOException public void testRender_withLongLabel() throws IOException
{ {
view.setLabel("The quick brown fox jumps over the lazy fox"); // view.setLabel("The quick brown fox jumps over the lazy fox");
measureView(dpToPixels(100), dpToPixels(100), view); measureView(dpToPixels(100), dpToPixels(100), view);
assertRenders(view, "RingView/renderLongLabel.png"); assertRenders(view, "RingView/renderLongLabel.png");
@ -67,9 +67,9 @@ public class RingViewTest extends ViewTest
@Test @Test
public void testRender_withDifferentParams() throws IOException public void testRender_withDifferentParams() throws IOException
{ {
view.setLabel("Habit Strength"); // view.setLabel("Habit Strength");
view.setPercentage(0.25f); view.setPercentage(0.25f);
view.setMaxDiameter(dpToPixels(50)); // view.setMaxDiameter(dpToPixels(50));
view.setColor(ColorHelper.CSV_PALETTE[5]); view.setColor(ColorHelper.CSV_PALETTE[5]);
measureView(dpToPixels(200), dpToPixels(200), view); measureView(dpToPixels(200), dpToPixels(200), view);

@ -61,6 +61,7 @@ import org.isoron.uhabits.helpers.DateHelper;
import org.isoron.uhabits.helpers.HintManager; import org.isoron.uhabits.helpers.HintManager;
import org.isoron.uhabits.helpers.ListHabitsHelper; import org.isoron.uhabits.helpers.ListHabitsHelper;
import org.isoron.uhabits.helpers.ReminderHelper; import org.isoron.uhabits.helpers.ReminderHelper;
import org.isoron.uhabits.helpers.UIHelper;
import org.isoron.uhabits.helpers.UIHelper.OnSavedListener; import org.isoron.uhabits.helpers.UIHelper.OnSavedListener;
import org.isoron.uhabits.loaders.HabitListLoader; import org.isoron.uhabits.loaders.HabitListLoader;
import org.isoron.uhabits.models.Habit; import org.isoron.uhabits.models.Habit;
@ -121,7 +122,7 @@ public class ListHabitsFragment extends Fragment
loader.setCheckmarkCount(helper.getButtonCount()); loader.setCheckmarkCount(helper.getButtonCount());
llHint.setOnClickListener(this); llHint.setOnClickListener(this);
tvStarEmpty.setTypeface(helper.getFontawesome()); tvStarEmpty.setTypeface(UIHelper.getFontAwesome());
adapter = new HabitListAdapter(getActivity(), loader); adapter = new HabitListAdapter(getActivity(), loader);
adapter.setSelectedPositions(selectedPositions); adapter.setSelectedPositions(selectedPositions);

@ -166,6 +166,7 @@ public class ShowHabitFragment extends Fragment
int androidColor = ColorHelper.getColor(getActivity(), habit.color); int androidColor = ColorHelper.getColor(getActivity(), habit.color);
scoreRing.setColor(androidColor); scoreRing.setColor(androidColor);
scoreRing.setPercentage(percentage); scoreRing.setPercentage(percentage);
scoreRing.setText(String.format("%.0f%%", 100 * percentage));
} }
private void updateHeaders(View view) private void updateHeaders(View view)

@ -112,6 +112,12 @@ public class ColorHelper
return setHSVParameter(color, newValue, 2); return setHSVParameter(color, newValue, 2);
} }
public static int setAlpha(int color, float newAlpha)
{
int intAlpha = (int) (newAlpha * 255);
return Color.argb(intAlpha, Color.red(color), Color.green(color), Color.blue(color));
}
public static int setMinValue(int color, float newValue) public static int setMinValue(int color, float newValue)
{ {
float hsv[] = new float[3]; float hsv[] = new float[3];

@ -20,7 +20,6 @@
package org.isoron.uhabits.helpers; package org.isoron.uhabits.helpers;
import android.content.Context; import android.content.Context;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.MotionEvent; import android.view.MotionEvent;
@ -33,6 +32,7 @@ import org.isoron.uhabits.R;
import org.isoron.uhabits.loaders.HabitListLoader; import org.isoron.uhabits.loaders.HabitListLoader;
import org.isoron.uhabits.models.Habit; import org.isoron.uhabits.models.Habit;
import org.isoron.uhabits.models.Score; import org.isoron.uhabits.models.Score;
import org.isoron.uhabits.views.RingView;
import java.util.GregorianCalendar; import java.util.GregorianCalendar;
@ -43,7 +43,6 @@ public class ListHabitsHelper
private final Context context; private final Context context;
private final HabitListLoader loader; private final HabitListLoader loader;
private Typeface fontawesome;
public ListHabitsHelper(Context context, HabitListLoader loader) public ListHabitsHelper(Context context, HabitListLoader loader)
{ {
@ -52,12 +51,6 @@ public class ListHabitsHelper
lowContrastColor = UIHelper.getStyledColor(context, R.attr.lowContrastTextColor); lowContrastColor = UIHelper.getStyledColor(context, R.attr.lowContrastTextColor);
mediumContrastColor = UIHelper.getStyledColor(context, R.attr.mediumContrastTextColor); mediumContrastColor = UIHelper.getStyledColor(context, R.attr.mediumContrastTextColor);
fontawesome = Typeface.createFromAsset(context.getAssets(), "fontawesome-webfont.ttf");
}
public Typeface getFontawesome()
{
return fontawesome;
} }
public int getButtonCount() public int getButtonCount()
@ -105,46 +98,24 @@ public class ListHabitsHelper
public void initializeLabelAndIcon(View itemView) public void initializeLabelAndIcon(View itemView)
{ {
TextView tvStar = (TextView) itemView.findViewById(R.id.tvStar);
tvStar.setTypeface(getFontawesome());
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(getHabitNameWidth(), LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(getHabitNameWidth(),
LinearLayout.LayoutParams.WRAP_CONTENT, 1); LinearLayout.LayoutParams.WRAP_CONTENT, 1);
itemView.findViewById(R.id.label).setLayoutParams(params); itemView.findViewById(R.id.label).setLayoutParams(params);
} }
public void updateNameAndIcon(Habit habit, TextView tvStar, TextView tvName) public void updateNameAndIcon(Habit habit, RingView ring, TextView tvName)
{ {
int activeColor = getActiveColor(habit); int activeColor = getActiveColor(habit);
tvName.setText(habit.name); tvName.setText(habit.name);
tvName.setTextColor(activeColor); tvName.setTextColor(activeColor);
if (habit.isArchived()) int score = loader.scores.get(habit.getId());
{ float percentage = (float) score / Score.MAX_VALUE;
tvStar.setText(context.getString(R.string.fa_archive));
tvStar.setTextColor(activeColor); ring.setColor(activeColor);
} ring.setPercentage(percentage);
else ring.setPrecision(0.2f);
{
int score = loader.scores.get(habit.getId());
if (score < Score.HALF_STAR_CUTOFF)
{
tvStar.setText(context.getString(R.string.fa_star_o));
tvStar.setTextColor(lowContrastColor);
}
else if (score < Score.FULL_STAR_CUTOFF)
{
tvStar.setText(context.getString(R.string.fa_star_half_o));
tvStar.setTextColor(lowContrastColor);
}
else
{
tvStar.setText(context.getString(R.string.fa_star));
tvStar.setTextColor(activeColor);
}
}
} }
public void updateCheckmark(int activeColor, TextView tvCheck, int check) public void updateCheckmark(int activeColor, TextView tvCheck, int check)
@ -184,7 +155,7 @@ public class ListHabitsHelper
public void updateHabitCard(View view, Habit habit, boolean selected) public void updateHabitCard(View view, Habit habit, boolean selected)
{ {
TextView tvStar = ((TextView) view.findViewById(R.id.tvStar)); RingView scoreRing = ((RingView) view.findViewById(R.id.scoreRing));
TextView tvName = (TextView) view.findViewById(R.id.label); TextView tvName = (TextView) view.findViewById(R.id.label);
LinearLayout llInner = (LinearLayout) view.findViewById(R.id.llInner); LinearLayout llInner = (LinearLayout) view.findViewById(R.id.llInner);
LinearLayout llButtons = (LinearLayout) view.findViewById(R.id.llButtons); LinearLayout llButtons = (LinearLayout) view.findViewById(R.id.llButtons);
@ -192,7 +163,7 @@ public class ListHabitsHelper
llInner.setTag(R.string.habit_key, habit.getId()); llInner.setTag(R.string.habit_key, habit.getId());
llInner.setOnTouchListener(new HotspotTouchListener()); llInner.setOnTouchListener(new HotspotTouchListener());
updateNameAndIcon(habit, tvStar, tvName); updateNameAndIcon(habit, scoreRing, tvName);
updateCheckmarkButtons(habit, llButtons); updateCheckmarkButtons(habit, llButtons);
updateHabitCardBackground(llInner, selected); updateHabitCardBackground(llInner, selected);
} }
@ -227,7 +198,7 @@ public class ListHabitsHelper
{ {
View check = inflater.inflate(R.layout.list_habits_item_check, null); View check = inflater.inflate(R.layout.list_habits_item_check, null);
TextView btCheck = (TextView) check.findViewById(R.id.tvCheck); TextView btCheck = (TextView) check.findViewById(R.id.tvCheck);
btCheck.setTypeface(fontawesome); btCheck.setTypeface(UIHelper.getFontAwesome());
btCheck.setOnLongClickListener(onLongClickListener); btCheck.setOnLongClickListener(onLongClickListener);
btCheck.setOnClickListener(onClickListener); btCheck.setOnClickListener(onClickListener);
btCheck.setHapticFeedbackEnabled(false); btCheck.setHapticFeedbackEnabled(false);

@ -50,13 +50,26 @@ public abstract class UIHelper
public static final int THEME_LIGHT = 0; public static final int THEME_LIGHT = 0;
public static final int THEME_DARK = 1; public static final int THEME_DARK = 1;
private static Typeface fontawesome; private static Typeface fontAwesome;
public interface OnSavedListener public interface OnSavedListener
{ {
void onSaved(Command command, Object savedObject); void onSaved(Command command, Object savedObject);
} }
public static Typeface getFontAwesome()
{
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;
}
public static void showSoftKeyboard(View view) public static void showSoftKeyboard(View view)
{ {
InputMethodManager imm = (InputMethodManager) view.getContext() InputMethodManager imm = (InputMethodManager) view.getContext()
@ -102,6 +115,14 @@ public abstract class UIHelper
else return defaultValue; else return defaultValue;
} }
public static boolean getBooleanAttribute(Context context, AttributeSet attrs, String name,
boolean defaultValue)
{
String boolText = getAttribute(context, attrs, name, null);
if(boolText != null) return Boolean.parseBoolean(boolText);
else return defaultValue;
}
public static float getFloatAttribute(Context context, AttributeSet attrs, String name, public static float getFloatAttribute(Context context, AttributeSet attrs, String name,
float defaultValue) float defaultValue)
{ {

@ -24,33 +24,34 @@ import android.content.Context;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.RectF; import android.graphics.RectF;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint; import android.text.TextPaint;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.View; import android.view.View;
import org.isoron.uhabits.R; import org.isoron.uhabits.R;
import org.isoron.uhabits.helpers.ColorHelper;
import org.isoron.uhabits.helpers.UIHelper; import org.isoron.uhabits.helpers.UIHelper;
public class RingView extends View public class RingView extends View
{ {
private float precision;
private boolean enableFontAwesome;
private int color; private int color;
private float percentage; private float percentage;
private float labelMarginTop;
private TextPaint pRing; private TextPaint pRing;
private String label;
private RectF rect; private RectF rect;
private StaticLayout labelLayout;
private int width; private int diameter;
private int height;
private float diameter;
private float maxDiameter;
private float textSize; private float textSize;
private int textColor;
private float thickness;
private int backgroundColor; private int backgroundColor;
private int inactiveColor;
private float em;
private String text;
public RingView(Context context) public RingView(Context context)
{ {
@ -62,9 +63,20 @@ public class RingView extends View
{ {
super(context, attrs); super(context, attrs);
this.label = UIHelper.getAttribute(context, attrs, "label", "Label"); percentage = UIHelper.getFloatAttribute(context, attrs, "percentage", 0);
this.maxDiameter = UIHelper.getFloatAttribute(context, attrs, "maxDiameter", 100); precision = UIHelper.getFloatAttribute(context, attrs, "precision", 0.01f);
this.maxDiameter = UIHelper.dpToPixels(context, maxDiameter);
thickness = UIHelper.getFloatAttribute(context, attrs, "thickness", 0);
thickness = UIHelper.dpToPixels(context, thickness);
float defaultTextSize = context.getResources().getDimension(R.dimen.smallTextSize);
textSize = UIHelper.getFloatAttribute(context, attrs, "textSize", defaultTextSize);
textSize = UIHelper.spToPixels(context, textSize);
text = UIHelper.getAttribute(context, attrs, "text", "");
enableFontAwesome = UIHelper.getBooleanAttribute(context, attrs, "enableFontAwesome", false);
init(); init();
} }
@ -74,19 +86,27 @@ public class RingView extends View
postInvalidate(); postInvalidate();
} }
public void setMaxDiameter(float maxDiameter) public void setPercentage(float percentage)
{ {
this.maxDiameter = maxDiameter; this.percentage = percentage;
postInvalidate();
} }
public void setLabel(String label) public void setPrecision(float precision)
{ {
this.label = label; this.precision = precision;
postInvalidate();
} }
public void setPercentage(float percentage) public void setThickness(float thickness)
{ {
this.percentage = percentage; this.thickness = thickness;
postInvalidate();
}
public void setText(String text)
{
this.text = text;
postInvalidate(); postInvalidate();
} }
@ -98,8 +118,10 @@ public class RingView extends View
pRing.setTextAlign(Paint.Align.CENTER); pRing.setTextAlign(Paint.Align.CENTER);
backgroundColor = UIHelper.getStyledColor(getContext(), R.attr.cardBackgroundColor); backgroundColor = UIHelper.getStyledColor(getContext(), R.attr.cardBackgroundColor);
textColor = UIHelper.getStyledColor(getContext(), R.attr.mediumContrastTextColor);
textSize = getResources().getDimension(R.dimen.smallTextSize); color = ColorHelper.CSV_PALETTE[6];
inactiveColor = UIHelper.getStyledColor(getContext(), R.attr.highContrastTextColor);
inactiveColor = ColorHelper.setAlpha(inactiveColor, 0.1f);
rect = new RectF(); rect = new RectF();
} }
@ -110,48 +132,41 @@ public class RingView extends View
{ {
super.onMeasure(widthMeasureSpec, heightMeasureSpec); super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width = MeasureSpec.getSize(widthMeasureSpec); int width = MeasureSpec.getSize(widthMeasureSpec);
height = MeasureSpec.getSize(heightMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec);
diameter = Math.min(height, width);
diameter = Math.min(maxDiameter, width);
pRing.setTextSize(textSize); pRing.setTextSize(textSize);
labelMarginTop = textSize * 0.80f; em = pRing.measureText("M");
labelLayout = new StaticLayout(label, pRing, width, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0f,
false);
width = Math.max(width, labelLayout.getWidth());
height = (int) (diameter + labelLayout.getHeight() + labelMarginTop);
setMeasuredDimension(width, height); setMeasuredDimension(diameter, diameter);
} }
@Override @Override
protected void onDraw(Canvas canvas) protected void onDraw(Canvas canvas)
{ {
super.onDraw(canvas); super.onDraw(canvas);
float thickness = diameter * 0.15f;
pRing.setColor(color); pRing.setColor(color);
rect.set(0, 0, diameter, diameter); rect.set(0, 0, diameter, diameter);
rect.offset((width - diameter) / 2, 0);
canvas.drawArc(rect, -90, 360 * percentage, true, pRing);
int grey = UIHelper.getStyledColor(getContext(), R.attr.lowContrastTextColor); float angle = 360 * Math.round(percentage / precision) * precision;
pRing.setColor(grey);
canvas.drawArc(rect, 360 * percentage - 90 + 2, 360 * (1 - percentage) - 4, true, pRing);
pRing.setColor(backgroundColor); canvas.drawArc(rect, -90, angle, true, pRing);
rect.inset(thickness, thickness);
canvas.drawArc(rect, -90, 360, true, pRing);
pRing.setColor(textColor); pRing.setColor(inactiveColor);
pRing.setTextSize(textSize); canvas.drawArc(rect, angle - 90, 360 - angle, true, pRing);
float lineHeight = pRing.getFontSpacing();
canvas.drawText(String.format("%.0f%%", percentage * 100), rect.centerX(), if(thickness > 0)
rect.centerY() + lineHeight / 3, pRing); {
pRing.setTextSize(textSize); pRing.setColor(backgroundColor);
canvas.translate(width / 2, diameter + labelMarginTop); rect.inset(thickness, thickness);
labelLayout.draw(canvas); canvas.drawArc(rect, -90, 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);
}
} }
} }

@ -19,16 +19,22 @@
--> -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/llOuter" xmlns:habit="http://isoron.org/android"
style="@style/ListHabits.Item"> android:id="@+id/llOuter"
style="@style/ListHabits.Item">
<LinearLayout <LinearLayout
android:id="@+id/llInner" android:id="@+id/llInner"
style="@style/ListHabits.HabitCard"> style="@style/ListHabits.HabitCard">
<TextView <org.isoron.uhabits.views.RingView
android:id="@+id/tvStar" android:layout_height="15dp"
style="@style/ListHabits.Star" /> android:layout_width="15dp"
android:id="@+id/scoreRing"
habit:thickness="3"
android:layout_marginTop="0dp"
android:layout_marginRight="10dp"
android:layout_marginLeft="8dp"/>
<TextView <TextView
android:id="@+id/label" android:id="@+id/label"

@ -18,7 +18,7 @@
--> -->
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://isoron.org/android" xmlns:habit="http://isoron.org/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -43,15 +43,23 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center" android:gravity="center"
android:orientation="horizontal"> android:orientation="vertical">
<org.isoron.uhabits.views.RingView <org.isoron.uhabits.views.RingView
android:id="@+id/scoreRing" android:id="@+id/scoreRing"
style="@style/SmallDataView" android:layout_width="75dp"
android:layout_width="100dp" android:layout_height="75dp"
app:label="@string/strength" habit:percentage="0"
app:maxDiameter="80" habit:thickness="10"
app:textSize="@dimen/smallTextSize"/> habit:textSize="12"
android:layout_margin="10dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/habit_strength"
android:textSize="@dimen/smallTextSize"
android:textColor="?mediumContrastTextColor"/>
</LinearLayout> </LinearLayout>

Loading…
Cancel
Save