Add quick selection for commonly used habit frequencies

Closes #25
pull/69/head
Alinson S. Xavier 10 years ago
parent d39e1978a2
commit c3ff1fbe03

@ -89,3 +89,22 @@ Material design icons are the official icon set from Google that are designed
under the material design guidelines. Available under the Creative Common
Attribution 4.0 International License (CC-BY 4.0).
### Android Flow Layout
<https://github.com/ApmeM/android-flowlayout>
Extended linear layout that wrap its content when there is no place in the current line.
Copyright 2011, Artem Votincev (apmem.org)
Licensed under the Apache License, Version 2.0 (the "License"); you may not
use this file except in compliance with the License. You may obtain a copy
of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
License for the specific language governing permissions and limitations
under the License.

@ -34,6 +34,7 @@ android {
dependencies {
compile 'com.android.support:support-v4:23.1.1'
compile 'com.github.paolorotolo:appintro:3.4.0'
compile 'org.apmem.tools:layouts:1.10@aar'
compile project(':libs:drag-sort-listview:library')
compile files('libs/ActiveAndroid.jar')

@ -19,7 +19,7 @@
package org.isoron.uhabits.ui;
import android.support.test.espresso.matcher.ViewMatchers;
import android.support.test.espresso.NoMatchingViewException;
import org.isoron.uhabits.R;
import org.isoron.uhabits.models.Habit;
@ -37,14 +37,18 @@ import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.action.ViewActions.longClick;
import static android.support.test.espresso.action.ViewActions.replaceText;
import static android.support.test.espresso.assertion.ViewAssertions.matches;
import static android.support.test.espresso.matcher.RootMatchers.isPlatformPopup;
import static android.support.test.espresso.matcher.ViewMatchers.Visibility.VISIBLE;
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.withContentDescription;
import static android.support.test.espresso.matcher.ViewMatchers.withEffectiveVisibility;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.startsWith;
import static org.isoron.uhabits.ui.HabitMatchers.containsHabit;
import static org.isoron.uhabits.ui.HabitMatchers.withName;
@ -97,6 +101,20 @@ public class MainActivityActions
.perform(replaceText(name));
onView(withId(R.id.input_description))
.perform(replaceText(description));
try
{
onView(allOf(withId(R.id.sFrequency), withEffectiveVisibility(VISIBLE)))
.perform(click());
onData(allOf(instanceOf(String.class), startsWith("Custom")))
.inRoot(isPlatformPopup())
.perform(click());
}
catch(NoMatchingViewException e)
{
// ignored
}
onView(withId(R.id.input_freq_num))
.perform(replaceText(num));
onView(withId(R.id.input_freq_den))

@ -19,9 +19,9 @@
package org.isoron.uhabits.fragments;
import android.annotation.SuppressLint;
import android.app.DialogFragment;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.text.format.DateFormat;
@ -29,8 +29,11 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import com.android.colorpicker.ColorPickerDialog;
@ -49,11 +52,10 @@ import org.isoron.uhabits.dialogs.WeekdayPickerDialog;
import org.isoron.uhabits.models.Habit;
import java.util.Arrays;
import java.util.Date;
public class EditHabitFragment extends DialogFragment
implements OnClickListener, WeekdayPickerDialog.OnWeekdaysPickedListener,
TimePickerDialog.OnTimeSetListener
TimePickerDialog.OnTimeSetListener, Spinner.OnItemSelectedListener
{
private Integer mode;
static final int EDIT_MODE = 0;
@ -71,6 +73,10 @@ public class EditHabitFragment extends DialogFragment
private TextView tvReminderTime;
private TextView tvReminderDays;
private Spinner sFrequency;
private ViewGroup llCustomFrequency;
private ViewGroup llReminderDays;
private SharedPreferences prefs;
private boolean is24HourMode;
@ -105,6 +111,10 @@ public class EditHabitFragment extends DialogFragment
tvReminderTime = (TextView) view.findViewById(R.id.inputReminderTime);
tvReminderDays = (TextView) view.findViewById(R.id.inputReminderDays);
sFrequency = (Spinner) view.findViewById(R.id.sFrequency);
llCustomFrequency = (ViewGroup) view.findViewById(R.id.llCustomFrequency);
llReminderDays = (ViewGroup) view.findViewById(R.id.llReminderDays);
Button buttonSave = (Button) view.findViewById(R.id.buttonSave);
Button buttonDiscard = (Button) view.findViewById(R.id.buttonDiscard);
ImageButton buttonPickColor = (ImageButton) view.findViewById(R.id.buttonPickColor);
@ -114,6 +124,7 @@ public class EditHabitFragment extends DialogFragment
tvReminderTime.setOnClickListener(this);
tvReminderDays.setOnClickListener(this);
buttonPickColor.setOnClickListener(this);
sFrequency.setOnItemSelectedListener(this);
prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
@ -163,6 +174,7 @@ public class EditHabitFragment extends DialogFragment
tvFreqDen.append(modifiedHabit.freqDen.toString());
changeColor(modifiedHabit.color);
updateFrequency();
updateReminder();
return view;
@ -183,19 +195,17 @@ public class EditHabitFragment extends DialogFragment
{
if (modifiedHabit.hasReminder())
{
tvReminderTime.setTextColor(Color.BLACK);
tvReminderTime.setText(DateHelper.formatTime(getActivity(), modifiedHabit.reminderHour,
modifiedHabit.reminderMin));
tvReminderDays.setVisibility(View.VISIBLE);
llReminderDays.setVisibility(View.VISIBLE);
boolean weekdays[] = DateHelper.unpackWeekdayList(modifiedHabit.reminderDays);
tvReminderDays.setText(DateHelper.formatWeekdayList(getActivity(), weekdays));
}
else
{
tvReminderTime.setTextColor(Color.GRAY);
tvReminderTime.setText(R.string.reminder_off);
tvReminderDays.setVisibility(View.GONE);
llReminderDays.setVisibility(View.GONE);
}
}
@ -378,4 +388,79 @@ public class EditHabitFragment extends DialogFragment
outState.putInt("reminderDays", modifiedHabit.reminderDays);
}
}
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id)
{
if(parent.getId() == R.id.sFrequency)
{
switch (position)
{
case 0:
modifiedHabit.freqNum = 1;
modifiedHabit.freqDen = 1;
break;
case 1:
modifiedHabit.freqNum = 1;
modifiedHabit.freqDen = 7;
break;
case 2:
modifiedHabit.freqNum = 2;
modifiedHabit.freqDen = 7;
break;
case 3:
modifiedHabit.freqNum = 5;
modifiedHabit.freqDen = 7;
break;
case 4:
modifiedHabit.freqNum = 3;
modifiedHabit.freqDen = 7;
break;
}
}
updateFrequency();
}
@SuppressLint("SetTextI18n")
private void updateFrequency()
{
int quickSelectPosition = -1;
if(modifiedHabit.freqNum.equals(modifiedHabit.freqDen))
quickSelectPosition = 0;
else if(modifiedHabit.freqNum == 1 && modifiedHabit.freqDen == 7)
quickSelectPosition = 1;
else if(modifiedHabit.freqNum == 2 && modifiedHabit.freqDen == 7)
quickSelectPosition = 2;
else if(modifiedHabit.freqNum == 5 && modifiedHabit.freqDen == 7)
quickSelectPosition = 3;
if(quickSelectPosition >= 0)
{
sFrequency.setVisibility(View.VISIBLE);
sFrequency.setSelection(quickSelectPosition);
llCustomFrequency.setVisibility(View.GONE);
tvFreqNum.setText(modifiedHabit.freqNum.toString());
tvFreqDen.setText(modifiedHabit.freqDen.toString());
}
else
{
sFrequency.setVisibility(View.GONE);
llCustomFrequency.setVisibility(View.VISIBLE);
}
}
@Override
public void onNothingSelected(AdapterView<?> parent)
{
}
}

