mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-06 09:08:52 -06:00
ShowHabit: Refactor score chart
This commit is contained in:
@@ -30,9 +30,9 @@ import org.junit.runner.RunWith;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@SmallTest
|
||||
public class HabitFrequencyViewTest extends BaseViewTest
|
||||
public class FrequencyChartTest extends BaseViewTest
|
||||
{
|
||||
private HabitFrequencyView view;
|
||||
private FrequencyChart view;
|
||||
|
||||
@Before
|
||||
public void setUp()
|
||||
@@ -42,7 +42,7 @@ public class HabitFrequencyViewTest extends BaseViewTest
|
||||
fixtures.purgeHabits(habitList);
|
||||
Habit habit = fixtures.createLongHabit();
|
||||
|
||||
view = new HabitFrequencyView(targetContext);
|
||||
view = new FrequencyChart(targetContext);
|
||||
view.setHabit(habit);
|
||||
refreshData(view);
|
||||
measureView(dpToPixels(300), dpToPixels(100), view);
|
||||
@@ -40,7 +40,7 @@ public class HabitHistoryViewTest extends BaseViewTest
|
||||
{
|
||||
private Habit habit;
|
||||
|
||||
private HabitHistoryView view;
|
||||
private HistoryView view;
|
||||
|
||||
@Before
|
||||
public void setUp()
|
||||
@@ -50,7 +50,7 @@ public class HabitHistoryViewTest extends BaseViewTest
|
||||
fixtures.purgeHabits(habitList);
|
||||
habit = fixtures.createLongHabit();
|
||||
|
||||
view = new HabitHistoryView(targetContext);
|
||||
view = new HistoryView(targetContext);
|
||||
view.setHabit(habit);
|
||||
measureView(dpToPixels(400), dpToPixels(200), view);
|
||||
refreshData(view);
|
||||
|
||||
@@ -25,18 +25,20 @@ import android.util.Log;
|
||||
|
||||
import org.isoron.uhabits.*;
|
||||
import org.isoron.uhabits.models.Habit;
|
||||
import org.isoron.uhabits.utils.*;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@SmallTest
|
||||
public class HabitScoreViewTest extends BaseViewTest
|
||||
public class ScoreChartTest extends BaseViewTest
|
||||
{
|
||||
private Habit habit;
|
||||
|
||||
private HabitScoreView view;
|
||||
private ScoreChart view;
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void setUp()
|
||||
{
|
||||
@@ -45,10 +47,10 @@ public class HabitScoreViewTest extends BaseViewTest
|
||||
fixtures.purgeHabits(habitList);
|
||||
habit = fixtures.createLongHabit();
|
||||
|
||||
view = new HabitScoreView(targetContext);
|
||||
view.setHabit(habit);
|
||||
view = new ScoreChart(targetContext);
|
||||
view.setScores(habit.getScores().getAll());
|
||||
view.setPrimaryColor(ColorUtils.getColor(targetContext, habit.getColor()));
|
||||
view.setBucketSize(7);
|
||||
refreshData(view);
|
||||
measureView(dpToPixels(300), dpToPixels(200), view);
|
||||
}
|
||||
|
||||
@@ -79,8 +81,8 @@ public class HabitScoreViewTest extends BaseViewTest
|
||||
@Test
|
||||
public void testRender_withMonthlyBucket() throws Throwable
|
||||
{
|
||||
view.setScores(habit.getScores().groupBy(DateUtils.TruncateField.MONTH));
|
||||
view.setBucketSize(30);
|
||||
view.refreshData();
|
||||
view.invalidate();
|
||||
|
||||
assertRenders(view, "HabitScoreView/renderMonthly.png");
|
||||
@@ -96,8 +98,8 @@ public class HabitScoreViewTest extends BaseViewTest
|
||||
@Test
|
||||
public void testRender_withYearlyBucket() throws Throwable
|
||||
{
|
||||
view.setScores(habit.getScores().groupBy(DateUtils.TruncateField.YEAR));
|
||||
view.setBucketSize(365);
|
||||
view.refreshData();
|
||||
view.invalidate();
|
||||
|
||||
assertRenders(view, "HabitScoreView/renderYearly.png");
|
||||
@@ -30,9 +30,9 @@ import org.junit.runner.RunWith;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@SmallTest
|
||||
public class HabitStreakViewTest extends BaseViewTest
|
||||
public class StreakChartTest extends BaseViewTest
|
||||
{
|
||||
private HabitStreakView view;
|
||||
private StreakChart view;
|
||||
|
||||
@Override
|
||||
@Before
|
||||
@@ -43,7 +43,7 @@ public class HabitStreakViewTest extends BaseViewTest
|
||||
fixtures.purgeHabits(habitList);
|
||||
Habit habit = fixtures.createLongHabit();
|
||||
|
||||
view = new HabitStreakView(targetContext);
|
||||
view = new StreakChart(targetContext);
|
||||
measureView(dpToPixels(300), dpToPixels(100), view);
|
||||
|
||||
view.setHabit(habit);
|
||||
@@ -44,6 +44,7 @@ public class MemoryScoreList extends ScoreList
|
||||
if (s.getTimestamp() >= timestamp) discard.add(s);
|
||||
|
||||
list.removeAll(discard);
|
||||
getObservable().notifyListeners();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -134,6 +134,8 @@ public class SQLiteScoreList extends ScoreList
|
||||
.where("habit = ?", habit.getId())
|
||||
.and("timestamp >= ?", timestamp)
|
||||
.execute();
|
||||
|
||||
getObservable().notifyListeners();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -32,7 +32,7 @@ import org.isoron.uhabits.R;
|
||||
import org.isoron.uhabits.models.Habit;
|
||||
import org.isoron.uhabits.models.HabitList;
|
||||
import org.isoron.uhabits.tasks.BaseTask;
|
||||
import org.isoron.uhabits.ui.habits.show.views.HabitHistoryView;
|
||||
import org.isoron.uhabits.ui.habits.show.views.HistoryView;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@@ -43,7 +43,7 @@ public class HistoryEditorDialog extends AppCompatDialogFragment
|
||||
|
||||
private Listener listener;
|
||||
|
||||
HabitHistoryView historyView;
|
||||
HistoryView historyView;
|
||||
|
||||
@Inject
|
||||
HabitList habitList;
|
||||
@@ -53,7 +53,7 @@ public class HistoryEditorDialog extends AppCompatDialogFragment
|
||||
{
|
||||
Context context = getActivity();
|
||||
HabitsApplication.getComponent().inject(this);
|
||||
historyView = new HabitHistoryView(context, null);
|
||||
historyView = new HistoryView(context, null);
|
||||
|
||||
if (savedInstanceState != null)
|
||||
{
|
||||
|
||||
@@ -22,13 +22,11 @@ package org.isoron.uhabits.ui.habits.show;
|
||||
import android.os.*;
|
||||
import android.support.v4.app.*;
|
||||
import android.view.*;
|
||||
import android.widget.*;
|
||||
|
||||
import org.isoron.uhabits.*;
|
||||
import org.isoron.uhabits.models.*;
|
||||
import org.isoron.uhabits.ui.habits.edit.*;
|
||||
import org.isoron.uhabits.ui.habits.show.views.*;
|
||||
import org.isoron.uhabits.utils.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -39,44 +37,33 @@ public class ShowHabitFragment extends Fragment
|
||||
{
|
||||
Habit habit;
|
||||
|
||||
float todayScore;
|
||||
|
||||
float lastMonthScore;
|
||||
|
||||
float lastYearScore;
|
||||
|
||||
int activeColor;
|
||||
|
||||
int inactiveColor;
|
||||
|
||||
int previousScoreInterval;
|
||||
|
||||
private ShowHabitHelper helper;
|
||||
|
||||
protected ShowHabitActivity activity;
|
||||
|
||||
private List<HabitDataView> dataViews;
|
||||
|
||||
@BindView(R.id.sStrengthInterval)
|
||||
Spinner sStrengthInterval;
|
||||
|
||||
@BindView(R.id.scoreView)
|
||||
HabitScoreView habitScoreView;
|
||||
|
||||
@BindView(R.id.historyView)
|
||||
HabitHistoryView habitHistoryView;
|
||||
HistoryView historyView;
|
||||
|
||||
@BindView(R.id.punchcardView)
|
||||
HabitFrequencyView habitFrequencyView;
|
||||
FrequencyChart frequencyChart;
|
||||
|
||||
@BindView(R.id.streakView)
|
||||
HabitStreakView habitStreakView;
|
||||
@BindView(R.id.streakChart)
|
||||
StreakChart streakChart;
|
||||
|
||||
@BindView(R.id.subtitle)
|
||||
SubtitleCardView subtitleView;
|
||||
@BindView(R.id.subtitleCard)
|
||||
SubtitleCard subtitleCard;
|
||||
|
||||
@BindView(R.id.overview)
|
||||
OverviewCardView overview;
|
||||
@BindView(R.id.overviewCard)
|
||||
OverviewCard overviewCard;
|
||||
|
||||
@BindView(R.id.strengthCard)
|
||||
ScoreCard scoreCard;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater,
|
||||
@@ -92,15 +79,6 @@ public class ShowHabitFragment extends Fragment
|
||||
habit = activity.getHabit();
|
||||
helper.updateColors();
|
||||
|
||||
int defaultScoreInterval =
|
||||
InterfaceUtils.getDefaultScoreInterval(getContext());
|
||||
previousScoreInterval = defaultScoreInterval;
|
||||
setScoreBucketSize(defaultScoreInterval);
|
||||
|
||||
sStrengthInterval.setSelection(defaultScoreInterval);
|
||||
sStrengthInterval.setOnItemSelectedListener(
|
||||
new OnItemSelectedListener());
|
||||
|
||||
createDataViews();
|
||||
helper.updateCardHeaders(view);
|
||||
setHasOptionsMenu(true);
|
||||
@@ -118,14 +96,14 @@ public class ShowHabitFragment extends Fragment
|
||||
|
||||
private void createDataViews()
|
||||
{
|
||||
subtitleView.setHabit(habit);
|
||||
overview.setHabit(habit);
|
||||
subtitleCard.setHabit(habit);
|
||||
overviewCard.setHabit(habit);
|
||||
scoreCard.setHabit(habit);
|
||||
|
||||
dataViews = new LinkedList<>();
|
||||
dataViews.add(habitScoreView);
|
||||
dataViews.add(habitHistoryView);
|
||||
dataViews.add(habitFrequencyView);
|
||||
dataViews.add(habitStreakView);
|
||||
dataViews.add(historyView);
|
||||
dataViews.add(frequencyChart);
|
||||
dataViews.add(streakChart);
|
||||
|
||||
for (HabitDataView dataView : dataViews)
|
||||
dataView.setHabit(habit);
|
||||
@@ -156,17 +134,6 @@ public class ShowHabitFragment extends Fragment
|
||||
return true;
|
||||
}
|
||||
|
||||
private void setScoreBucketSize(int position)
|
||||
{
|
||||
if (getView() == null) return;
|
||||
|
||||
habitScoreView.setBucketSize(
|
||||
HabitScoreView.DEFAULT_BUCKET_SIZES[position]);
|
||||
|
||||
InterfaceUtils.setDefaultScoreInterval(getContext(), position);
|
||||
previousScoreInterval = position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onModelChange()
|
||||
{
|
||||
@@ -190,23 +157,4 @@ public class ShowHabitFragment extends Fragment
|
||||
habit.getObservable().removeListener(this);
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
private class OnItemSelectedListener
|
||||
implements AdapterView.OnItemSelectedListener
|
||||
{
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> parent,
|
||||
View view,
|
||||
int position,
|
||||
long id)
|
||||
{
|
||||
setScoreBucketSize(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> parent)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,6 @@ public class ShowHabitHelper
|
||||
void updateCardHeaders(View view)
|
||||
{
|
||||
updateColor(view, R.id.tvHistory);
|
||||
updateColor(view, R.id.tvStrength);
|
||||
updateColor(view, R.id.tvStreaks);
|
||||
updateColor(view, R.id.tvWeekdayFreq);
|
||||
updateColor(view, R.id.scoreLabel);
|
||||
|
||||
@@ -31,7 +31,7 @@ import org.isoron.uhabits.utils.*;
|
||||
import java.text.*;
|
||||
import java.util.*;
|
||||
|
||||
public class HabitFrequencyView extends ScrollableDataView
|
||||
public class FrequencyChart extends ScrollableChart
|
||||
implements HabitDataView, ModelObservable.Listener
|
||||
{
|
||||
private Paint pGrid;
|
||||
@@ -70,13 +70,13 @@ public class HabitFrequencyView extends ScrollableDataView
|
||||
|
||||
private HashMap<Long, Integer[]> frequency;
|
||||
|
||||
public HabitFrequencyView(Context context)
|
||||
public FrequencyChart(Context context)
|
||||
{
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public HabitFrequencyView(Context context, AttributeSet attrs)
|
||||
public FrequencyChart(Context context, AttributeSet attrs)
|
||||
{
|
||||
super(context, attrs);
|
||||
this.primaryColor = ColorUtils.getColor(getContext(), 7);
|
||||
@@ -33,10 +33,9 @@ import org.isoron.uhabits.utils.*;
|
||||
import java.text.*;
|
||||
import java.util.*;
|
||||
|
||||
public class HabitHistoryView extends ScrollableDataView implements
|
||||
HabitDataView,
|
||||
ToggleRepetitionTask.Listener,
|
||||
ModelObservable.Listener
|
||||
public class HistoryView extends ScrollableChart implements HabitDataView,
|
||||
ToggleRepetitionTask.Listener,
|
||||
ModelObservable.Listener
|
||||
{
|
||||
private Habit habit;
|
||||
|
||||
@@ -89,13 +88,13 @@ public class HabitHistoryView extends ScrollableDataView implements
|
||||
|
||||
private float headerOverflow = 0;
|
||||
|
||||
public HabitHistoryView(Context context)
|
||||
public HistoryView(Context context)
|
||||
{
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public HabitHistoryView(Context context, AttributeSet attrs)
|
||||
public HistoryView(Context context, AttributeSet attrs)
|
||||
{
|
||||
super(context, attrs);
|
||||
init();
|
||||
@@ -169,6 +168,7 @@ public class HabitHistoryView extends ScrollableDataView implements
|
||||
postInvalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHabit(Habit habit)
|
||||
{
|
||||
this.habit = habit;
|
||||
@@ -31,7 +31,7 @@ import org.isoron.uhabits.utils.*;
|
||||
|
||||
import butterknife.*;
|
||||
|
||||
public class OverviewCardView extends LinearLayout
|
||||
public class OverviewCard extends LinearLayout
|
||||
implements ModelObservable.Listener
|
||||
{
|
||||
@Nullable
|
||||
@@ -57,13 +57,13 @@ public class OverviewCardView extends LinearLayout
|
||||
|
||||
private int color;
|
||||
|
||||
public OverviewCardView(Context context)
|
||||
public OverviewCard(Context context)
|
||||
{
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public OverviewCardView(Context context, AttributeSet attrs)
|
||||
public OverviewCard(Context context, AttributeSet attrs)
|
||||
{
|
||||
super(context, attrs);
|
||||
init();
|
||||
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* This file is part of Loop Habit Tracker.
|
||||
*
|
||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.ui.habits.show.views;
|
||||
|
||||
import android.content.*;
|
||||
import android.support.annotation.*;
|
||||
import android.util.*;
|
||||
import android.widget.*;
|
||||
|
||||
import org.isoron.uhabits.*;
|
||||
import org.isoron.uhabits.models.*;
|
||||
import org.isoron.uhabits.tasks.*;
|
||||
import org.isoron.uhabits.utils.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import butterknife.*;
|
||||
|
||||
public class ScoreCard extends RelativeLayout
|
||||
implements ModelObservable.Listener
|
||||
{
|
||||
public static final int[] BUCKET_SIZES = { 1, 7, 31, 92, 365 };
|
||||
|
||||
@BindView(R.id.spinner)
|
||||
Spinner spinner;
|
||||
|
||||
@BindView(R.id.scoreView)
|
||||
ScoreChart chart;
|
||||
|
||||
@BindView(R.id.title)
|
||||
TextView title;
|
||||
|
||||
@Nullable
|
||||
private Habit habit;
|
||||
|
||||
private int color;
|
||||
|
||||
private int bucketSize;
|
||||
|
||||
public ScoreCard(Context context)
|
||||
{
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public ScoreCard(Context context, AttributeSet attrs)
|
||||
{
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
@OnItemSelected(R.id.spinner)
|
||||
public void onItemSelected(int position)
|
||||
{
|
||||
setBucketSizeFromPosition(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onModelChange()
|
||||
{
|
||||
refreshData();
|
||||
}
|
||||
|
||||
public void setHabit(@NonNull Habit habit)
|
||||
{
|
||||
this.habit = habit;
|
||||
color = ColorUtils.getColor(getContext(), habit.getColor());
|
||||
refreshData();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow()
|
||||
{
|
||||
super.onAttachedToWindow();
|
||||
if (habit != null)
|
||||
{
|
||||
habit.getObservable().addListener(this);
|
||||
habit.getScores().getObservable().addListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow()
|
||||
{
|
||||
if (habit != null)
|
||||
{
|
||||
habit.getObservable().removeListener(this);
|
||||
habit.getScores().getObservable().removeListener(this);
|
||||
}
|
||||
|
||||
super.onDetachedFromWindow();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private DateUtils.TruncateField getTruncateField()
|
||||
{
|
||||
DateUtils.TruncateField field;
|
||||
|
||||
switch (bucketSize)
|
||||
{
|
||||
case 7:
|
||||
field = DateUtils.TruncateField.WEEK_NUMBER;
|
||||
break;
|
||||
|
||||
case 365:
|
||||
field = DateUtils.TruncateField.YEAR;
|
||||
break;
|
||||
|
||||
case 92:
|
||||
field = DateUtils.TruncateField.QUARTER;
|
||||
break;
|
||||
|
||||
default:
|
||||
Log.e("ScoreCard",
|
||||
String.format("Unknown bucket size: %d", bucketSize));
|
||||
// continue to case 31
|
||||
|
||||
case 31:
|
||||
field = DateUtils.TruncateField.MONTH;
|
||||
break;
|
||||
}
|
||||
|
||||
return field;
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
inflate(getContext(), R.layout.show_habit_strength, this);
|
||||
ButterKnife.bind(this);
|
||||
|
||||
int defaultPosition = getDefaultSpinnerPosition();
|
||||
setBucketSizeFromPosition(defaultPosition);
|
||||
spinner.setSelection(defaultPosition);
|
||||
|
||||
if(isInEditMode())
|
||||
{
|
||||
spinner.setVisibility(GONE);
|
||||
title.setTextColor(ColorUtils.getAndroidTestColor(1));
|
||||
chart.setPrimaryColor(ColorUtils.getAndroidTestColor(1));
|
||||
chart.populateWithRandomData();
|
||||
}
|
||||
}
|
||||
|
||||
private int getDefaultSpinnerPosition()
|
||||
{
|
||||
if(isInEditMode()) return 0;
|
||||
return InterfaceUtils.getDefaultScoreSpinnerPosition(getContext());
|
||||
}
|
||||
|
||||
private void refreshData()
|
||||
{
|
||||
if (habit == null) return;
|
||||
|
||||
title.setTextColor(color);
|
||||
chart.setPrimaryColor(color);
|
||||
|
||||
new BaseTask()
|
||||
{
|
||||
@Override
|
||||
protected void doInBackground()
|
||||
{
|
||||
List<Score> scores;
|
||||
|
||||
if (bucketSize == 1) scores = habit.getScores().getAll();
|
||||
else scores = habit.getScores().groupBy(getTruncateField());
|
||||
|
||||
chart.setScores(scores);
|
||||
chart.setBucketSize(bucketSize);
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
private void setBucketSizeFromPosition(int position)
|
||||
{
|
||||
if(isInEditMode()) return;
|
||||
|
||||
InterfaceUtils.setDefaultScoreSpinnerPosition(getContext(), position);
|
||||
bucketSize = BUCKET_SIZES[position];
|
||||
refreshData();
|
||||
}
|
||||
}
|
||||
@@ -26,14 +26,12 @@ import android.util.*;
|
||||
|
||||
import org.isoron.uhabits.*;
|
||||
import org.isoron.uhabits.models.*;
|
||||
import org.isoron.uhabits.tasks.*;
|
||||
import org.isoron.uhabits.utils.*;
|
||||
|
||||
import java.text.*;
|
||||
import java.util.*;
|
||||
|
||||
public class HabitScoreView extends ScrollableDataView
|
||||
implements HabitDataView, ModelObservable.Listener
|
||||
public class ScoreChart extends ScrollableChart
|
||||
{
|
||||
private static final PorterDuffXfermode XFERMODE_CLEAR =
|
||||
new PorterDuffXfermode(PorterDuff.Mode.CLEAR);
|
||||
@@ -41,14 +39,10 @@ public class HabitScoreView extends ScrollableDataView
|
||||
private static final PorterDuffXfermode XFERMODE_SRC =
|
||||
new PorterDuffXfermode(PorterDuff.Mode.SRC);
|
||||
|
||||
public static int DEFAULT_BUCKET_SIZES[] = {1, 7, 31, 92, 365};
|
||||
|
||||
private Paint pGrid;
|
||||
|
||||
private float em;
|
||||
|
||||
private Habit habit;
|
||||
|
||||
private SimpleDateFormat dfMonth;
|
||||
|
||||
private SimpleDateFormat dfDay;
|
||||
@@ -80,8 +74,6 @@ public class HabitScoreView extends ScrollableDataView
|
||||
|
||||
private int bucketSize = 7;
|
||||
|
||||
private int footerHeight;
|
||||
|
||||
private int backgroundColor;
|
||||
|
||||
private Bitmap drawingCache;
|
||||
@@ -96,51 +88,23 @@ public class HabitScoreView extends ScrollableDataView
|
||||
|
||||
private String previousMonthText;
|
||||
|
||||
public HabitScoreView(Context context)
|
||||
public ScoreChart(Context context)
|
||||
{
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public HabitScoreView(Context context, AttributeSet attrs)
|
||||
public ScoreChart(Context context, AttributeSet attrs)
|
||||
{
|
||||
super(context, attrs);
|
||||
this.primaryColor = ColorUtils.getColor(getContext(), 7);
|
||||
init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onModelChange()
|
||||
{
|
||||
refreshData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshData()
|
||||
{
|
||||
if (isInEditMode()) generateRandomData();
|
||||
else
|
||||
{
|
||||
if (habit == null) return;
|
||||
if (bucketSize == 1) scores = habit.getScores().getAll();
|
||||
else scores = habit.getScores().groupBy(getTruncateField());
|
||||
|
||||
createColors();
|
||||
}
|
||||
|
||||
postInvalidate();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setBucketSize(int bucketSize)
|
||||
{
|
||||
this.bucketSize = bucketSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHabit(Habit habit)
|
||||
{
|
||||
this.habit = habit;
|
||||
createColors();
|
||||
postInvalidate();
|
||||
}
|
||||
|
||||
public void setIsTransparencyEnabled(boolean enabled)
|
||||
@@ -150,6 +114,18 @@ public class HabitScoreView extends ScrollableDataView
|
||||
requestLayout();
|
||||
}
|
||||
|
||||
public void setPrimaryColor(int primaryColor)
|
||||
{
|
||||
this.primaryColor = primaryColor;
|
||||
postInvalidate();
|
||||
}
|
||||
|
||||
public void setScores(@NonNull List<Score> scores)
|
||||
{
|
||||
this.scores = scores;
|
||||
postInvalidate();
|
||||
}
|
||||
|
||||
protected void createPaints()
|
||||
{
|
||||
pText = new Paint();
|
||||
@@ -163,30 +139,6 @@ public class HabitScoreView extends ScrollableDataView
|
||||
pGrid.setAntiAlias(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow()
|
||||
{
|
||||
super.onAttachedToWindow();
|
||||
new BaseTask()
|
||||
{
|
||||
@Override
|
||||
protected void doInBackground()
|
||||
{
|
||||
refreshData();
|
||||
}
|
||||
}.execute();
|
||||
habit.getObservable().addListener(this);
|
||||
habit.getScores().getObservable().addListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow()
|
||||
{
|
||||
habit.getScores().getObservable().removeListener(this);
|
||||
habit.getObservable().removeListener(this);
|
||||
super.onDetachedFromWindow();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas)
|
||||
{
|
||||
@@ -205,7 +157,7 @@ public class HabitScoreView extends ScrollableDataView
|
||||
activeCanvas = canvas;
|
||||
}
|
||||
|
||||
if (habit == null || scores == null) return;
|
||||
if (scores == null) return;
|
||||
|
||||
rect.set(0, 0, nColumns * columnWidth, columnHeight);
|
||||
rect.offset(0, paddingTop);
|
||||
@@ -220,16 +172,13 @@ public class HabitScoreView extends ScrollableDataView
|
||||
previousYearText = "";
|
||||
skipYear = 0;
|
||||
|
||||
long currentDate = DateUtils.getStartOfToday();
|
||||
|
||||
for (int k = 0; k < nColumns + getDataOffset() - 1; k++)
|
||||
currentDate -= bucketSize * DateUtils.millisecondsInOneDay;
|
||||
|
||||
for (int k = 0; k < nColumns; k++)
|
||||
{
|
||||
int score = 0;
|
||||
int offset = nColumns - k - 1 + getDataOffset();
|
||||
if (offset < scores.size()) score = scores.get(offset).getValue();
|
||||
if (offset >= scores.size()) continue;
|
||||
|
||||
int score = scores.get(offset).getValue();
|
||||
long timestamp = scores.get(offset).getTimestamp();
|
||||
|
||||
double relativeScore = ((double) score) / Score.MAX_VALUE;
|
||||
int height = (int) (columnHeight * relativeScore);
|
||||
@@ -250,9 +199,7 @@ public class HabitScoreView extends ScrollableDataView
|
||||
rect.set(0, 0, columnWidth, columnHeight);
|
||||
rect.offset(k * columnWidth, paddingTop);
|
||||
|
||||
drawFooter(activeCanvas, rect, currentDate);
|
||||
|
||||
currentDate += bucketSize * DateUtils.millisecondsInOneDay;
|
||||
drawFooter(activeCanvas, rect, timestamp);
|
||||
}
|
||||
|
||||
if (activeCanvas != canvas) canvas.drawBitmap(drawingCache, 0, 0, null);
|
||||
@@ -279,18 +226,17 @@ public class HabitScoreView extends ScrollableDataView
|
||||
pText.setTextSize(Math.min(textSize, maxTextSize));
|
||||
em = pText.getFontSpacing();
|
||||
|
||||
footerHeight = (int) (3 * em);
|
||||
int footerHeight = (int) (3 * em);
|
||||
paddingTop = (int) (em);
|
||||
|
||||
baseSize = (height - footerHeight - paddingTop) / 8;
|
||||
setScrollerBucketSize(baseSize);
|
||||
|
||||
columnWidth = baseSize;
|
||||
columnWidth = Math.max(columnWidth, getMaxDayWidth() * 1.5f);
|
||||
columnWidth = Math.max(columnWidth, getMaxMonthWidth() * 1.2f);
|
||||
|
||||
nColumns = (int) (width / columnWidth);
|
||||
columnWidth = (float) width / nColumns;
|
||||
setScrollerBucketSize((int) columnWidth);
|
||||
|
||||
columnHeight = 8 * baseSize;
|
||||
|
||||
@@ -304,9 +250,7 @@ public class HabitScoreView extends ScrollableDataView
|
||||
|
||||
private void createColors()
|
||||
{
|
||||
if (habit != null) this.primaryColor =
|
||||
ColorUtils.getColor(getContext(), habit.getColor());
|
||||
|
||||
primaryColor = Color.BLACK;
|
||||
textColor = InterfaceUtils.getStyledColor(getContext(),
|
||||
R.attr.mediumContrastTextColor);
|
||||
gridColor = InterfaceUtils.getStyledColor(getContext(),
|
||||
@@ -411,7 +355,7 @@ public class HabitScoreView extends ScrollableDataView
|
||||
if (isTransparencyEnabled) pGraph.setXfermode(XFERMODE_SRC);
|
||||
}
|
||||
|
||||
private void generateRandomData()
|
||||
public void populateWithRandomData()
|
||||
{
|
||||
Random random = new Random();
|
||||
scores = new LinkedList<>();
|
||||
@@ -461,38 +405,6 @@ public class HabitScoreView extends ScrollableDataView
|
||||
return maxMonthWidth;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private DateUtils.TruncateField getTruncateField()
|
||||
{
|
||||
DateUtils.TruncateField field;
|
||||
|
||||
switch (bucketSize)
|
||||
{
|
||||
case 7:
|
||||
field = DateUtils.TruncateField.WEEK_NUMBER;
|
||||
break;
|
||||
|
||||
case 365:
|
||||
field = DateUtils.TruncateField.YEAR;
|
||||
break;
|
||||
|
||||
case 92:
|
||||
field = DateUtils.TruncateField.QUARTER;
|
||||
break;
|
||||
|
||||
default:
|
||||
Log.e("HabitScoreView",
|
||||
String.format("Unknown bucket size: %d", bucketSize));
|
||||
// continue to case 31
|
||||
|
||||
case 31:
|
||||
field = DateUtils.TruncateField.MONTH;
|
||||
break;
|
||||
}
|
||||
|
||||
return field;
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
createPaints();
|
||||
@@ -25,7 +25,7 @@ import android.util.*;
|
||||
import android.view.*;
|
||||
import android.widget.*;
|
||||
|
||||
public abstract class ScrollableDataView extends View
|
||||
public abstract class ScrollableChart extends View
|
||||
implements GestureDetector.OnGestureListener,
|
||||
ValueAnimator.AnimatorUpdateListener
|
||||
{
|
||||
@@ -40,13 +40,13 @@ public abstract class ScrollableDataView extends View
|
||||
|
||||
private ValueAnimator scrollAnimator;
|
||||
|
||||
public ScrollableDataView(Context context)
|
||||
public ScrollableChart(Context context)
|
||||
{
|
||||
super(context);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public ScrollableDataView(Context context, AttributeSet attrs)
|
||||
public ScrollableChart(Context context, AttributeSet attrs)
|
||||
{
|
||||
super(context, attrs);
|
||||
init(context);
|
||||
@@ -32,7 +32,7 @@ import org.isoron.uhabits.utils.*;
|
||||
import java.text.*;
|
||||
import java.util.*;
|
||||
|
||||
public class HabitStreakView extends View
|
||||
public class StreakChart extends View
|
||||
implements HabitDataView, ModelObservable.Listener
|
||||
{
|
||||
private Habit habit;
|
||||
@@ -73,13 +73,13 @@ public class HabitStreakView extends View
|
||||
|
||||
private int reverseTextColor;
|
||||
|
||||
public HabitStreakView(Context context)
|
||||
public StreakChart(Context context)
|
||||
{
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public HabitStreakView(Context context, AttributeSet attrs)
|
||||
public StreakChart(Context context, AttributeSet attrs)
|
||||
{
|
||||
super(context, attrs);
|
||||
this.primaryColor = ColorUtils.getColor(getContext(), 7);
|
||||
@@ -33,7 +33,7 @@ import org.isoron.uhabits.utils.*;
|
||||
|
||||
import butterknife.*;
|
||||
|
||||
public class SubtitleCardView extends LinearLayout
|
||||
public class SubtitleCard extends LinearLayout
|
||||
implements ModelObservable.Listener
|
||||
{
|
||||
@BindView(R.id.questionLabel)
|
||||
@@ -48,13 +48,13 @@ public class SubtitleCardView extends LinearLayout
|
||||
@Nullable
|
||||
private Habit habit;
|
||||
|
||||
public SubtitleCardView(Context context)
|
||||
public SubtitleCard(Context context)
|
||||
{
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public SubtitleCardView(Context context, AttributeSet attrs)
|
||||
public SubtitleCard(Context context, AttributeSet attrs)
|
||||
{
|
||||
super(context, attrs);
|
||||
init();
|
||||
@@ -269,13 +269,13 @@ public abstract class InterfaceUtils
|
||||
}
|
||||
|
||||
|
||||
public static void setDefaultScoreInterval(Context context, int position)
|
||||
public static void setDefaultScoreSpinnerPosition(Context context, int position)
|
||||
{
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
prefs.edit().putInt("pref_score_view_interval", position).apply();
|
||||
}
|
||||
|
||||
public static int getDefaultScoreInterval(Context context)
|
||||
public static int getDefaultScoreSpinnerPosition(Context context)
|
||||
{
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
int defaultScoreInterval = prefs.getInt("pref_score_view_interval", 1);
|
||||
|
||||
@@ -28,14 +28,14 @@ import org.isoron.uhabits.R;
|
||||
import org.isoron.uhabits.models.Habit;
|
||||
import org.isoron.uhabits.widgets.views.GraphWidgetView;
|
||||
import org.isoron.uhabits.ui.habits.show.views.HabitDataView;
|
||||
import org.isoron.uhabits.ui.habits.show.views.HabitFrequencyView;
|
||||
import org.isoron.uhabits.ui.habits.show.views.FrequencyChart;
|
||||
|
||||
public class FrequencyWidgetProvider extends BaseWidgetProvider
|
||||
{
|
||||
@Override
|
||||
protected View buildCustomView(Context context, Habit habit)
|
||||
{
|
||||
HabitFrequencyView dataView = new HabitFrequencyView(context);
|
||||
FrequencyChart dataView = new FrequencyChart(context);
|
||||
GraphWidgetView view = new GraphWidgetView(context, dataView);
|
||||
view.setHabit(habit);
|
||||
return view;
|
||||
|
||||
@@ -27,14 +27,14 @@ import org.isoron.uhabits.R;
|
||||
import org.isoron.uhabits.models.Habit;
|
||||
import org.isoron.uhabits.widgets.views.GraphWidgetView;
|
||||
import org.isoron.uhabits.ui.habits.show.views.HabitDataView;
|
||||
import org.isoron.uhabits.ui.habits.show.views.HabitHistoryView;
|
||||
import org.isoron.uhabits.ui.habits.show.views.HistoryView;
|
||||
|
||||
public class HistoryWidgetProvider extends BaseWidgetProvider
|
||||
{
|
||||
@Override
|
||||
protected View buildCustomView(Context context, Habit habit)
|
||||
{
|
||||
HabitHistoryView dataView = new HabitHistoryView(context);
|
||||
HistoryView dataView = new HistoryView(context);
|
||||
GraphWidgetView view = new GraphWidgetView(context, dataView);
|
||||
view.setHabit(habit);
|
||||
return view;
|
||||
|
||||
@@ -18,33 +18,33 @@
|
||||
*/
|
||||
package org.isoron.uhabits.widgets;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.app.*;
|
||||
import android.content.*;
|
||||
import android.view.*;
|
||||
|
||||
import org.isoron.uhabits.HabitBroadcastReceiver;
|
||||
import org.isoron.uhabits.R;
|
||||
import org.isoron.uhabits.models.Habit;
|
||||
import org.isoron.uhabits.utils.InterfaceUtils;
|
||||
import org.isoron.uhabits.widgets.views.GraphWidgetView;
|
||||
import org.isoron.uhabits.ui.habits.show.views.HabitDataView;
|
||||
import org.isoron.uhabits.ui.habits.show.views.HabitScoreView;
|
||||
import org.apache.commons.lang3.*;
|
||||
import org.isoron.uhabits.*;
|
||||
import org.isoron.uhabits.models.*;
|
||||
import org.isoron.uhabits.ui.habits.show.views.*;
|
||||
import org.isoron.uhabits.utils.*;
|
||||
|
||||
public class ScoreWidgetProvider extends BaseWidgetProvider
|
||||
{
|
||||
@Override
|
||||
protected View buildCustomView(Context context, Habit habit)
|
||||
{
|
||||
int defaultScoreInterval = InterfaceUtils.getDefaultScoreInterval(context);
|
||||
int size = HabitScoreView.DEFAULT_BUCKET_SIZES[defaultScoreInterval];
|
||||
int defaultScoreInterval = InterfaceUtils.getDefaultScoreSpinnerPosition(context);
|
||||
int size = ScoreCard.BUCKET_SIZES[defaultScoreInterval];
|
||||
|
||||
HabitScoreView dataView = new HabitScoreView(context);
|
||||
ScoreChart dataView = new ScoreChart(context);
|
||||
dataView.setIsTransparencyEnabled(true);
|
||||
dataView.setBucketSize(size);
|
||||
|
||||
GraphWidgetView view = new GraphWidgetView(context, dataView);
|
||||
view.setHabit(habit);
|
||||
return view;
|
||||
// GraphWidgetView view = new GraphWidgetView(context, dataView);
|
||||
// view.setHabit(habit);
|
||||
// return view;
|
||||
|
||||
throw new NotImplementedException("");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -27,14 +27,14 @@ import org.isoron.uhabits.R;
|
||||
import org.isoron.uhabits.models.Habit;
|
||||
import org.isoron.uhabits.widgets.views.GraphWidgetView;
|
||||
import org.isoron.uhabits.ui.habits.show.views.HabitDataView;
|
||||
import org.isoron.uhabits.ui.habits.show.views.HabitStreakView;
|
||||
import org.isoron.uhabits.ui.habits.show.views.StreakChart;
|
||||
|
||||
public class StreakWidgetProvider extends BaseWidgetProvider
|
||||
{
|
||||
@Override
|
||||
protected View buildCustomView(Context context, Habit habit)
|
||||
{
|
||||
HabitStreakView dataView = new HabitStreakView(context);
|
||||
StreakChart dataView = new StreakChart(context);
|
||||
GraphWidgetView view = new GraphWidgetView(context, dataView);
|
||||
view.setHabit(habit);
|
||||
return view;
|
||||
|
||||
@@ -31,49 +31,23 @@
|
||||
style="@style/CardList"
|
||||
android:clipToPadding="false">
|
||||
|
||||
<org.isoron.uhabits.ui.habits.show.views.SubtitleCardView
|
||||
<org.isoron.uhabits.ui.habits.show.views.SubtitleCard
|
||||
style="@style/ShowHabit.Subtitle"
|
||||
android:id="@+id/subtitle"/>
|
||||
android:id="@+id/subtitleCard"/>
|
||||
|
||||
<!--<View-->
|
||||
<!--android:id="@+id/headerShadow"-->
|
||||
<!--style="@style/ToolbarShadow"/>-->
|
||||
|
||||
<org.isoron.uhabits.ui.habits.show.views.OverviewCardView
|
||||
android:id="@+id/overview"
|
||||
<org.isoron.uhabits.ui.habits.show.views.OverviewCard
|
||||
android:id="@+id/overviewCard"
|
||||
android:paddingTop="12dp"
|
||||
style="@style/Card" />
|
||||
|
||||
<RelativeLayout
|
||||
<org.isoron.uhabits.ui.habits.show.views.ScoreCard
|
||||
android:id="@+id/strengthCard"
|
||||
style="@style/Card"
|
||||
android:gravity="center">
|
||||
|
||||
<android.support.v7.widget.AppCompatSpinner
|
||||
android:id="@+id/sStrengthInterval"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="22dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:entries="@array/strengthIntervalNames"
|
||||
android:theme="@style/SmallSpinner"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvStrength"
|
||||
style="@style/CardHeader"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:text="@string/habit_strength"/>
|
||||
|
||||
<org.isoron.uhabits.ui.habits.show.views.HabitScoreView
|
||||
android:id="@+id/scoreView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="220dp"
|
||||
android:layout_below="@id/tvStrength"/>
|
||||
|
||||
</RelativeLayout>
|
||||
android:gravity="center" />
|
||||
|
||||
<LinearLayout
|
||||
style="@style/Card"
|
||||
@@ -86,7 +60,7 @@
|
||||
style="@style/CardHeader"
|
||||
android:text="@string/history"/>
|
||||
|
||||
<org.isoron.uhabits.ui.habits.show.views.HabitHistoryView
|
||||
<org.isoron.uhabits.ui.habits.show.views.HistoryView
|
||||
android:id="@+id/historyView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="160dp"/>
|
||||
@@ -113,8 +87,8 @@
|
||||
style="@style/CardHeader"
|
||||
android:text="@string/best_streaks"/>
|
||||
|
||||
<org.isoron.uhabits.ui.habits.show.views.HabitStreakView
|
||||
android:id="@+id/streakView"
|
||||
<org.isoron.uhabits.ui.habits.show.views.StreakChart
|
||||
android:id="@+id/streakChart"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="200dp"/>
|
||||
</LinearLayout>
|
||||
@@ -128,7 +102,7 @@
|
||||
style="@style/CardHeader"
|
||||
android:text="@string/frequency"/>
|
||||
|
||||
<org.isoron.uhabits.ui.habits.show.views.HabitFrequencyView
|
||||
<org.isoron.uhabits.ui.habits.show.views.FrequencyChart
|
||||
android:id="@+id/punchcardView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="200dp"/>
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?windowBackgroundColor"
|
||||
@@ -31,24 +30,28 @@
|
||||
<android.support.v7.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
style="@style/Toolbar"
|
||||
app:title="Meditation"
|
||||
android:background="@color/deep_orange_700"
|
||||
android:elevation="1dp"
|
||||
app:popupTheme="?toolbarPopupTheme"
|
||||
android:elevation="1dp"/>
|
||||
app:title="Meditation"/>
|
||||
|
||||
<LinearLayout
|
||||
style="@style/CardList"
|
||||
android:clipToPadding="false">
|
||||
|
||||
<org.isoron.uhabits.ui.habits.show.views.SubtitleCardView
|
||||
<org.isoron.uhabits.ui.habits.show.views.SubtitleCard
|
||||
android:id="@+id/subtitleView"
|
||||
style="@style/ShowHabit.Subtitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<org.isoron.uhabits.ui.habits.show.views.OverviewCardView
|
||||
android:paddingTop="12dp"
|
||||
style="@style/Card" />
|
||||
<org.isoron.uhabits.ui.habits.show.views.OverviewCard
|
||||
style="@style/Card"
|
||||
android:paddingTop="12dp"/>
|
||||
|
||||
<org.isoron.uhabits.ui.habits.show.views.ScoreCard
|
||||
style="@style/Card"
|
||||
android:paddingTop="12dp"/>
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
48
app/src/main/res/layout/show_habit_strength.xml
Normal file
48
app/src/main/res/layout/show_habit_strength.xml
Normal file
@@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
||||
~
|
||||
~ This file is part of Loop Habit Tracker.
|
||||
~
|
||||
~ Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||
~ it under the terms of the GNU General Public License as published by the
|
||||
~ Free Software Foundation, either version 3 of the License, or (at your
|
||||
~ option) any later version.
|
||||
~
|
||||
~ Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||
~ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
~ more details.
|
||||
~
|
||||
~ You should have received a copy of the GNU General Public License along
|
||||
~ with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<android.support.v7.widget.AppCompatSpinner
|
||||
android:id="@+id/spinner"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="22dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:entries="@array/strengthIntervalNames"
|
||||
android:theme="@style/SmallSpinner"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
style="@style/CardHeader"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:text="@string/habit_strength"/>
|
||||
|
||||
<org.isoron.uhabits.ui.habits.show.views.ScoreChart
|
||||
android:id="@+id/scoreView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="220dp"
|
||||
android:layout_below="@id/title"/>
|
||||
|
||||
</merge>
|
||||
Reference in New Issue
Block a user