From f4f7faf3a4e62c86233af7eb7fb51591cebf2917 Mon Sep 17 00:00:00 2001 From: Alinson Xavier Date: Mon, 20 Mar 2017 20:00:10 -0400 Subject: [PATCH] Fix a few issues with header scrolling --- .../common/views/ScrollableChart.java | 117 +++++++++++------- .../habits/list/ListHabitsRootView.java | 1 + .../habits/list/views/HeaderView.java | 46 ++++--- 3 files changed, 101 insertions(+), 63 deletions(-) diff --git a/app/src/main/java/org/isoron/uhabits/activities/common/views/ScrollableChart.java b/app/src/main/java/org/isoron/uhabits/activities/common/views/ScrollableChart.java index 0e77043b7..8b54b324f 100644 --- a/app/src/main/java/org/isoron/uhabits/activities/common/views/ScrollableChart.java +++ b/app/src/main/java/org/isoron/uhabits/activities/common/views/ScrollableChart.java @@ -33,7 +33,9 @@ public abstract class ScrollableChart extends View private int dataOffset; - private int scrollerBucketSize; + private int scrollerBucketSize = 1; + + private int direction = 1; private GestureDetector detector; @@ -43,10 +45,7 @@ public abstract class ScrollableChart extends View private ScrollController scrollController; - public void setScrollController(ScrollController scrollController) - { - this.scrollController = scrollController; - } + private int maxDataOffset = 10000; public ScrollableChart(Context context) { @@ -79,19 +78,6 @@ public abstract class ScrollableChart extends View } } - private void updateDataOffset() - { - int newDataOffset = - Math.max(0, scroller.getCurrX() / scrollerBucketSize); - - if(newDataOffset != dataOffset) - { - dataOffset = newDataOffset; - scrollController.onDataOffsetChanged(dataOffset); - postInvalidate(); - } - } - @Override public boolean onDown(MotionEvent e) { @@ -105,19 +91,44 @@ public abstract class ScrollableChart extends View float velocityY) { scroller.fling(scroller.getCurrX(), scroller.getCurrY(), - (int) velocityX / 2, 0, 0, 100000, 0, 0); + direction * ((int) velocityX) / 2, 0, 0, getMaxX(), 0, 0); invalidate(); scrollAnimator.setDuration(scroller.getDuration()); scrollAnimator.start(); - return false; } + private int getMaxX() + { + return maxDataOffset * scrollerBucketSize; + } + @Override - public void onLongPress(MotionEvent e) + public void onRestoreInstanceState(Parcelable state) { + BundleSavedState bss = (BundleSavedState) state; + int x = bss.bundle.getInt("x"); + int y = bss.bundle.getInt("y"); + direction = bss.bundle.getInt("direction"); + dataOffset = bss.bundle.getInt("dataOffset"); + maxDataOffset = bss.bundle.getInt("maxDataOffset"); + scroller.startScroll(0, 0, x, y, 0); + scroller.computeScrollOffset(); + super.onRestoreInstanceState(bss.getSuperState()); + } + @Override + public Parcelable onSaveInstanceState() + { + Parcelable superState = super.onSaveInstanceState(); + Bundle bundle = new Bundle(); + bundle.putInt("x", scroller.getCurrX()); + bundle.putInt("y", scroller.getCurrY()); + bundle.putInt("dataOffset", dataOffset); + bundle.putInt("direction", direction); + bundle.putInt("maxDataOffset", maxDataOffset); + return new BundleSavedState(superState, bundle); } @Override @@ -131,11 +142,14 @@ public abstract class ScrollableChart extends View if (parent != null) parent.requestDisallowInterceptTouchEvent(true); } - scroller.startScroll(scroller.getCurrX(), scroller.getCurrY(), - (int) -dx, (int) dy, 0); + + dx = - direction * dx; + dx = Math.min(dx, getMaxX() - scroller.getCurrX()); + scroller.startScroll(scroller.getCurrX(), scroller.getCurrY(), (int) dx, + (int) dy, 0); + scroller.computeScrollOffset(); updateDataOffset(); - return true; } @@ -157,32 +171,35 @@ public abstract class ScrollableChart extends View return detector.onTouchEvent(event); } - public void setScrollerBucketSize(int scrollerBucketSize) + public void setDirection(int direction) { - this.scrollerBucketSize = scrollerBucketSize; + if (direction != 1 && direction != -1) + throw new IllegalArgumentException(); + this.direction = direction; } @Override - public void onRestoreInstanceState(Parcelable state) + public void onLongPress(MotionEvent e) { - BundleSavedState bss = (BundleSavedState) state; - int x = bss.bundle.getInt("x"); - int y = bss.bundle.getInt("y"); - dataOffset = bss.bundle.getInt("dataOffset"); - scroller.startScroll(0, 0, x, y, 0); - scroller.computeScrollOffset(); - super.onRestoreInstanceState(bss.getSuperState()); + } - @Override - public Parcelable onSaveInstanceState() + public void setMaxDataOffset(int maxDataOffset) { - Parcelable superState = super.onSaveInstanceState(); - Bundle bundle = new Bundle(); - bundle.putInt("x", scroller.getCurrX()); - bundle.putInt("y", scroller.getCurrY()); - bundle.putInt("dataOffset", dataOffset); - return new BundleSavedState(superState, bundle); + this.maxDataOffset = maxDataOffset; + this.dataOffset = Math.min(dataOffset, maxDataOffset); + scrollController.onDataOffsetChanged(this.dataOffset); + postInvalidate(); + } + + public void setScrollController(ScrollController scrollController) + { + this.scrollController = scrollController; + } + + public void setScrollerBucketSize(int scrollerBucketSize) + { + this.scrollerBucketSize = scrollerBucketSize; } private void init(Context context) @@ -191,7 +208,21 @@ public abstract class ScrollableChart extends View scroller = new Scroller(context, null, true); scrollAnimator = ValueAnimator.ofFloat(0, 1); scrollAnimator.addUpdateListener(this); - scrollController = new ScrollController(){}; + scrollController = new ScrollController() {}; + } + + private void updateDataOffset() + { + int newDataOffset = scroller.getCurrX() / scrollerBucketSize; + newDataOffset = Math.max(0, newDataOffset); + newDataOffset = Math.min(maxDataOffset, newDataOffset); + + if (newDataOffset != dataOffset) + { + dataOffset = newDataOffset; + scrollController.onDataOffsetChanged(dataOffset); + postInvalidate(); + } } public interface ScrollController diff --git a/app/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsRootView.java b/app/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsRootView.java index 4a3c1ee73..7a716c9cd 100644 --- a/app/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsRootView.java +++ b/app/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsRootView.java @@ -164,6 +164,7 @@ public class ListHabitsRootView extends BaseRootView { int count = getCheckmarkCount(); header.setButtonCount(count); + header.setMaxDataOffset(Math.max(MAX_CHECKMARK_COUNT - count, 0)); listView.setCheckmarkCount(count); super.onSizeChanged(w, h, oldw, oldh); } diff --git a/app/src/main/java/org/isoron/uhabits/activities/habits/list/views/HeaderView.java b/app/src/main/java/org/isoron/uhabits/activities/habits/list/views/HeaderView.java index 9492b5857..e4863cd54 100644 --- a/app/src/main/java/org/isoron/uhabits/activities/habits/list/views/HeaderView.java +++ b/app/src/main/java/org/isoron/uhabits/activities/habits/list/views/HeaderView.java @@ -34,8 +34,6 @@ import org.isoron.uhabits.utils.*; import java.util.*; -import static org.isoron.uhabits.utils.InterfaceUtils.*; - public class HeaderView extends ScrollableChart implements Preferences.Listener, MidnightTimer.MidnightListener { @@ -52,6 +50,8 @@ public class HeaderView extends ScrollableChart private RectF rect; + private int maxDataOffset; + public HeaderView(Context context, AttributeSet attrs) { super(context, attrs); @@ -61,18 +61,6 @@ public class HeaderView extends ScrollableChart setButtonCount(5); } - StyledResources res = new StyledResources(context); - setScrollerBucketSize((int) dpToPixels(context, 42)); - paint = new TextPaint(); - paint.setColor(Color.BLACK); - paint.setAntiAlias(true); - paint.setTextSize(getResources().getDimension(R.dimen.tinyTextSize)); - paint.setTextAlign(Paint.Align.CENTER); - paint.setTypeface(Typeface.DEFAULT_BOLD); - paint.setColor(res.getColor(R.attr.mediumContrastTextColor)); - - rect = new RectF(); - Context appContext = context.getApplicationContext(); if (appContext instanceof HabitsApplication) { @@ -85,6 +73,21 @@ public class HeaderView extends ScrollableChart ListHabitsActivity activity = (ListHabitsActivity) context; midnightTimer = activity.getListHabitsComponent().getMidnightTimer(); } + + Resources res = context.getResources(); + setScrollerBucketSize((int) res.getDimension(R.dimen.checkmarkWidth)); + setDirection(shouldReverseCheckmarks() ? 1 : -1); + + StyledResources sr = new StyledResources(context); + paint = new TextPaint(); + paint.setColor(Color.BLACK); + paint.setAntiAlias(true); + paint.setTextSize(getResources().getDimension(R.dimen.tinyTextSize)); + paint.setTextAlign(Paint.Align.CENTER); + paint.setTypeface(Typeface.DEFAULT_BOLD); + paint.setColor(sr.getColor(R.attr.mediumContrastTextColor)); + + rect = new RectF(); } @Override @@ -96,6 +99,7 @@ public class HeaderView extends ScrollableChart @Override public void onCheckmarkOrderChanged() { + setDirection(shouldReverseCheckmarks() ? 1 : -1); postInvalidate(); } @@ -137,24 +141,26 @@ public class HeaderView extends ScrollableChart super.onDraw(canvas); GregorianCalendar day = DateUtils.getStartOfTodayCalendar(); - Resources res = getContext().getResources(); float width = res.getDimension(R.dimen.checkmarkWidth); float height = res.getDimension(R.dimen.checkmarkHeight); - rect.set(0, 0, width, height); - rect.offset(canvas.getWidth(), 0); + boolean reverse = shouldReverseCheckmarks(); day.add(GregorianCalendar.DAY_OF_MONTH, -getDataOffset()); float em = paint.measureText("m"); for (int i = 0; i < buttonCount; i++) { - rect.offset(-width, 0); + rect.set(0, 0, width, height); + rect.offset(canvas.getWidth(), 0); + if(reverse) rect.offset(- (i + 1) * width, 0); + else rect.offset((i - buttonCount) * width, 0); + String text = DateUtils.formatHeaderDate(day).toUpperCase(); String[] lines = text.split("\n"); - int y1 = (int)(rect.centerY() - 0.5 * em); - int y2 = (int)(rect.centerY() + em); + int y1 = (int)(rect.centerY() - 0.25 * em); + int y2 = (int)(rect.centerY() + 1.25 * em); canvas.drawText(lines[0], rect.centerX(), y1, paint); canvas.drawText(lines[1], rect.centerX(), y2, paint);