@ -17,12 +17,13 @@
~ with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
<LinearLayout
android:id="@+id/container"
style="@style/dialogForm"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context="org.isoron.uhabits.fragments.EditHabitFragment"
tools:ignore="MergeRootFrame"
style="@style/dialogForm">
tools:ignore="MergeRootFrame">
<LinearLayout
android:id="@+id/formPanel"
@ -34,72 +35,97 @@
<EditText
android:id="@+id/input_name"
android:hint="@string/name"
android:inputType="textCapSentences"
style="@style/dialogFormInput">
style="@style/dialogFormInput"
android:hint="@string/name">
<requestFocus />
<requestFocus/>
</EditText>
<ImageButton
android:id="@+id/buttonPickColor"
android:src="@drawable/ic_action_color_light"
style="@style/dialogFormInputColor"
android:contentDescription="@string/color_picker_default_title"
style="@style/dialogFormInputColor" />
android:src="@drawable/ic_action_color_light"/>
</LinearLayout>
<EditText
android:id="@+id/input_description"
android:hint="@string/description_hint"
android:inputType="textCapSentences"
style="@style/dialogFormInputMultiline" />
style="@style/dialogFormInputMultiline"
android:hint="@string/description_hint"/>
<LinearLayout
style="@style/dialogFormRow"
android:gravity="start">
style="@style/dialogFormRow">
<TextView
android:id="@+id/textView1"
style="@style/dialogFormLabel"
android:text="@string/repeat" />
android:text="@string/repeat"/>
<Spinner
android:id="@+id/sFrequency"
style="@style/dialogFormSpinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:entries="@array/frequencyQuickSelect"
android:visibility="gone"/>
<org.apmem.tools.layouts.FlowLayout
android:id="@+id/llCustomFrequency"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="visible"
android:gravity="fill">
<EditText
android:id="@+id/input_freq_num"
style="@style/dialogFormInputSmallNumber" />
style="@style/dialogFormInputSmallNumber"/>
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/times_every" />
style="@style/dialogFormText"
android:text="@string/times_every"
android:gravity="center"/>
<EditText
android:id="@+id/input_freq_den"
style="@style/dialogFormInputSmallNumber" />
style="@style/dialogFormInputSmallNumber"/>
<TextView
android:id="@+id/textView5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/days" />
style="@style/dialogFormText"
android:text="@string/days"
android:gravity="center_vertical"
android:paddingLeft="12dp"/>
</org.apmem.tools.layouts.FlowLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/reminedPanel"
android:id="@+id/reminderPanel"
style="@style/dialogFormRow">
<TextView
android:id="@+id/TextView2"
style="@style/dialogFormLabel"
android:text="@string/reminder" />
android:text="@string/reminder"/>
<TextView
android:id="@+id/inputReminderTime"
style="@style/dialogFormTimePicker" />
style="@style/dialogFormSpinner"/>
</LinearLayout>
<LinearLayout
android:id="@+id/llReminderDays"
style="@style/dialogFormRow">
<TextView
android:id="@+id/TextView3"
style="@style/dialogFormLabel"
android:text=""/>
<TextView
android:id="@+id/inputReminderDays"
style="@style/dialogFormTimePicker" />
style="@style/dialogFormSpinner"/>
</LinearLayout>
</LinearLayout>
@ -110,20 +136,22 @@
android:layout_height="wrap_content"
android:gravity="end"
android:paddingEnd="16dp"
android:paddingRight="16dp">
android:paddingLeft="0dp"
android:paddingRight="16dp"
android:paddingStart="0dp">
<Button
android:id="@+id/buttonDiscard"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/discard" />
android:text="@string/discard"/>
<Button
android:id="@+id/buttonSave"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/save" />
android:text="@string/save"/>
</LinearLayout>
</LinearLayout>

