Refactor custom views; fix rendering issues

pull/30/head
Alinson S. Xavier 10 years ago
parent f0d12e9925
commit b8cacaffa9

@ -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);

@ -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);
}

@ -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);
}
}

@ -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 = "";

@ -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;
}
}

@ -2,6 +2,6 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#30000000" />
<solid android:color="#7f000000" />
<corners android:radius="10dp" />
</shape>

@ -11,7 +11,6 @@
tools:context="org.isoron.uhabits.ShowHabitActivity">
<LinearLayout
android:id="@+id/llOverview"
style="@style/cardStyle"
android:gravity="center">
@ -28,10 +27,7 @@
</LinearLayout>
<LinearLayout
android:id="@+id/llStrength"
style="@style/cardStyle"
android:gravity="center">
<LinearLayout style="@style/cardStyle">
<TextView
android:id="@+id/tvStrength"
@ -41,7 +37,7 @@
<org.isoron.uhabits.views.HabitScoreView
android:id="@+id/scoreView"
android:layout_width="match_parent"
android:layout_height="180dp"/>
android:layout_height="200dp"/>
</LinearLayout>
@ -81,7 +77,7 @@
<org.isoron.uhabits.views.HabitStreakView
android:id="@+id/streakView"
android:layout_width="match_parent"
android:layout_height="180dp"/>
android:layout_height="200dp"/>
</LinearLayout>
</LinearLayout>
</ScrollView>
Loading…
Cancel
Save