mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-08 01:58:52 -06:00
Scroll checkmarks
This commit is contained in:
@@ -41,6 +41,13 @@ public abstract class ScrollableChart extends View
|
|||||||
|
|
||||||
private ValueAnimator scrollAnimator;
|
private ValueAnimator scrollAnimator;
|
||||||
|
|
||||||
|
private ScrollController scrollController;
|
||||||
|
|
||||||
|
public void setScrollController(ScrollController scrollController)
|
||||||
|
{
|
||||||
|
this.scrollController = scrollController;
|
||||||
|
}
|
||||||
|
|
||||||
public ScrollableChart(Context context)
|
public ScrollableChart(Context context)
|
||||||
{
|
{
|
||||||
super(context);
|
super(context);
|
||||||
@@ -64,8 +71,7 @@ public abstract class ScrollableChart extends View
|
|||||||
if (!scroller.isFinished())
|
if (!scroller.isFinished())
|
||||||
{
|
{
|
||||||
scroller.computeScrollOffset();
|
scroller.computeScrollOffset();
|
||||||
dataOffset = Math.max(0, scroller.getCurrX() / scrollerBucketSize);
|
updateDataOffset();
|
||||||
postInvalidate();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -73,6 +79,19 @@ 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
|
@Override
|
||||||
public boolean onDown(MotionEvent e)
|
public boolean onDown(MotionEvent e)
|
||||||
{
|
{
|
||||||
@@ -115,8 +134,7 @@ public abstract class ScrollableChart extends View
|
|||||||
scroller.startScroll(scroller.getCurrX(), scroller.getCurrY(),
|
scroller.startScroll(scroller.getCurrX(), scroller.getCurrY(),
|
||||||
(int) -dx, (int) dy, 0);
|
(int) -dx, (int) dy, 0);
|
||||||
scroller.computeScrollOffset();
|
scroller.computeScrollOffset();
|
||||||
dataOffset = Math.max(0, scroller.getCurrX() / scrollerBucketSize);
|
updateDataOffset();
|
||||||
postInvalidate();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -173,5 +191,11 @@ public abstract class ScrollableChart extends View
|
|||||||
scroller = new Scroller(context, null, true);
|
scroller = new Scroller(context, null, true);
|
||||||
scrollAnimator = ValueAnimator.ofFloat(0, 1);
|
scrollAnimator = ValueAnimator.ofFloat(0, 1);
|
||||||
scrollAnimator.addUpdateListener(this);
|
scrollAnimator.addUpdateListener(this);
|
||||||
|
scrollController = new ScrollController(){};
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ScrollController
|
||||||
|
{
|
||||||
|
default void onDataOffsetChanged(int newDataOffset) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import android.widget.*;
|
|||||||
|
|
||||||
import org.isoron.uhabits.R;
|
import org.isoron.uhabits.R;
|
||||||
import org.isoron.uhabits.activities.*;
|
import org.isoron.uhabits.activities.*;
|
||||||
|
import org.isoron.uhabits.activities.common.views.*;
|
||||||
import org.isoron.uhabits.activities.habits.list.controllers.*;
|
import org.isoron.uhabits.activities.habits.list.controllers.*;
|
||||||
import org.isoron.uhabits.activities.habits.list.model.*;
|
import org.isoron.uhabits.activities.habits.list.model.*;
|
||||||
import org.isoron.uhabits.activities.habits.list.views.*;
|
import org.isoron.uhabits.activities.habits.list.views.*;
|
||||||
@@ -43,7 +44,7 @@ import butterknife.*;
|
|||||||
public class ListHabitsRootView extends BaseRootView
|
public class ListHabitsRootView extends BaseRootView
|
||||||
implements ModelObservable.Listener, TaskRunner.Listener
|
implements ModelObservable.Listener, TaskRunner.Listener
|
||||||
{
|
{
|
||||||
public static final int MAX_CHECKMARK_COUNT = 21;
|
public static final int MAX_CHECKMARK_COUNT = 60;
|
||||||
|
|
||||||
@BindView(R.id.listView)
|
@BindView(R.id.listView)
|
||||||
HabitCardListView listView;
|
HabitCardListView listView;
|
||||||
@@ -132,6 +133,13 @@ public class ListHabitsRootView extends BaseRootView
|
|||||||
listController.setSelectionListener(menu);
|
listController.setSelectionListener(menu);
|
||||||
listView.setController(listController);
|
listView.setController(listController);
|
||||||
menu.setListController(listController);
|
menu.setListController(listController);
|
||||||
|
header.setScrollController(new ScrollableChart.ScrollController() {
|
||||||
|
@Override
|
||||||
|
public void onDataOffsetChanged(int newDataOffset)
|
||||||
|
{
|
||||||
|
listView.setDataOffset(newDataOffset);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -178,6 +178,20 @@ public class HabitCardListAdapter
|
|||||||
listView.bindCardView(holder, habit, score, checkmarks, selected);
|
listView.bindCardView(holder, habit, score, checkmarks, selected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onViewAttachedToWindow(@Nullable HabitCardViewHolder holder)
|
||||||
|
{
|
||||||
|
if (listView == null) return;
|
||||||
|
listView.attachCardView(holder);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onViewDetachedFromWindow(@Nullable HabitCardViewHolder holder)
|
||||||
|
{
|
||||||
|
if (listView == null) return;
|
||||||
|
listView.detachCardView(holder);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HabitCardViewHolder onCreateViewHolder(ViewGroup parent,
|
public HabitCardViewHolder onCreateViewHolder(ViewGroup parent,
|
||||||
int viewType)
|
int viewType)
|
||||||
|
|||||||
@@ -53,6 +53,8 @@ public class CheckmarkPanelView extends LinearLayout implements Preferences.List
|
|||||||
@NonNull
|
@NonNull
|
||||||
private Habit habit;
|
private Habit habit;
|
||||||
|
|
||||||
|
private int dataOffset;
|
||||||
|
|
||||||
public CheckmarkPanelView(Context context)
|
public CheckmarkPanelView(Context context)
|
||||||
{
|
{
|
||||||
super(context);
|
super(context);
|
||||||
@@ -75,19 +77,23 @@ public class CheckmarkPanelView extends LinearLayout implements Preferences.List
|
|||||||
return (CheckmarkButtonView) getChildAt(position);
|
return (CheckmarkButtonView) getChildAt(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCheckmarkValues(int[] checkmarkValues)
|
public void setButtonCount(int newButtonCount)
|
||||||
{
|
{
|
||||||
this.checkmarkValues = checkmarkValues;
|
if(nButtons != newButtonCount)
|
||||||
|
|
||||||
if (this.nButtons != checkmarkValues.length)
|
|
||||||
{
|
{
|
||||||
this.nButtons = checkmarkValues.length;
|
nButtons = newButtonCount;
|
||||||
addCheckmarkButtons();
|
addCheckmarkButtons();
|
||||||
}
|
}
|
||||||
|
|
||||||
setupCheckmarkButtons();
|
setupCheckmarkButtons();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setCheckmarkValues(int[] checkmarkValues)
|
||||||
|
{
|
||||||
|
this.checkmarkValues = checkmarkValues;
|
||||||
|
setupCheckmarkButtons();
|
||||||
|
}
|
||||||
|
|
||||||
public void setColor(int color)
|
public void setColor(int color)
|
||||||
{
|
{
|
||||||
this.color = color;
|
this.color = color;
|
||||||
@@ -100,6 +106,12 @@ public class CheckmarkPanelView extends LinearLayout implements Preferences.List
|
|||||||
setupCheckmarkButtons();
|
setupCheckmarkButtons();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setDataOffset(int dataOffset)
|
||||||
|
{
|
||||||
|
this.dataOffset = dataOffset;
|
||||||
|
setupCheckmarkButtons();
|
||||||
|
}
|
||||||
|
|
||||||
public void setHabit(@NonNull Habit habit)
|
public void setHabit(@NonNull Habit habit)
|
||||||
{
|
{
|
||||||
this.habit = habit;
|
this.habit = habit;
|
||||||
@@ -170,11 +182,13 @@ public class CheckmarkPanelView extends LinearLayout implements Preferences.List
|
|||||||
{
|
{
|
||||||
long timestamp = DateUtils.getStartOfToday();
|
long timestamp = DateUtils.getStartOfToday();
|
||||||
long day = DateUtils.millisecondsInOneDay;
|
long day = DateUtils.millisecondsInOneDay;
|
||||||
|
timestamp -= day * dataOffset;
|
||||||
|
|
||||||
for (int i = 0; i < nButtons; i++)
|
for (int i = 0; i < nButtons; i++)
|
||||||
{
|
{
|
||||||
CheckmarkButtonView buttonView = indexToButton(i);
|
CheckmarkButtonView buttonView = indexToButton(i);
|
||||||
buttonView.setValue(checkmarkValues[i]);
|
if(i + dataOffset >= checkmarkValues.length) break;
|
||||||
|
buttonView.setValue(checkmarkValues[i + dataOffset]);
|
||||||
buttonView.setColor(color);
|
buttonView.setColor(color);
|
||||||
setupButtonControllers(timestamp, buttonView);
|
setupButtonControllers(timestamp, buttonView);
|
||||||
timestamp -= day;
|
timestamp -= day;
|
||||||
|
|||||||
@@ -26,9 +26,9 @@ import android.support.v7.widget.helper.*;
|
|||||||
import android.util.*;
|
import android.util.*;
|
||||||
import android.view.*;
|
import android.view.*;
|
||||||
|
|
||||||
import org.isoron.uhabits.models.*;
|
|
||||||
import org.isoron.uhabits.activities.habits.list.controllers.*;
|
import org.isoron.uhabits.activities.habits.list.controllers.*;
|
||||||
import org.isoron.uhabits.activities.habits.list.model.*;
|
import org.isoron.uhabits.activities.habits.list.model.*;
|
||||||
|
import org.isoron.uhabits.models.*;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@@ -44,6 +44,10 @@ public class HabitCardListView extends RecyclerView
|
|||||||
|
|
||||||
private int checkmarkCount;
|
private int checkmarkCount;
|
||||||
|
|
||||||
|
private int dataOffset;
|
||||||
|
|
||||||
|
private LinkedList<HabitCardViewHolder> attachedHolders;
|
||||||
|
|
||||||
public HabitCardListView(Context context, AttributeSet attrs)
|
public HabitCardListView(Context context, AttributeSet attrs)
|
||||||
{
|
{
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
@@ -54,6 +58,13 @@ public class HabitCardListView extends RecyclerView
|
|||||||
TouchHelperCallback callback = new TouchHelperCallback();
|
TouchHelperCallback callback = new TouchHelperCallback();
|
||||||
touchHelper = new ItemTouchHelper(callback);
|
touchHelper = new ItemTouchHelper(callback);
|
||||||
touchHelper.attachToRecyclerView(this);
|
touchHelper.attachToRecyclerView(this);
|
||||||
|
|
||||||
|
attachedHolders = new LinkedList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void attachCardView(HabitCardViewHolder holder)
|
||||||
|
{
|
||||||
|
attachedHolders.add(holder);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -75,13 +86,12 @@ public class HabitCardListView extends RecyclerView
|
|||||||
int[] checkmarks,
|
int[] checkmarks,
|
||||||
boolean selected)
|
boolean selected)
|
||||||
{
|
{
|
||||||
int visibleCheckmarks[] =
|
|
||||||
Arrays.copyOfRange(checkmarks, 0, checkmarkCount);
|
|
||||||
|
|
||||||
HabitCardView cardView = (HabitCardView) holder.itemView;
|
HabitCardView cardView = (HabitCardView) holder.itemView;
|
||||||
cardView.setHabit(habit);
|
cardView.setHabit(habit);
|
||||||
cardView.setSelected(selected);
|
cardView.setSelected(selected);
|
||||||
cardView.setCheckmarkValues(visibleCheckmarks);
|
cardView.setCheckmarkValues(checkmarks);
|
||||||
|
cardView.setCheckmarkCount(checkmarkCount);
|
||||||
|
cardView.setDataOffset(dataOffset);
|
||||||
cardView.setScore(score);
|
cardView.setScore(score);
|
||||||
if (controller != null) setupCardViewController(holder);
|
if (controller != null) setupCardViewController(holder);
|
||||||
return cardView;
|
return cardView;
|
||||||
@@ -92,6 +102,11 @@ public class HabitCardListView extends RecyclerView
|
|||||||
return new HabitCardView(getContext());
|
return new HabitCardView(getContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void detachCardView(HabitCardViewHolder holder)
|
||||||
|
{
|
||||||
|
attachedHolders.remove(holder);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setAdapter(RecyclerView.Adapter adapter)
|
public void setAdapter(RecyclerView.Adapter adapter)
|
||||||
{
|
{
|
||||||
@@ -109,6 +124,16 @@ public class HabitCardListView extends RecyclerView
|
|||||||
this.controller = controller;
|
this.controller = controller;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setDataOffset(int dataOffset)
|
||||||
|
{
|
||||||
|
this.dataOffset = dataOffset;
|
||||||
|
for(HabitCardViewHolder holder : attachedHolders)
|
||||||
|
{
|
||||||
|
HabitCardView cardView = (HabitCardView) holder.itemView;
|
||||||
|
cardView.setDataOffset(dataOffset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onAttachedToWindow()
|
protected void onAttachedToWindow()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -72,6 +72,8 @@ public class HabitCardView extends FrameLayout
|
|||||||
@Nullable
|
@Nullable
|
||||||
private Habit habit;
|
private Habit habit;
|
||||||
|
|
||||||
|
private int dataOffset;
|
||||||
|
|
||||||
public HabitCardView(Context context)
|
public HabitCardView(Context context)
|
||||||
{
|
{
|
||||||
super(context);
|
super(context);
|
||||||
@@ -90,6 +92,11 @@ public class HabitCardView extends FrameLayout
|
|||||||
new Handler(Looper.getMainLooper()).post(() -> refresh());
|
new Handler(Looper.getMainLooper()).post(() -> refresh());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setCheckmarkCount(int checkmarkCount)
|
||||||
|
{
|
||||||
|
checkmarkPanel.setButtonCount(checkmarkCount);
|
||||||
|
}
|
||||||
|
|
||||||
public void setCheckmarkValues(int checkmarks[])
|
public void setCheckmarkValues(int checkmarks[])
|
||||||
{
|
{
|
||||||
checkmarkPanel.setCheckmarkValues(checkmarks);
|
checkmarkPanel.setCheckmarkValues(checkmarks);
|
||||||
@@ -103,6 +110,12 @@ public class HabitCardView extends FrameLayout
|
|||||||
checkmarkPanel.setController(controller);
|
checkmarkPanel.setController(controller);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setDataOffset(int dataOffset)
|
||||||
|
{
|
||||||
|
this.dataOffset = dataOffset;
|
||||||
|
checkmarkPanel.setDataOffset(dataOffset);
|
||||||
|
}
|
||||||
|
|
||||||
public void setHabit(@NonNull Habit habit)
|
public void setHabit(@NonNull Habit habit)
|
||||||
{
|
{
|
||||||
if (this.habit != null) detachFromHabit();
|
if (this.habit != null) detachFromHabit();
|
||||||
@@ -134,7 +147,7 @@ public class HabitCardView extends FrameLayout
|
|||||||
{
|
{
|
||||||
long today = DateUtils.getStartOfToday();
|
long today = DateUtils.getStartOfToday();
|
||||||
long day = DateUtils.millisecondsInOneDay;
|
long day = DateUtils.millisecondsInOneDay;
|
||||||
int offset = (int) ((today - timestamp) / day);
|
int offset = (int) ((today - timestamp) / day) - dataOffset;
|
||||||
CheckmarkButtonView button = checkmarkPanel.indexToButton(offset);
|
CheckmarkButtonView button = checkmarkPanel.indexToButton(offset);
|
||||||
|
|
||||||
float y = button.getHeight() / 2.0f;
|
float y = button.getHeight() / 2.0f;
|
||||||
|
|||||||
Reference in New Issue
Block a user