@ -31,6 +31,8 @@
</style>
<style name="MyDialogStyle" parent="android:Theme.Material.Light.Dialog">
<item name="android:spinnerItemStyle">@style/dialogFormText</item>
<item name="android:spinnerDropDownItemStyle">@style/dialogFormSpinnerDropDown</item>
</style>
<style name="cardStyle" parent="cardBasicStyle">

@ -19,6 +19,8 @@
<color name="primary">#37474f</color>
<color name="primary_darker">#263238</color>
<color name="windowBackground">#e6e6e6</color>
<color name="dialogTextColor">@color/grey_800</color>
<color name="dialogFadedTextColor">@color/grey_600</color>
<color name="white">#ffffff</color>
@ -312,14 +314,14 @@
<!--<color name="orange_A400">#FF9100</color>-->
<!--<color name="orange_A700">#FF6D00</color>-->
<!--<color name="grey_50">#FAFAFA</color>-->
<color name="grey_50">#FAFAFA</color>
<color name="grey_100">#F5F5F5</color>
<!--<color name="grey_200">#EEEEEE</color>-->
<!--<color name="grey_300">#E0E0E0</color>-->
<color name="grey_200">#EEEEEE</color>
<color name="grey_300">#E0E0E0</color>
<color name="grey_400">#BDBDBD</color>
<color name="grey_500">#9E9E9E</color>
<!--<color name="grey_600">#757575</color>-->
<!--<color name="grey_700">#616161</color>-->
<!--<color name="grey_800">#424242</color>-->
<!--<color name="grey_900">#212121</color>-->
<color name="grey_600">#757575</color>
<color name="grey_700">#616161</color>
<color name="grey_800">#424242</color>
<color name="grey_900">#212121</color>
</resources>

@ -42,5 +42,13 @@
<item>480</item>
</string-array>
<string-array name="frequencyQuickSelect" translatable="false">
<item>@string/every_day</item>
<item>@string/every_week</item>
<item>@string/two_times_per_week</item>
<item>@string/five_times_per_week</item>
<item>@string/custom_frequency</item>
</string-array>
<string name="snooze_interval_default" translatable="false">15</string>
</resources>

@ -131,4 +131,10 @@
<string name="last_x_months">Last %d months</string>
<string name="last_x_years">Last %d years</string>
<string name="all_time">All time</string>
<string name="every_day">Every day</string>
<string name="every_week">Every week</string>
<string name="two_times_per_week">2 times per week</string>
<string name="five_times_per_week">2 times per week</string>
<string name="custom_frequency">Custom …</string>
</resources>

@ -19,7 +19,10 @@
<resources>
<style name="AppBaseTheme" parent="android:Theme.Holo.Light" />
<style name="AppBaseTheme" parent="android:Theme.Holo.Light">
<item name="android:spinnerItemStyle">@style/dialogFormText</item>
<item name="android:spinnerDropDownItemStyle">@style/dialogFormSpinnerDropDown</item>
</style>
<style name="time_label">
<item name="android:textSize">@dimen/time_label_size</item>
@ -33,7 +36,7 @@
<item name="android:textStyle">bold</item>
</style>
<style name="day_of_week_label_condensed" />
<style name="day_of_week_label_condensed"/>
<style name="cardsListStyle">
<item name="android:layout_width">match_parent</item>

@ -20,7 +20,7 @@
<resources>
<style name="dialogFormInputMultiline">
<style name="dialogFormInputMultiline" parent="dialogFormInput">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:ems">10</item>
@ -34,7 +34,7 @@
<item name="android:background">?android:attr/selectableItemBackground</item>
</style>
<style name="dialogFormInputSmallNumber">
<style name="dialogFormInputSmallNumber" parent="dialogFormInput">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:ems">2</item>
@ -43,40 +43,57 @@
<item name="android:maxLength">2</item>
</style>
<style name="dialogFormInput">
<style name="dialogFormText">
<item name="android:textSize">16sp</item>
<item name="android:textColor">@color/dialogTextColor</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
</style>
<style name="dialogFormSpinnerDropDown" parent="dialogFormText">
<item name="android:padding">12dp</item>
<item name="android:textColor">@color/dialogTextColor</item>
</style>
<style name="dialogFormInput" parent="dialogFormText">
<item name="android:layout_width">0dp</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_weight">10</item>
<item name="android:ems">10</item>
<item name="android:inputType">textCapSentences</item>
</style>
<style name="dialogFormLabel">
<style name="dialogFormLabel" parent="dialogFormText">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:width">80dp</item>
<item name="android:gravity">right</item>
<item name="android:paddingRight">9dp</item>
<item name="android:width">100dp</item>
<item name="android:gravity">left</item>
<item name="android:paddingLeft">6dp</item>
<item name="android:textColor">@color/dialogFadedTextColor</item>
</style>
<style name="dialogFormTimePicker" parent="android:Widget.DeviceDefault.Light.Spinner">
<item name="android:layout_width">wrap_content</item>
<style name="dialogFormSpinner" parent="android:Widget.DeviceDefault.Light.Spinner">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:paddingLeft">12dp</item>
<item name="android:textSize">16sp</item>
<item name="android:minWidth">400dp</item>
<item name="android:textColor">@color/dialogTextColor</item>
</style>
<style name="dialogFormRow">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_marginTop">8dp</item>
<item name="android:layout_marginTop">12dp</item>
<item name="android:orientation">horizontal</item>
<item name="android:minWidth">300dp</item>
<item name="android:gravity">start|center_vertical</item>
</style>
<style name="dialogForm">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">match_parent</item>
<item name="android:orientation">vertical</item>
<item name="android:paddingBottom">8dp</item>
</style>
<style name="dialogFormPanel">

Loading…
Cancel
Save