Reorganizing

pull/30/head
Alinson S. Xavier 10 years ago
parent a1f05714ba
commit de02e119d1

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="uHabits" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<module external.linked.project.id=":app" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$USER_HOME$/Android/uHabits" external.system.id="GRADLE" external.system.module.group="uHabits" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android-gradle" name="Android-Gradle">
<configuration>
@ -12,8 +12,9 @@
<option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
<option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugAndroidTest" />
<option name="SOURCE_GEN_TASK_NAME" value="generateDebugSources" />
<option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugAndroidTest" />
<option name="COMPILE_JAVA_TEST_TASK_NAME" value="compileDebugAndroidTestSources" />
<option name="TEST_SOURCE_GEN_TASK_NAME" value="generateDebugAndroidTestSources" />
<option name="ALLOW_USER_CONFIGURATION" value="false" />
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
@ -89,5 +90,4 @@
<orderEntry type="library" exported="" name="ActiveAndroid" level="project" />
<orderEntry type="library" exported="" name="support-annotations-22.0.0" level="project" />
</component>
</module>
</module>

@ -14,7 +14,7 @@
<application
android:name="com.activeandroid.app.Application"
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

@ -6,6 +6,7 @@ import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
@ -125,25 +126,24 @@ public class MainActivity extends Activity
return super.onOptionsItemSelected(item);
}
public void executeCommand(Command command, boolean datasetChanged)
public void executeCommand(Command command)
{
executeCommand(command, datasetChanged, true);
executeCommand(command, false);
}
public void executeCommand(Command command, boolean datasetChanged, boolean clearRedoStack)
public void executeCommand(Command command, boolean clearRedoStack)
{
undoList.push(command);
if (undoList.size() > MAX_UNDO_LEVEL)
undoList.removeLast();
if (clearRedoStack)
redoList.clear();
command.execute();
listHabitsFragment.notifyDataSetChanged();
showToast(command.getExecuteStringId());
if (datasetChanged)
{
listHabitsFragment.notifyDataSetChanged();
}
}
public void undo()
@ -170,7 +170,7 @@ public class MainActivity extends Activity
return;
}
Command last = redoList.pop();
executeCommand(last, true, false);
executeCommand(last, false);
}
private void showToast(Integer stringId)

@ -1,12 +1,6 @@
package org.isoron.uhabits;
import java.util.Date;
import java.util.List;
import org.isoron.uhabits.models.Habit;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
@ -14,148 +8,133 @@ import android.content.BroadcastReceiver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.media.RingtoneManager;
import android.net.Uri;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import org.isoron.uhabits.models.Habit;
import java.util.Date;
public class ReminderAlarmReceiver extends BroadcastReceiver
{
public static String ACTION_CHECK = "org.isoron.uhabits.ACTION_CHECK";
public static String ACTION_DISMISS = "org.isoron.uhabits.ACTION_DISMISS";
public static String ACTION_REMIND = "org.isoron.uhabits.ACTION_REMIND";
public static String ACTION_REMOVE_REMINDER = "org.isoron.uhabits.ACTION_REMOVE_REMINDER";
public static String ACTION_SNOOZE = "org.isoron.uhabits.ACTION_SNOOZE";
@Override
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if(action.equals(ACTION_REMIND))
createNotification(context, intent.getData());
else if(action.equals(ACTION_DISMISS))
dismissAllHabits();
else if(action.equals(ACTION_CHECK))
checkHabit(context, intent.getData());
else if(action.equals(ACTION_SNOOZE))
snoozeHabit(context, intent.getData());
}
private void snoozeHabit(Context context, Uri data)
{
int delayMinutes = 15;
Habit habit = Habit.get(ContentUris.parseId(data));
MainActivity.createReminderAlarm(context, habit, new Date().getTime() + delayMinutes * 1000);
dismissNotification(context);
}
private void checkHabit(Context context, Uri data)
{
Habit habit = Habit.get(ContentUris.parseId(data));
habit.toggleRepetitionToday();
habit.save();
dismissNotification(context);
}
private void dismissAllHabits()
{
for(Habit h : Habit.getHighlightedHabits())
{
Log.d("Alarm", String.format("Removing highlight from: %s", h.name));
h.highlight = 0;
h.save();
}
}
private void dismissNotification(Context context)
{
NotificationManager notificationManager = (NotificationManager) context
.getSystemService(Activity.NOTIFICATION_SERVICE);
notificationManager.cancel(1);
}
private void createNotification(Context context, Uri data)
{
Log.d("Alarm", "Alarm received!");
Habit habit = Habit.get(ContentUris.parseId(data));
if(habit.hasImplicitRepToday())
{
Log.d("Alarm", String.format("(%s) has implicit rep today", habit.name));
return;
}
Log.d("Alarm", String.format("Applying highlight: %s", habit.name));
habit.highlight = 1;
habit.save();
// Check if reminder has been turned off after alarm was scheduled
if(habit.reminder_hour == null)
return;
Intent contentIntent = new Intent(context, MainActivity.class);
contentIntent.setData(data);
PendingIntent contentPendingIntent = PendingIntent.getActivity(context, 0, contentIntent, 0);
Intent deleteIntent = new Intent(context, ReminderAlarmReceiver.class);
deleteIntent.setAction(ACTION_DISMISS);
PendingIntent deletePendingIntent = PendingIntent.getBroadcast(context, 0, deleteIntent, 0);
Intent checkIntent = new Intent(context, ReminderAlarmReceiver.class);
checkIntent.setData(data);
checkIntent.setAction(ACTION_CHECK);
PendingIntent checkIntentPending = PendingIntent.getBroadcast(context, 0, checkIntent, 0);
Intent snoozeIntent = new Intent(context, ReminderAlarmReceiver.class);
snoozeIntent.setData(data);
snoozeIntent.setAction(ACTION_SNOOZE);
PendingIntent snoozeIntentPending = PendingIntent.getBroadcast(context, 0, snoozeIntent, 0);
Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
inboxStyle.setBigContentTitle("Habit Reminder:");
List<Habit> pendingHabits = Habit.getHighlightedHabits();
StringBuffer contentText = new StringBuffer();
for(Habit h : pendingHabits)
{
if(h.hasImplicitRepToday())
continue;
inboxStyle.addLine(h.name);
if(contentText.length() > 0)
contentText.append(", ");
contentText.append(h.name);
Log.d("Alarm", String.format("Found highlighted: %s", h.name));
}
Notification notification =
new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_notification)
.setContentTitle("Habit Reminder")
.setContentText(contentText)
.setContentIntent(contentPendingIntent)
.setDeleteIntent(deletePendingIntent)
.addAction(R.drawable.ic_action_check, "Check", checkIntentPending)
.addAction(R.drawable.ic_action_snooze, "Later", snoozeIntentPending)
.setSound(soundUri)
.setStyle(inboxStyle)
.build();
notification.flags |= Notification.FLAG_AUTO_CANCEL;
NotificationManager notificationManager = (NotificationManager) context
.getSystemService(Activity.NOTIFICATION_SERVICE);
notificationManager.notify(1, notification);
}
public static String ACTION_CHECK = "org.isoron.uhabits.ACTION_CHECK";
public static String ACTION_DISMISS = "org.isoron.uhabits.ACTION_DISMISS";
public static String ACTION_REMIND = "org.isoron.uhabits.ACTION_REMIND";
public static String ACTION_REMOVE_REMINDER = "org.isoron.uhabits.ACTION_REMOVE_REMINDER";
public static String ACTION_SNOOZE = "org.isoron.uhabits.ACTION_SNOOZE";
@Override
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if (action.equals(ACTION_REMIND)) createNotification(context, intent.getData());
else if (action.equals(ACTION_DISMISS)) dismissAllHabits();
else if (action.equals(ACTION_CHECK)) checkHabit(context, intent.getData());
else if (action.equals(ACTION_SNOOZE)) snoozeHabit(context, intent.getData());
}
private void snoozeHabit(Context context, Uri data)
{
int delayMinutes = 60;
Habit habit = Habit.get(ContentUris.parseId(data));
MainActivity.createReminderAlarm(context, habit,
new Date().getTime() + delayMinutes * 60 * 1000);
dismissNotification(context, habit);
}
private void checkHabit(Context context, Uri data)
{
Habit habit = Habit.get(ContentUris.parseId(data));
habit.toggleRepetitionToday();
habit.save();
dismissNotification(context, habit);
}
private void dismissAllHabits()
{
for (Habit h : Habit.getHighlightedHabits())
{
h.highlight = 0;
h.save();
}
}
private void dismissNotification(Context context, Habit habit)
{
NotificationManager notificationManager =
(NotificationManager) context.getSystemService(Activity.NOTIFICATION_SERVICE);
int notificationId = (int) (habit.getId() % Integer.MAX_VALUE);
notificationManager.cancel(notificationId);
}
private void createNotification(Context context, Uri data)
{
Habit habit = Habit.get(ContentUris.parseId(data));
if (habit.hasImplicitRepToday()) return;
Log.d("Alarm", String.format("Applying highlight: %s", habit.name));
habit.highlight = 1;
habit.save();
// Check if reminder has been turned off after alarm was scheduled
if (habit.reminder_hour == null) return;
Intent contentIntent = new Intent(context, MainActivity.class);
contentIntent.setData(data);
PendingIntent contentPendingIntent =
PendingIntent.getActivity(context, 0, contentIntent, 0);
Intent deleteIntent = new Intent(context, ReminderAlarmReceiver.class);
deleteIntent.setAction(ACTION_DISMISS);
PendingIntent deletePendingIntent = PendingIntent.getBroadcast(context, 0, deleteIntent, 0);
Intent checkIntent = new Intent(context, ReminderAlarmReceiver.class);
checkIntent.setData(data);
checkIntent.setAction(ACTION_CHECK);
PendingIntent checkIntentPending = PendingIntent.getBroadcast(context, 0, checkIntent, 0);
Intent snoozeIntent = new Intent(context, ReminderAlarmReceiver.class);
snoozeIntent.setData(data);
snoozeIntent.setAction(ACTION_SNOOZE);
PendingIntent snoozeIntentPending = PendingIntent.getBroadcast(context, 0, snoozeIntent, 0);
Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.WearableExtender wearableExtender =
new NotificationCompat.WearableExtender().setBackground(
BitmapFactory.decodeResource(context.getResources(), R.drawable.stripe));
Notification notification =
new NotificationCompat.Builder(context).setSmallIcon(R.drawable.ic_notification)
.setContentTitle(habit.name)
.setContentText(habit.description)
.setContentIntent(contentPendingIntent)
.setDeleteIntent(deletePendingIntent)
.addAction(R.drawable.ic_action_check, "Check", checkIntentPending)
.addAction(R.drawable.ic_action_snooze, "Later", snoozeIntentPending)
.setSound(soundUri)
.extend(wearableExtender)
.build();
notification.flags |= Notification.FLAG_AUTO_CANCEL;
NotificationManager notificationManager =
(NotificationManager) context.getSystemService(Activity.NOTIFICATION_SERVICE);
int notificationId = (int) (habit.getId() % Integer.MAX_VALUE);
notificationManager.notify(notificationId, notification);
}
}

@ -1,18 +1,5 @@
package org.isoron.uhabits.dialogs;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;
import org.isoron.helpers.Command;
import org.isoron.helpers.DateHelper;
import org.isoron.helpers.DialogHelper.OnSavedListener;
import org.isoron.uhabits.MainActivity;
import org.isoron.uhabits.R;
import org.isoron.uhabits.ShowHabitActivity;
import org.isoron.uhabits.models.Habit;
import android.app.Fragment;
import android.content.Context;
import android.content.Intent;
@ -20,9 +7,9 @@ import android.graphics.Color;
import android.graphics.Point;
import android.graphics.Typeface;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Vibrator;
import android.transition.Explode;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.ContextMenu;
@ -50,362 +37,359 @@ import com.mobeta.android.dslv.DragSortController;
import com.mobeta.android.dslv.DragSortListView;
import com.mobeta.android.dslv.DragSortListView.DropListener;
public class ListHabitsFragment extends Fragment implements OnSavedListener, OnItemClickListener,
OnLongClickListener, DropListener, OnClickListener
import org.isoron.helpers.Command;
import org.isoron.helpers.DateHelper;
import org.isoron.helpers.DialogHelper.OnSavedListener;
import org.isoron.uhabits.MainActivity;
import org.isoron.uhabits.R;
import org.isoron.uhabits.ShowHabitActivity;
import org.isoron.uhabits.models.Habit;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;
public class ListHabitsFragment extends Fragment
implements OnSavedListener, OnItemClickListener, OnLongClickListener, DropListener,
OnClickListener
{
private int tvNameWidth;
private int button_count;
ListHabitsAdapter adapter;
DragSortListView listView;
MainActivity mainActivity;
TextView tvNameHeader;
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Adapter *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
class ListHabitsAdapter extends BaseAdapter
{
private Context context;
private LayoutInflater inflater;
private Typeface fontawesome;
String habits[] = { "wake up early", "work out", "meditate", "take vitamins",
"go to school",
"cook dinner & lunch" };
public ListHabitsAdapter(Context context)
{
this.context = context;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
fontawesome = Typeface.createFromAsset(context.getAssets(), "fontawesome-webfont.ttf");
}
@Override
public int getCount()
{
return Habit.getCount();
}
@Override
public Object getItem(int position)
{
return Habit.getByPosition(position);
}
@Override
public long getItemId(int position)
{
return ((Habit) getItem(position)).getId();
}
@Override
public View getView(int position, View view, ViewGroup parent)
{
final Habit habit = (Habit) getItem(position);
if(view == null || (Long) view.getTag(R.id.KEY_TIMESTAMP) != DateHelper.getStartOfToday())
{
view = inflater.inflate(R.layout.list_habits_item, null);
((TextView) view.findViewById(R.id.tvStar)).setTypeface(fontawesome);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(tvNameWidth,
LayoutParams.WRAP_CONTENT, 1);
((TextView) view.findViewById(R.id.tvName)).setLayoutParams(params);
Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay();
Point size = new Point();
display.getSize(size);
LinearLayout.LayoutParams llp = new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
llp.setMargins(2, 0, 2, 0);
for (int i = 0; i < button_count; i++)
{
View check = inflater.inflate(R.layout.list_habits_item_check, null);
TextView btCheck = (TextView) check.findViewById(R.id.tvCheck);
btCheck.setTypeface(fontawesome);
btCheck.setOnLongClickListener(ListHabitsFragment.this);
ListHabitsAdapter adapter;
DragSortListView listView;
MainActivity mainActivity;
TextView tvNameHeader;
long lastLongClick = 0;
private int tvNameWidth;
private int button_count;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.list_habits_fragment, container, false);
DisplayMetrics dm = getResources().getDisplayMetrics();
int width = (int) (dm.widthPixels / dm.density);
button_count = (int) ((width - 160) / 42);
tvNameWidth = (int) ((width - 30 - button_count * 42) * dm.density);
tvNameHeader = (TextView) view.findViewById(R.id.tvNameHeader);
// updateStarCount();
adapter = new ListHabitsAdapter(getActivity());
listView = (DragSortListView) view.findViewById(R.id.listView);
listView.setAdapter(adapter);
listView.setOnItemClickListener(this);
registerForContextMenu(listView);
listView.setDropListener(this);
DragSortController controller = new DragSortController(listView);
controller.setDragHandleId(R.id.tvStar);
controller.setRemoveEnabled(false);
controller.setSortEnabled(true);
controller.setDragInitMode(1);
listView.setFloatViewManager(controller);
listView.setOnTouchListener(controller);
listView.setDragEnabled(true);
GregorianCalendar day = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
day.setTimeInMillis(DateHelper.getStartOfDay(DateHelper.getLocalTime()));
for (int i = 0; i < button_count; i++)
{
View check = inflater.inflate(R.layout.list_habits_header_check, null);
Button btCheck = (Button) check.findViewById(R.id.tvCheck);
btCheck.setText(
day.getDisplayName(GregorianCalendar.DAY_OF_WEEK, GregorianCalendar.SHORT,
Locale.US) + "\n" +
Integer.toString(day.get(GregorianCalendar.DAY_OF_MONTH)));
((LinearLayout) view.findViewById(R.id.llButtonsHeader)).addView(check);
day.add(GregorianCalendar.DAY_OF_MONTH, -1);
}
mainActivity = (MainActivity) getActivity();
setHasOptionsMenu(true);
return view;
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
{
inflater.inflate(R.menu.show_habits_options, menu);
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo)
{
super.onCreateContextMenu(menu, view, menuInfo);
getActivity().getMenuInflater().inflate(R.menu.show_habits_context, menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
int id = item.getItemId();
if (id == R.id.action_add)
{
EditHabitFragment frag = EditHabitFragment.createHabitFragment();
frag.setOnSavedListener(this);
frag.show(getFragmentManager(), "dialog");
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public boolean onContextItemSelected(MenuItem menuItem)
{
AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuItem.getMenuInfo();
final int id = menuItem.getItemId();
final Habit habit = Habit.get(info.id);
if (id == R.id.action_edit_habit)
{
EditHabitFragment frag = EditHabitFragment.editSingleHabitFragment(habit.getId());
frag.setOnSavedListener(this);
frag.show(getFragmentManager(), "dialog");
return true;
}
return super.onContextItemSelected(menuItem);
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
if (new Date().getTime() - lastLongClick < 1000) return;
Habit habit = Habit.getByPosition(position);
Log.d("ItemClick", Long.toString(id));
Intent intent = new Intent(getActivity(), ShowHabitActivity.class);
intent.setData(Uri.parse("content://org.isoron.uhabits/habit/" + habit.getId()));
startActivity(intent);
}
@Override
public void onSaved(Command command)
{
executeCommand(command);
MainActivity.createReminderAlarms(mainActivity);
}
public void notifyDataSetChanged()
{
adapter.notifyDataSetChanged();
}
@Override
public boolean onLongClick(View v)
{
int id = v.getId();
if (id == R.id.tvCheck)
{
lastLongClick = new Date().getTime();
Habit habit = Habit.get((Long) v.getTag(R.string.habit_key));
int offset = (Integer) v.getTag(R.string.offset_key);
long timestamp = DateHelper.getStartOfDay(
DateHelper.getLocalTime() - offset * DateHelper.millisecondsInOneDay);
executeCommand(habit.new ToggleRepetitionCommand(timestamp));
Vibrator vb = (Vibrator) getActivity().getSystemService(Context.VIBRATOR_SERVICE);
vb.vibrate(100);
return true;
}
return false;
}
private void executeCommand(Command c)
{
mainActivity.executeCommand(c);
}
@Override
public void drop(int from, int to)
{
Habit.reorder(from, to);
notifyDataSetChanged();
}
@Override
public void onClick(View v)
{
}
void updateStarCount()
{
Log.d("StarCount", "updating star count");
String msg = "";
int starCount = Habit.getStarCount();
if (starCount == 1) msg = String.format("%d star", starCount);
else if (starCount > 1) msg = String.format("%d stars", starCount);
tvNameHeader.setText(msg);
}
class ListHabitsAdapter extends BaseAdapter
{
String habits[] = {"wake up early", "work out", "meditate", "take vitamins", "go to school",
"cook dinner & lunch"};
private Context context;
private LayoutInflater inflater;
private Typeface fontawesome;
public ListHabitsAdapter(Context context)
{
this.context = context;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
fontawesome = Typeface.createFromAsset(context.getAssets(), "fontawesome-webfont.ttf");
}
@Override
public int getCount()
{
return Habit.getCount();
}
@Override
public Object getItem(int position)
{
return Habit.getByPosition(position);
}
@Override
public long getItemId(int position)
{
return ((Habit) getItem(position)).getId();
}
@Override
public View getView(int position, View view, ViewGroup parent)
{
final Habit habit = (Habit) getItem(position);
if (view == null ||
(Long) view.getTag(R.id.KEY_TIMESTAMP) != DateHelper.getStartOfToday())
{
view = inflater.inflate(R.layout.list_habits_item, null);
((TextView) view.findViewById(R.id.tvStar)).setTypeface(fontawesome);
LinearLayout.LayoutParams params =
new LinearLayout.LayoutParams(tvNameWidth, LayoutParams.WRAP_CONTENT, 1);
((TextView) view.findViewById(R.id.tvName)).setLayoutParams(params);
Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay();
Point size = new Point();
display.getSize(size);
LinearLayout.LayoutParams llp =
new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
llp.setMargins(2, 0, 2, 0);
for (int i = 0; i < button_count; i++)
{
View check = inflater.inflate(R.layout.list_habits_item_check, null);
TextView btCheck = (TextView) check.findViewById(R.id.tvCheck);
btCheck.setTypeface(fontawesome);
btCheck.setOnLongClickListener(ListHabitsFragment.this);
// btCheck.setLayoutParams(llp);
((LinearLayout) view.findViewById(R.id.llButtons)).addView(check);
}
((LinearLayout) view.findViewById(R.id.llButtons)).addView(check);
}
// LinearLayout llInner = (LinearLayout) view.findViewById(R.id.llInner);
// llInner.setOnClickListener(ListHabitsFragment.this);
view.setTag(R.id.KEY_TIMESTAMP, DateHelper.getStartOfToday());
}
TextView tvStar = (TextView) view.findViewById(R.id.tvStar);
TextView tvName = (TextView) view.findViewById(R.id.tvName);
if(habit == null)
{
tvName.setText(null);
return view;
}
LinearLayout llInner = (LinearLayout) view.findViewById(R.id.llInner);
llInner.setTag(R.string.habit_key, habit.getId());
int inactiveColor = Color.rgb(230, 230, 230);
int activeColor = habit.color;
tvName.setText(habit.name);
tvName.setTextColor(activeColor);
int score = habit.getScore();
if(score < Habit.HALF_STAR_CUTOFF)
{
tvStar.setText(context.getString(R.string.fa_star_o));
tvStar.setTextColor(inactiveColor);
}
else if(score < Habit.FULL_STAR_CUTOFF)
{
tvStar.setText(context.getString(R.string.fa_star_half_o));
tvStar.setTextColor(inactiveColor);
}
else
{
tvStar.setText(context.getString(R.string.fa_star));
tvStar.setTextColor(activeColor);
}
LinearLayout llButtons = (LinearLayout) view.findViewById(R.id.llButtons);
int m = llButtons.getChildCount();
long dateTo = DateHelper.getStartOfDay(DateHelper.getLocalTime());
long dateFrom = dateTo - m * DateHelper.millisecondsInOneDay;
int isChecked[] = habit.getReps(dateFrom, dateTo);
for (int i = 0; i < m; i++)
{
TextView tvCheck = (TextView) llButtons.getChildAt(i);
tvCheck.setTag(R.string.habit_key, habit.getId());
tvCheck.setTag(R.string.offset_key, i);
switch(isChecked[i])
{
case 2:
tvCheck.setText(R.string.fa_check);
tvCheck.setTextColor(activeColor);
break;
case 1:
tvCheck.setText(R.string.fa_check);
tvCheck.setTextColor(inactiveColor);
break;
case 0:
tvCheck.setText(R.string.fa_times);
tvCheck.setTextColor(inactiveColor);
break;
}
}
return view;
}
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Creation *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.list_habits_fragment, container, false);
DisplayMetrics dm = getResources().getDisplayMetrics();
int width = (int) (dm.widthPixels / dm.density);
button_count = (int) ((width - 160) / 42);
tvNameWidth = (int) ((width - 30 - button_count * 42) * dm.density);
tvNameHeader = (TextView) view.findViewById(R.id.tvNameHeader);
// updateStarCount();
adapter = new ListHabitsAdapter(getActivity());
listView = (DragSortListView) view.findViewById(R.id.listView);
listView.setAdapter(adapter);
listView.setOnItemClickListener(this);
registerForContextMenu(listView);
listView.setDropListener(this);
DragSortController controller = new DragSortController(listView);
controller.setDragHandleId(R.id.tvStar);
controller.setRemoveEnabled(false);
controller.setSortEnabled(true);
controller.setDragInitMode(1);
listView.setFloatViewManager(controller);
listView.setOnTouchListener(controller);
listView.setDragEnabled(true);
GregorianCalendar day = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
day.setTimeInMillis(DateHelper.getStartOfDay(DateHelper.getLocalTime()));
for (int i = 0; i < button_count; i++)
{
View check = inflater.inflate(R.layout.list_habits_header_check, null);
Button btCheck = (Button) check.findViewById(R.id.tvCheck);
btCheck.setText(day.getDisplayName(GregorianCalendar.DAY_OF_WEEK,
GregorianCalendar.SHORT, Locale.US) + "\n"
+ Integer.toString(day.get(GregorianCalendar.DAY_OF_MONTH)));
((LinearLayout) view.findViewById(R.id.llButtonsHeader)).addView(check);
day.add(GregorianCalendar.DAY_OF_MONTH, -1);
}
mainActivity = (MainActivity) getActivity();
setHasOptionsMenu(true);
return view;
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
{
inflater.inflate(R.menu.show_habits_options, menu);
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo)
{
super.onCreateContextMenu(menu, view, menuInfo);
getActivity().getMenuInflater().inflate(R.menu.show_habits_context, menu);
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Callback *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
int id = item.getItemId();
if(id == R.id.action_add)
{
EditHabitFragment frag = EditHabitFragment.createHabitFragment();
frag.setOnSavedListener(this);
frag.show(getFragmentManager(), "dialog");
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public boolean onContextItemSelected(MenuItem menuItem)
{
AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuItem.getMenuInfo();
final int id = menuItem.getItemId();
final Habit habit = Habit.get(info.id);
if(id == R.id.action_edit_habit)
{
EditHabitFragment frag = EditHabitFragment.editSingleHabitFragment(habit.getId());
frag.setOnSavedListener(this);
frag.show(getFragmentManager(), "dialog");
return true;
}
return super.onContextItemSelected(menuItem);
}
long lastLongClick = 0;
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
if(new Date().getTime() - lastLongClick < 1000) return;
Habit habit = Habit.getByPosition(position);
Log.d("ItemClick", Long.toString(id));
Intent intent = new Intent(getActivity(), ShowHabitActivity.class);
intent.setData(Uri.parse("content://org.isoron.uhabits/habit/"
+ habit.getId()));
startActivity(intent);
}
@Override
public void onSaved(Command command)
{
executeCommand(command);
MainActivity.createReminderAlarms(mainActivity);
}
public void notifyDataSetChanged()
{
adapter.notifyDataSetChanged();
}
@Override
public boolean onLongClick(View v)
{
int id = v.getId();
if(id == R.id.tvCheck)
{
lastLongClick = new Date().getTime();
Habit habit = Habit.get((Long) v.getTag(R.string.habit_key));
int offset = (Integer) v.getTag(R.string.offset_key);
long timestamp = DateHelper.getStartOfDay(DateHelper.getLocalTime() - offset
* DateHelper.millisecondsInOneDay);
executeCommand(habit.new ToggleRepetitionCommand(timestamp));
Vibrator vb = (Vibrator) getActivity().getSystemService(Context.VIBRATOR_SERVICE);
vb.vibrate(100);
return true;
}
return false;
}
private void executeCommand(Command c)
{
mainActivity.executeCommand(c, false);
notifyDataSetChanged();
}
@Override
public void drop(int from, int to)
{
Habit.reorder(from, to);
notifyDataSetChanged();
}
@Override
public void onClick(View v)
{
}
void updateStarCount()
{
Log.d("StarCount", "updating star count");
String msg = "";
int starCount = Habit.getStarCount();
if(starCount == 1)
msg = String.format("%d star", starCount);
else if(starCount > 1)
msg = String.format("%d stars", starCount);
tvNameHeader.setText(msg);
}
view.setTag(R.id.KEY_TIMESTAMP, DateHelper.getStartOfToday());
}
TextView tvStar = (TextView) view.findViewById(R.id.tvStar);
TextView tvName = (TextView) view.findViewById(R.id.tvName);
if (habit == null)
{
tvName.setText(null);
return view;
}
LinearLayout llInner = (LinearLayout) view.findViewById(R.id.llInner);
llInner.setTag(R.string.habit_key, habit.getId());
int inactiveColor = Color.rgb(230, 230, 230);
int activeColor = habit.color;
tvName.setText(habit.name);
tvName.setTextColor(activeColor);
int score = habit.getScore();
if (score < Habit.HALF_STAR_CUTOFF)
{
tvStar.setText(context.getString(R.string.fa_star_o));
tvStar.setTextColor(inactiveColor);
} else if (score < Habit.FULL_STAR_CUTOFF)
{
tvStar.setText(context.getString(R.string.fa_star_half_o));
tvStar.setTextColor(inactiveColor);
} else
{
tvStar.setText(context.getString(R.string.fa_star));
tvStar.setTextColor(activeColor);
}
LinearLayout llButtons = (LinearLayout) view.findViewById(R.id.llButtons);
int m = llButtons.getChildCount();
long dateTo = DateHelper.getStartOfDay(DateHelper.getLocalTime());
long dateFrom = dateTo - m * DateHelper.millisecondsInOneDay;
int isChecked[] = habit.getReps(dateFrom, dateTo);
for (int i = 0; i < m; i++)
{
TextView tvCheck = (TextView) llButtons.getChildAt(i);
tvCheck.setTag(R.string.habit_key, habit.getId());
tvCheck.setTag(R.string.offset_key, i);
switch (isChecked[i])
{
case 2:
tvCheck.setText(R.string.fa_check);
tvCheck.setTextColor(activeColor);
break;
case 1:
tvCheck.setText(R.string.fa_check);
tvCheck.setTextColor(inactiveColor);
break;
case 0:
tvCheck.setText(R.string.fa_times);
tvCheck.setTextColor(inactiveColor);
break;
}
}
return view;
}
}
}

@ -1,49 +1,42 @@
package org.isoron.uhabits.dialogs;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;
import org.isoron.helpers.ColorHelper;
import org.isoron.helpers.DateHelper;
import org.isoron.uhabits.R;
import org.isoron.uhabits.ShowHabitActivity;
import org.isoron.uhabits.models.Habit;
import org.isoron.uhabits.views.HabitHistoryView;
import org.isoron.uhabits.views.HabitStreakView;
import org.isoron.uhabits.views.RingView;
import android.app.Fragment;
import android.graphics.Color;
import android.graphics.Typeface;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;
import org.isoron.helpers.ColorHelper;
import org.isoron.uhabits.R;
import org.isoron.uhabits.ShowHabitActivity;
import org.isoron.uhabits.models.Habit;
import org.isoron.uhabits.views.HabitHistoryView;
import org.isoron.uhabits.views.HabitScoreView;
import org.isoron.uhabits.views.HabitStreakView;
import org.isoron.uhabits.views.RingView;
public class ShowHabitFragment extends Fragment
{
protected ShowHabitActivity activity;
protected ShowHabitActivity activity;
@Override
public void onStart()
{
super.onStart();
}
public void onStart()
{
super.onStart();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
Log.d("ShowHabitActivity", "Creating view...");
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
Log.d("ShowHabitActivity", "Creating view...");
View view = inflater.inflate(R.layout.show_habit, container, false);
activity = (ShowHabitActivity) getActivity();
View view = inflater.inflate(R.layout.show_habit, container, false);
activity = (ShowHabitActivity) getActivity();
Habit habit = activity.habit;
if (android.os.Build.VERSION.SDK_INT >= 21)
@ -52,26 +45,34 @@ public class ShowHabitFragment extends Fragment
activity.getWindow().setStatusBarColor(darkerHabitColor);
}
TextView tvHistory = (TextView) view.findViewById(R.id.tvHistory);
TextView tvOverview = (TextView) view.findViewById(R.id.tvOverview);
TextView tvStreaks= (TextView) view.findViewById(R.id.tvStreaks);
tvHistory.setTextColor(habit.color);
tvOverview.setTextColor(habit.color);
TextView tvHistory = (TextView) view.findViewById(R.id.tvHistory);
TextView tvOverview = (TextView) view.findViewById(R.id.tvOverview);
TextView tvStrength = (TextView) view.findViewById(R.id.tvStrength);
TextView tvStreaks = (TextView) view.findViewById(R.id.tvStreaks);
tvHistory.setTextColor(habit.color);
tvOverview.setTextColor(habit.color);
tvStrength.setTextColor(habit.color);
tvStreaks.setTextColor(habit.color);
LinearLayout llOverview = (LinearLayout) view.findViewById(R.id.llOverview);
llOverview.addView(new RingView(activity, 200, habit.color, ((float) habit.getScore() / Habit.MAX_SCORE), "Habit strength"));
llOverview.addView(new RingView(activity,
(int) activity.getResources().getDimension(R.dimen.small_square_size) * 4, habit.color,
((float) habit.getScore() / Habit.MAX_SCORE), "Habit strength"));
LinearLayout llStrength = (LinearLayout) view.findViewById(R.id.llStrength);
llStrength.addView(new HabitScoreView(activity, habit,
(int) activity.getResources().getDimension(R.dimen.small_square_size)));
LinearLayout llHistory = (LinearLayout) view.findViewById(R.id.llHistory);
LinearLayout llHistory = (LinearLayout) view.findViewById(R.id.llHistory);
HabitHistoryView hhv = new HabitHistoryView(activity, habit,
(int) activity.getResources().getDimension(R.dimen.square_size));
(int) activity.getResources().getDimension(R.dimen.small_square_size));
llHistory.addView(hhv);
LinearLayout llStreaks = (LinearLayout) view.findViewById(R.id.llStreaks);
HabitStreakView hsv = new HabitStreakView(activity, habit,
(int) activity.getResources().getDimension(R.dimen.square_size));
(int) activity.getResources().getDimension(R.dimen.small_square_size));
llStreaks.addView(hsv);
return view;
}
return view;
}
}

@ -3,6 +3,7 @@ package org.isoron.uhabits.models;
import android.annotation.SuppressLint;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.AsyncTask;
import android.util.Log;
import com.activeandroid.Cache;
@ -20,6 +21,7 @@ import org.isoron.helpers.Command;
import org.isoron.helpers.DateHelper;
import org.isoron.uhabits.R;
import java.util.Date;
import java.util.List;
@Table(name = "Habits")
@ -77,8 +79,7 @@ public class Habit extends Model
@SuppressLint("DefaultLocale")
public static void updateId(long oldId, long newId)
{
SQLiteUtils.execSql(String.format(
"update Habits set Id = %d where Id = %d", newId, oldId));
SQLiteUtils.execSql(String.format("update Habits set Id = %d where Id = %d", newId, oldId));
}
protected static From select()
@ -114,18 +115,13 @@ public class Habit extends Model
public static void reorder(int from, int to)
{
if (from == to)
return;
if (from == to) return;
Habit h = Habit.getByPosition(from);
if (to < from)
new Update(Habit.class).set("position = position + 1")
.where("position >= ? and position < ?", to, from)
.execute();
else
new Update(Habit.class).set("position = position - 1")
.where("position > ? and position <= ?", from, to)
.execute();
if (to < from) new Update(Habit.class).set("position = position + 1")
.where("position >= ? and position < ?", to, from).execute();
else new Update(Habit.class).set("position = position - 1")
.where("position > ? and position <= ?", from, to).execute();
h.position = to;
h.save();
@ -152,13 +148,20 @@ public class Habit extends Model
}
}
public static void recomputeAllScores()
{
for (Habit habit : getHabits())
{
habit.deleteScoresNewerThan(0);
}
}
public static int getStarCount()
{
String args[] = {};
return SQLiteUtils.intQuery(
"select count(*) from (select score, max(timestamp) from " +
"score group by habit) as scores where scores.score >= "
+ Integer.toString(12973000), args);
return SQLiteUtils.intQuery("select count(*) from (select score, max(timestamp) from " +
"score group by habit) as scores where scores.score >= " +
Integer.toString(12973000), args);
}
@ -184,14 +187,12 @@ public class Habit extends Model
protected From selectReps()
{
return new Select().from(Repetition.class).where("habit = ?", getId())
.orderBy("timestamp");
return new Select().from(Repetition.class).where("habit = ?", getId()).orderBy("timestamp");
}
protected From selectRepsFromTo(long timeFrom, long timeTo)
{
return selectReps().and("timestamp >= ?", timeFrom).and(
"timestamp <= ?", timeTo);
return selectReps().and("timestamp >= ?", timeFrom).and("timestamp <= ?", timeTo);
}
public boolean hasRep(long timestamp)
@ -236,8 +237,7 @@ public class Habit extends Model
for (int j = 0; j < freq_den; j++)
if (checkExtended[i + j] == 2) counter++;
if (counter >= freq_num)
checkExtended[i] = Math.max(checkExtended[i], 1);
if (counter >= freq_num) checkExtended[i] = Math.max(checkExtended[i], 1);
}
int check[] = new int[nDays + 1];
@ -247,6 +247,13 @@ public class Habit extends Model
return check;
}
public int getRepsCount(int days)
{
long timeTo = DateHelper.getStartOfToday();
long timeFrom = timeTo - DateHelper.millisecondsInOneDay * days;
return selectRepsFromTo(timeFrom, timeTo).count();
}
public boolean hasImplicitRepToday()
{
long today = DateHelper.getStartOfToday();
@ -282,14 +289,14 @@ public class Habit extends Model
public Score getNewestScore()
{
return new Select().from(Score.class).where("habit = ?", getId())
.orderBy("timestamp desc").limit(1).executeSingle();
return new Select().from(Score.class).where("habit = ?", getId()).orderBy("timestamp desc")
.limit(1).executeSingle();
}
public void deleteScoresNewerThan(long timestamp)
{
new Delete().from(Score.class).where("habit = ?", getId())
.and("timestamp >= ?", timestamp).execute();
new Delete().from(Score.class).where("habit = ?", getId()).and("timestamp >= ?", timestamp)
.execute();
}
public Integer getScore()
@ -307,8 +314,7 @@ public class Habit extends Model
if (newestScore == null)
{
Repetition oldestRep = getOldestRep();
if (oldestRep == null)
return 0;
if (oldestRep == null) return 0;
beginningTime = oldestRep.timestamp;
beginningScore = 0;
} else
@ -318,8 +324,7 @@ public class Habit extends Model
}
long nDays = (today - beginningTime) / day;
if (nDays < 0)
return newestScore.score;
if (nDays < 0) return newestScore.score;
int reps[] = getReps(beginningTime, today);
@ -343,13 +348,26 @@ public class Habit extends Model
return lastScore;
}
public List<Score> getScores(long fromTimestamp, long toTimestamp)
{
return getScores(fromTimestamp, toTimestamp, 1, 0);
}
public List<Score> getScores(long fromTimestamp, long toTimestamp, int divisor, long offset)
{
return new Select().from(Score.class).where("habit = ? and timestamp > ? and " +
"timestamp <= ? and (timestamp - ?) % ? = 0", getId(), fromTimestamp, toTimestamp,
offset, divisor).execute();
}
public long[] getStreaks()
{
String query = "create temporary table T as select distinct r1.habit as habit, r1.timestamp as time,\n" +
" (select count(*) from repetitions r2 where r1.habit = r2.habit and\n" +
" (r1.timestamp = r2.timestamp - 24*60*60*1000 or\n" +
" r1.timestamp = r2.timestamp + 24*60*60*1000)) as neighbors\n" +
"from repetitions r1 where r1.habit = ?";
String query =
"create temporary table T as select distinct r1.habit as habit, r1.timestamp as time,\n" +
" (select count(*) from repetitions r2 where r1.habit = r2.habit and\n" +
" (r1.timestamp = r2.timestamp - 24*60*60*1000 or\n" +
" r1.timestamp = r2.timestamp + 24*60*60*1000)) as neighbors\n" +
"from repetitions r1 where r1.habit = ?";
String query2 =
"select time from T, (select 0 union select 1) where neighbors = 0 union all\n" +
@ -436,8 +454,8 @@ public class Habit extends Model
this.modified = new Habit(modified);
this.original = new Habit(Habit.this);
hasIntervalChanged = (this.original.freq_den != this.modified.freq_den
|| this.original.freq_num != this.modified.freq_num);
hasIntervalChanged = (this.original.freq_den != this.modified.freq_den ||
this.original.freq_num != this.modified.freq_num);
}
public void execute()
@ -446,7 +464,30 @@ public class Habit extends Model
habit.copyAttributes(modified);
habit.save();
if (hasIntervalChanged)
habit.deleteScoresNewerThan(0);
{
new AsyncTask<Habit, Integer, Integer>()
{
@Override
protected Integer doInBackground(Habit... habits)
{
// HACK: We wait one second before deleting old score, otherwise the view will
// trigger the very slow getScore on the main thread at the same time, or even
// before us.
try
{
Thread.sleep(1000);
} catch (InterruptedException e)
{
e.printStackTrace();
}
habits[0].deleteScoresNewerThan(0);
habits[0].getScore();
return 0;
}
}.execute(habit);
}
}
public void undo()
@ -455,7 +496,28 @@ public class Habit extends Model
habit.copyAttributes(original);
habit.save();
if (hasIntervalChanged)
habit.deleteScoresNewerThan(0);
{
new AsyncTask<Habit, Integer, Integer>()
{
@Override
protected Integer doInBackground(Habit... habits)
{
try
{
Thread.sleep(1000);
} catch (InterruptedException e)
{
e.printStackTrace();
}
habits[0].deleteScoresNewerThan(0);
habits[0].getScore();
return 0;
}
}.execute(habit);
}
}
public Integer getExecuteStringId()

@ -1,233 +1,233 @@
package org.isoron.uhabits.views;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;
import org.isoron.helpers.ColorHelper;
import org.isoron.helpers.DateHelper;
import org.isoron.uhabits.R;
import org.isoron.uhabits.models.Habit;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.support.v4.view.MotionEventCompat;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
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;
import java.util.Calendar;
import java.util.GregorianCalendar;
public class HabitHistoryView extends View
{
private Habit habit;
private int reps[];
private Habit habit;
private int reps[];
private Context context;
private Paint pSquareBg, pSquareFg, pTextHeader;
private Context context;
private Paint pSquareBg, pSquareFg, pTextHeader;
private int squareSize, squareSpacing;
private int nColumns, offsetWeeks;
private int colorPrimary, colorPrimaryBrighter, grey;
public HabitHistoryView(Context context, Habit habit, int squareSize)
{
super(context);
this.habit = habit;
this.context = context;
this.squareSize = squareSize;
Typeface fontawesome = Typeface.createFromAsset(context.getAssets(),
"fontawesome-webfont.ttf");
colorPrimary = habit.color;
colorPrimaryBrighter = ColorHelper.mixColors(colorPrimary, Color.WHITE, 0.5f);
grey = Color.rgb(230, 230, 230);
squareSpacing = 2;
pTextHeader = new Paint();
pTextHeader.setColor(Color.LTGRAY);
pTextHeader.setTextAlign(Align.LEFT);
pTextHeader.setTextSize(squareSize * 0.5f);
pTextHeader.setAntiAlias(true);
pSquareBg = new Paint();
pSquareBg.setColor(habit.color);
pSquareFg = new Paint();
pSquareFg.setColor(Color.WHITE);
pSquareFg.setAntiAlias(true);
// pSquareFg.setTypeface(fontawesome);
pSquareFg.setTextSize(squareSize * 0.5f);
pSquareFg.setTextAlign(Align.CENTER);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(getMeasuredWidth(), 8 * squareSize);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
private int nColumns, offsetWeeks;
private int colorPrimary, colorPrimaryBrighter, grey;
private Float prevX, prevY;
public HabitHistoryView(Context context, Habit habit, int squareSize)
{
super(context);
this.habit = habit;
this.context = context;
this.squareSize = squareSize;
colorPrimary = habit.color;
colorPrimaryBrighter = ColorHelper.mixColors(colorPrimary, Color.WHITE, 0.5f);
grey = Color.rgb(230, 230, 230);
squareSpacing = 2;
pTextHeader = new Paint();
pTextHeader.setColor(Color.LTGRAY);
pTextHeader.setTextAlign(Align.LEFT);
pTextHeader.setTextSize(squareSize * 0.5f);
pTextHeader.setAntiAlias(true);
pSquareBg = new Paint();
pSquareBg.setColor(habit.color);
pSquareFg = new Paint();
pSquareFg.setColor(Color.WHITE);
pSquareFg.setAntiAlias(true);
pSquareFg.setTextSize(squareSize * 0.5f);
pSquareFg.setTextAlign(Align.CENTER);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(getMeasuredWidth(), 8 * squareSize);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
nColumns = (w / squareSize) - 1;
fetchReps();
}
private void fetchReps()
{
Calendar currentDate = new GregorianCalendar();
currentDate.add(Calendar.DAY_OF_YEAR, -offsetWeeks * 7);
int dayOfWeek = currentDate.get(Calendar.DAY_OF_WEEK) % 7;
long dateTo = DateHelper.getStartOfToday();
for (int i = 0; i < 7 - dayOfWeek; i++)
dateTo += DateHelper.millisecondsInOneDay;
for (int i = 0; i < offsetWeeks * 7; i++)
dateTo -= DateHelper.millisecondsInOneDay;
long dateFrom = dateTo;
for (int i = 0; i < nColumns * 7; i++)
dateFrom -= DateHelper.millisecondsInOneDay;
reps = habit.getReps(dateFrom, dateTo);
}
@Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
Rect square = new Rect(0, 0, squareSize - squareSpacing, squareSize - squareSpacing);
Calendar currentDate = new GregorianCalendar();
currentDate.add(Calendar.DAY_OF_YEAR, -(offsetWeeks-1) * 7);
int nDays = nColumns * 7;
int todayWeekday = new GregorianCalendar().get(Calendar.DAY_OF_WEEK) % 7;
currentDate.add(Calendar.DAY_OF_YEAR, -nDays);
SimpleDateFormat dfMonth = new SimpleDateFormat("MMM");
SimpleDateFormat dfYear = new SimpleDateFormat("yyyy");
String previousMonth = "";
String previousYear = "";
int colors[] = { grey, colorPrimaryBrighter, colorPrimary };
String markers[] = { context.getString(R.string.fa_times),
context.getString(R.string.fa_check), context.getString(R.string.fa_check) };
float squareTextOffset = pSquareFg.getFontSpacing() * 0.4f;
float headerTextOffset = pTextHeader.getFontSpacing() * 0.3f;
boolean justPrintedYear = false;
int k = nDays;
for (int i = 0; i < nColumns; i++)
{
String month = dfMonth.format(currentDate.getTime());
String year = dfYear.format(currentDate.getTime());
if(!month.equals(previousMonth))
{
int offset = 0;
if(justPrintedYear)
offset += squareSize;
canvas.drawText(month, square.left + offset, square.bottom - headerTextOffset,
pTextHeader);
previousMonth = month;
justPrintedYear = false;
}
else if(!year.equals(previousYear))
{
canvas.drawText(year, square.left, square.bottom - headerTextOffset, pTextHeader);
previousYear = year;
justPrintedYear = true;
}
else
{
justPrintedYear = false;
}
square.offset(0, squareSize);
for (int j = 0; j < 7; j++)
{
if(!(i == nColumns - 1 && offsetWeeks == 0 && j > todayWeekday))
{
pSquareBg.setColor(colors[reps[k]]);
canvas.drawRect(square, pSquareBg);
// canvas.drawText(markers[reps[k]], square.centerX(), square.centerY()
// + squareTextOffset, pSquareFg);
canvas.drawText(Integer.toString(currentDate.get(Calendar.DAY_OF_MONTH)),
square.centerX(), square.centerY() + squareTextOffset, pSquareFg);
}
currentDate.add(Calendar.DAY_OF_MONTH, 1);
square.offset(0, squareSize);
k--;
}
square.offset(squareSize, -8 * squareSize);
}
String wdays[] = { "Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri" };
for (int i = 0; i < 7; i++)
{
square.offset(0, squareSize);
canvas.drawText(wdays[i], square.left + headerTextOffset, square.bottom
- headerTextOffset, pTextHeader);
}
}
private Float prevX, prevY;
@Override
public boolean onTouchEvent(MotionEvent event)
{
int action = event.getAction();
int pointerIndex = MotionEventCompat.getActionIndex(event);
final float x = MotionEventCompat.getX(event, pointerIndex);
final float y = MotionEventCompat.getY(event, pointerIndex);
if(action == MotionEvent.ACTION_DOWN)
{
prevX = x;
prevY = y;
}
if(action == MotionEvent.ACTION_MOVE)
{
float dx = x - prevX;
float dy = y - prevY;
int newOffsetWeeks = offsetWeeks + (int) (dx / squareSize);
newOffsetWeeks = Math.max(0, newOffsetWeeks);
if(newOffsetWeeks != offsetWeeks)
{
prevX = x;
prevY = y;
offsetWeeks = newOffsetWeeks;
fetchReps();
invalidate();
}
}
return true;
}
fetchReps();
}
private void fetchReps()
{
Calendar currentDate = new GregorianCalendar();
currentDate.add(Calendar.DAY_OF_YEAR, -offsetWeeks * 7);
int dayOfWeek = currentDate.get(Calendar.DAY_OF_WEEK) % 7;
long dateTo = DateHelper.getStartOfToday();
for (int i = 0; i < 7 - dayOfWeek; i++)
dateTo += DateHelper.millisecondsInOneDay;
for (int i = 0; i < offsetWeeks * 7; i++)
dateTo -= DateHelper.millisecondsInOneDay;
long dateFrom = dateTo;
for (int i = 0; i < nColumns * 7; i++)
dateFrom -= DateHelper.millisecondsInOneDay;
reps = habit.getReps(dateFrom, dateTo);
}
@Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
Rect square = new Rect(0, 0, squareSize - squareSpacing, squareSize - squareSpacing);
Calendar currentDate = new GregorianCalendar();
currentDate.add(Calendar.DAY_OF_YEAR, - (offsetWeeks - 1) * 7);
int nDays = nColumns * 7;
int todayWeekday = new GregorianCalendar().get(Calendar.DAY_OF_WEEK) % 7;
currentDate.add(Calendar.DAY_OF_YEAR, -nDays);
currentDate.add(Calendar.DAY_OF_YEAR, -todayWeekday);
SimpleDateFormat dfMonth = new SimpleDateFormat("MMM");
SimpleDateFormat dfYear = new SimpleDateFormat("yyyy");
String previousMonth = "";
String previousYear = "";
int colors[] = {grey, colorPrimaryBrighter, colorPrimary};
String markers[] =
{context.getString(R.string.fa_times), context.getString(R.string.fa_check),
context.getString(R.string.fa_check)};
float squareTextOffset = pSquareFg.getFontSpacing() * 0.4f;
float headerTextOffset = pTextHeader.getFontSpacing() * 0.3f;
boolean justPrintedYear = false;
int k = nDays;
for (int i = 0; i < nColumns; i++)
{
String month = dfMonth.format(currentDate.getTime());
String year = dfYear.format(currentDate.getTime());
if (!month.equals(previousMonth))
{
int offset = 0;
if (justPrintedYear) offset += squareSize;
canvas.drawText(month, square.left + offset, square.bottom - headerTextOffset,
pTextHeader);
previousMonth = month;
justPrintedYear = false;
} else if (!year.equals(previousYear))
{
canvas.drawText(year, square.left, square.bottom - headerTextOffset, pTextHeader);
previousYear = year;
justPrintedYear = true;
} else
{
justPrintedYear = false;
}
square.offset(0, squareSize);
for (int j = 0; j < 7; j++)
{
if (!(i == nColumns - 1 && offsetWeeks == 0 && j > todayWeekday))
{
pSquareBg.setColor(colors[reps[k]]);
canvas.drawRect(square, pSquareBg);
canvas.drawText(Integer.toString(currentDate.get(Calendar.DAY_OF_MONTH)),
square.centerX(), square.centerY() + squareTextOffset, pSquareFg);
}
currentDate.add(Calendar.DAY_OF_MONTH, 1);
square.offset(0, squareSize);
k--;
}
square.offset(squareSize, -8 * squareSize);
}
String wdays[] = {"Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri"};
for (int i = 0; i < 7; i++)
{
square.offset(0, squareSize);
canvas.drawText(wdays[i], square.left + headerTextOffset,
square.bottom - headerTextOffset, pTextHeader);
}
}
@Override
public boolean onTouchEvent(MotionEvent event)
{
int action = event.getAction();
int pointerIndex = MotionEventCompat.getActionIndex(event);
final float x = MotionEventCompat.getX(event, pointerIndex);
final float y = MotionEventCompat.getY(event, pointerIndex);
if (action == MotionEvent.ACTION_DOWN)
{
prevX = x;
prevY = y;
}
if (action == MotionEvent.ACTION_MOVE)
{
float dx = x - prevX;
float dy = y - prevY;
if (Math.abs(dy) > Math.abs(dx)) return false;
getParent().requestDisallowInterceptTouchEvent(true);
if(move(dx))
{
prevX = x;
prevY = y;
}
}
return true;
}
private boolean move(float dx)
{
int newOffsetWeeks = offsetWeeks + (int) (dx / squareSize);
newOffsetWeeks = Math.max(0, newOffsetWeeks);
if (newOffsetWeeks != offsetWeeks)
{
offsetWeeks = newOffsetWeeks;
fetchReps();
invalidate();
return true;
}
else
return false;
}
}

@ -0,0 +1,252 @@
package org.isoron.uhabits.views;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.support.v4.view.MotionEventCompat;
import android.view.MotionEvent;
import android.view.View;
import org.isoron.helpers.ColorHelper;
import org.isoron.helpers.DateHelper;
import org.isoron.uhabits.models.Habit;
import org.isoron.uhabits.models.Score;
import java.text.SimpleDateFormat;
import java.util.List;
public class HabitScoreView extends View
{
public static final int BUCKET_SIZE = 7;
private final Paint pGrid;
private final float em;
private Habit habit;
private int columnWidth, columnHeight, nColumns;
private Paint pText, pGraph;
private int dataOffset;
private int barHeaderHeight;
private int[] colors;
private float prevX;
private float prevY;
private List<Score> scores;
public HabitScoreView(Context context, Habit habit, int columnWidth)
{
super(context);
this.habit = habit;
this.columnWidth = columnWidth;
pText = new Paint();
pText.setColor(Color.LTGRAY);
pText.setTextAlign(Paint.Align.LEFT);
pText.setTextSize(columnWidth * 0.5f);
pText.setAntiAlias(true);
pGraph = new Paint();
pGraph.setTextAlign(Paint.Align.CENTER);
pGraph.setTextSize(columnWidth * 0.5f);
pGraph.setAntiAlias(true);
pGraph.setStrokeWidth(columnWidth * 0.1f);
pGrid = new Paint();
pGrid.setColor(Color.LTGRAY);
pGrid.setAntiAlias(true);
pGrid.setStrokeWidth(columnWidth * 0.05f);
columnHeight = 8 * columnWidth;
barHeaderHeight = columnWidth;
em = pText.getFontSpacing();
colors = new int[4];
colors[0] = Color.rgb(230, 230, 230);
colors[3] = habit.color;
colors[1] = ColorHelper.mixColors(colors[0], colors[3], 0.66f);
colors[2] = ColorHelper.mixColors(colors[0], colors[3], 0.33f);
}
private void fetchScores()
{
long toTimestamp = DateHelper.getStartOfToday();
for (int i = 0; i < dataOffset * BUCKET_SIZE; i++)
toTimestamp -= DateHelper.millisecondsInOneDay;
long fromTimestamp = toTimestamp;
for (int i = 0; i < nColumns * BUCKET_SIZE; i++)
fromTimestamp -= DateHelper.millisecondsInOneDay;
scores = habit.getScores(fromTimestamp, toTimestamp, BUCKET_SIZE * DateHelper.millisecondsInOneDay,
toTimestamp);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(getMeasuredWidth(), columnHeight + 2 * barHeaderHeight);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
super.onSizeChanged(w, h, oldw, oldh);
nColumns = w / columnWidth;
fetchScores();
}
@Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
float lineHeight = pText.getFontSpacing();
float barHeaderOffset = lineHeight * 0.4f;
RectF rGrid = new RectF(0, 0, nColumns * columnWidth, columnHeight);
rGrid.offset(0, barHeaderHeight);
drawGrid(canvas, rGrid);
SimpleDateFormat dfMonth = new SimpleDateFormat("MMM");
SimpleDateFormat dfDay = new SimpleDateFormat("d");
String previousMonth = "";
pGraph.setColor(habit.color);
RectF prevR = null;
for (int offset = nColumns - scores.size(); offset < nColumns; offset++)
{
Score score = scores.get(offset - nColumns + scores.size());
String month = dfMonth.format(score.timestamp);
String day = dfDay.format(score.timestamp);
long s = score.score;
double sRelative = ((double) s) / Habit.MAX_SCORE;
int height = (int) (columnHeight * sRelative);
RectF r = new RectF(0, 0, columnWidth, columnWidth);
r.offset(offset * columnWidth,
barHeaderHeight + columnHeight - height - columnWidth / 2);
if (prevR != null)
{
drawLine(canvas, prevR, r);
drawMarker(canvas, prevR);
}
if (offset == nColumns - 1) drawMarker(canvas, r);
prevR = r;
r = new RectF(0, 0, columnWidth, columnHeight);
r.offset(offset * columnWidth, barHeaderHeight);
if (!month.equals(previousMonth))
{
canvas.drawText(month, r.centerX(), r.bottom + lineHeight * 1.2f, pText);
} else
{
canvas.drawText(day, r.centerX(), r.bottom + lineHeight * 1.2f, pText);
}
previousMonth = month;
}
}
private void drawGrid(Canvas canvas, RectF rGrid)
{
// pGrid.setColor(Color.rgb(230, 230, 230));
// pGrid.setStyle(Paint.Style.STROKE);
// canvas.drawRect(rGrid, pGrid);
int nRows = 5;
float rowHeight = rGrid.height() / nRows;
pGrid.setColor(Color.rgb(240, 240, 240));
for (int i = 0; i < nRows; i++)
{
canvas.drawText(String.format("%d%%", (100 - i * 100 / nRows)), rGrid.left + 0.5f * em,
rGrid.top + 1f * em, pText);
canvas.drawLine(rGrid.left, rGrid.top, rGrid.right, rGrid.top, pGrid);
rGrid.offset(0, rowHeight);
}
canvas.drawLine(rGrid.left, rGrid.top, rGrid.right, rGrid.top, pGrid);
}
private void drawLine(Canvas canvas, RectF rectFrom, RectF rectTo)
{
pGraph.setColor(habit.color);
canvas.drawLine(rectFrom.centerX(), rectFrom.centerY(), rectTo.centerX(), rectTo.centerY(),
pGraph);
}
private void drawMarker(Canvas canvas, RectF rect)
{
rect.inset(columnWidth * 0.15f, columnWidth * 0.15f);
pGraph.setColor(Color.WHITE);
canvas.drawOval(rect, pGraph);
rect.inset(columnWidth * 0.1f, columnWidth * 0.1f);
pGraph.setColor(habit.color);
canvas.drawOval(rect, pGraph);
rect.inset(columnWidth * 0.1f, columnWidth * 0.1f);
pGraph.setColor(Color.WHITE);
canvas.drawOval(rect, pGraph);
}
@Override
public boolean onTouchEvent(MotionEvent event)
{
int action = event.getAction();
int pointerIndex = MotionEventCompat.getActionIndex(event);
final float x = MotionEventCompat.getX(event, pointerIndex);
final float y = MotionEventCompat.getY(event, pointerIndex);
if (action == MotionEvent.ACTION_DOWN)
{
prevX = x;
prevY = y;
}
if (action == MotionEvent.ACTION_MOVE)
{
float dx = x - prevX;
float dy = y - prevY;
if (Math.abs(dy) > Math.abs(dx)) return false;
getParent().requestDisallowInterceptTouchEvent(true);
if (move(dx))
{
prevX = x;
prevY = y;
}
}
return true;
}
private boolean move(float dx)
{
int newDataOffset = dataOffset + (int) (dx / columnWidth);
newDataOffset = Math.max(0, newDataOffset);
if (newDataOffset != dataOffset)
{
dataOffset = newDataOffset;
fetchScores();
invalidate();
return true;
} else return false;
}
}

@ -5,6 +5,8 @@ import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.support.v4.view.MotionEventCompat;
import android.view.MotionEvent;
import android.view.View;
import org.isoron.helpers.ColorHelper;
@ -22,6 +24,7 @@ public class HabitStreakView extends View
private Paint pText, pBar;
private long streaks[];
private int dataOffset;
private long streakStart[], streakEnd[], streakLength[];
private long maxStreakLength;
@ -29,6 +32,8 @@ public class HabitStreakView extends View
private int barHeaderHeight;
private int[] colors;
private float prevX;
private float prevY;
public HabitStreakView(Context context, Habit habit, int columnWidth)
{
@ -98,7 +103,7 @@ public class HabitStreakView extends View
float lineHeight = pText.getFontSpacing();
float barHeaderOffset = lineHeight * 0.4f;
int start = Math.max(0, streakStart.length - nColumns);
int start = Math.max(0, streakStart.length - nColumns - dataOffset);
SimpleDateFormat dfMonth = new SimpleDateFormat("MMM");
String previousMonth = "";
@ -125,4 +130,51 @@ public class HabitStreakView extends View
previousMonth = month;
}
}
@Override
public boolean onTouchEvent(MotionEvent event)
{
int action = event.getAction();
int pointerIndex = MotionEventCompat.getActionIndex(event);
final float x = MotionEventCompat.getX(event, pointerIndex);
final float y = MotionEventCompat.getY(event, pointerIndex);
if (action == MotionEvent.ACTION_DOWN)
{
prevX = x;
prevY = y;
}
if (action == MotionEvent.ACTION_MOVE)
{
float dx = x - prevX;
float dy = y - prevY;
if (Math.abs(dy) > Math.abs(dx)) return false;
getParent().requestDisallowInterceptTouchEvent(true);
if(move(dx))
{
prevX = x;
prevY = y;
}
}
return true;
}
private boolean move(float dx)
{
int newDataOffset = dataOffset + (int) (dx / columnWidth);
newDataOffset = Math.max(0, Math.min(streakStart.length - nColumns, newDataOffset));
if (newDataOffset != dataOffset)
{
dataOffset = newDataOffset;
invalidate();
return true;
}
else
return false;
}
}

@ -28,11 +28,8 @@ public class RingView extends View
pRing.setColor(color);
pRing.setAntiAlias(true);
pRing.setTextAlign(Paint.Align.CENTER);
pRing.setTextSize(size * 0.15f);
this.label = label;
lineHeight = pRing.getFontSpacing();
}
@Override
@ -52,16 +49,19 @@ public class RingView extends View
RectF r = new RectF(0, 0, size, size);
canvas.drawArc(r, -90, 360 * perc, true, pRing);
pRing.setColor(Color.rgb(230, 230, 230));
canvas.drawArc(r, 360 * perc - 90 + 2, 360 * (1-perc) - 4, true, pRing);
canvas.drawArc(r, 360 * perc - 90 + 2, 360 * (1 - perc) - 4, true, pRing);
pRing.setColor(Color.WHITE);
r.inset(thickness, thickness);
canvas.drawArc(r, -90, 360, true, pRing);
pRing.setColor(Color.GRAY);
canvas.drawText(String.format("%.2f%%", perc*100), r.centerX(), r.centerY()+lineHeight/3, pRing);
pRing.setTextSize(size * 0.2f);
lineHeight = pRing.getFontSpacing();
canvas.drawText(String.format("%.0f%%", perc * 100), r.centerX(), r.centerY()+lineHeight/3, pRing);
pRing.setTextSize(size * 0.15f);
canvas.drawText(label, size/2, size + lineHeight * 1.2f, pRing);
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 B

@ -1,21 +1,35 @@
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:fillViewport="true"
android:background="@color/windowBackground">
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@color/windowBackground"
android:fillViewport="true">
<LinearLayout
style="@style/cardsListStyle"
tools:context="org.isoron.uhabits.ShowHabitActivity">
<LinearLayout style="@style/cardStyle"
android:id="@+id/llOverview">
<LinearLayout
android:id="@+id/llOverview"
style="@style/cardStyle"
android:gravity="center">
<TextView
android:id="@+id/tvOverview"
style="@style/cardHeaderStyle"
android:text="@string/overview" />
android:text="@string/overview"/>
</LinearLayout>
<LinearLayout
android:id="@+id/llStrength"
style="@style/cardStyle"
android:gravity="center">
<TextView
android:id="@+id/tvStrength"
style="@style/cardHeaderStyle"
android:text="@string/habit_strength"/>
</LinearLayout>
@ -24,13 +38,13 @@
<TextView
android:id="@+id/tvHistory"
style="@style/cardHeaderStyle"
android:text="@string/history" />
android:text="@string/history"/>
<LinearLayout
android:id="@+id/llHistory"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" />
android:orientation="horizontal"/>
</LinearLayout>
<LinearLayout style="@style/cardStyle">
@ -38,13 +52,13 @@
<TextView
android:id="@+id/tvStreaks"
style="@style/cardHeaderStyle"
android:text="@string/streaks" />
android:text="@string/streaks"/>
<LinearLayout
android:id="@+id/llStreaks"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" />
android:orientation="horizontal"/>
</LinearLayout>
</LinearLayout>
</ScrollView>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

@ -14,19 +14,9 @@
<style name="MyDialogStyle" parent="android:Theme.Material.Light.Dialog">
</style>
<style name="cardStyle">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<style name="cardStyle" parent="cardBasicStyle">
<item name="android:background">@color/white</item>
<item name="android:elevation">1dp</item>
<item name="android:orientation">vertical</item>
<item name="android:paddingTop">16dp</item>
<item name="android:paddingBottom">16dp</item>
<item name="android:paddingLeft">16dp</item>
<item name="android:paddingRight">4dp</item>
<item name="android:layout_marginBottom">3dp</item>
<item name="android:layout_marginLeft">3dp</item>
<item name="android:layout_marginRight">3dp</item>
</style>
</resources>

@ -1,20 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="habitsListHeaderStyle">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_alignParentTop">true</item>
<style name="habitsListHeaderStyle" parent="habitsListHeaderBasicStyle">
<item name="android:background">#f0f0f0</item>
<item name="android:elevation">2dp</item>
<item name="android:paddingRight">4dp</item>
</style>
<style name="habitsListCheckStyle">
<item name="android:focusable">false</item>
<item name="android:minHeight">42dp</item>
<item name="android:minWidth">42dp</item>
<item name="android:gravity">center</item>
<style name="habitsListCheckStyle" parent="habitsListCheckBasicStyle">
<item name="android:background">@drawable/ripple_background</item>
</style>
</resources>

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="DragSortListView">
<attr name="collapsed_height" format="dimension"/>
<attr name="drag_scroll_start" format="float"/>
<attr name="max_drag_scroll_speed" format="float"/>
<attr name="float_background_color" format="color"/>
<attr name="remove_mode">
<enum name="clickRemove" value="0"/>
<enum name="flingRemove" value="1"/>
</attr>
<attr name="track_drag_sort" format="boolean"/>
<attr name="float_alpha" format="float"/>
<attr name="slide_shuffle_speed" format="float"/>
<attr name="remove_animation_duration" format="integer"/>
<attr name="drop_animation_duration" format="integer"/>
<attr name="drag_enabled" format="boolean"/>
<attr name="sort_enabled" format="boolean"/>
<attr name="remove_enabled" format="boolean"/>
<attr name="drag_start_mode">
<enum name="onDown" value="0"/>
<enum name="onMove" value="1"/>
<enum name="onLongPress" value="2"/>
</attr>
<attr name="drag_handle_id" format="integer"/>
<attr name="fling_handle_id" format="integer"/>
<attr name="click_remove_id" format="integer"/>
<attr name="use_default_controller" format="boolean"/>
</declare-styleable>
</resources>

@ -1,54 +1,6 @@
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="square_size">20dp</dimen>
<!-- Color picker -->
<dimen name="color_swatch_large">64dip</dimen>
<dimen name="color_swatch_small">48dip</dimen>
<dimen name="color_swatch_margins_large">8dip</dimen>
<dimen name="color_swatch_margins_small">4dip</dimen>
<!-- Date and time picker -->
<item name="circle_radius_multiplier" format="float" type="string">0.82</item>
<item name="circle_radius_multiplier_24HourMode" format="float" type="string">0.85</item>
<item name="selection_radius_multiplier" format="float" type="string">0.16</item>
<item name="ampm_circle_radius_multiplier" format="float" type="string">0.19</item>
<item name="numbers_radius_multiplier_normal" format="float" type="string">0.81</item>
<item name="numbers_radius_multiplier_inner" format="float" type="string">0.60</item>
<item name="numbers_radius_multiplier_outer" format="float" type="string">0.83</item>
<item name="text_size_multiplier_normal" format="float" type="string">0.17</item>
<item name="text_size_multiplier_inner" format="float" type="string">0.14</item>
<item name="text_size_multiplier_outer" format="float" type="string">0.11</item>
<dimen name="time_label_size">60sp</dimen>
<dimen name="extra_time_label_margin">-30dp</dimen>
<dimen name="ampm_label_size">16sp</dimen>
<dimen name="done_label_size">14sp</dimen>
<dimen name="ampm_left_padding">6dip</dimen>
<dimen name="separator_padding">4dip</dimen>
<dimen name="header_height">96dip</dimen>
<dimen name="footer_height">48dip</dimen>
<dimen name="minimum_margin_sides">48dip</dimen>
<dimen name="minimum_margin_top_bottom">24dip</dimen>
<dimen name="picker_dimen">270dip</dimen>
<dimen name="date_picker_component_width">270dp</dimen>
<dimen name="date_picker_header_height">30dp</dimen>
<dimen name="selected_calendar_layout_height">155dp</dimen>
<dimen name="date_picker_view_animator_height">270dp</dimen>
<dimen name="done_button_height">42dp</dimen>
<dimen name="month_list_item_header_height">50dp</dimen>
<dimen name="month_day_label_text_size">10sp</dimen>
<dimen name="day_number_select_circle_radius">16dp</dimen>
<dimen name="month_select_circle_radius">45dp</dimen>
<dimen name="selected_date_year_size">30dp</dimen>
<dimen name="selected_date_day_size">75dp</dimen>
<dimen name="selected_date_month_size">30dp</dimen>
<dimen name="date_picker_header_text_size">14dp</dimen>
<dimen name="month_label_size">16sp</dimen>
<dimen name="day_number_size">16sp</dimen>
<dimen name="year_label_height">64dp</dimen>
<dimen name="year_label_text_size">22dp</dimen>
<dimen name="small_square_size">20dp</dimen>
<dimen name="check_square_size">42dp</dimen>
</resources>

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="color_swatch_large">64dip</dimen>
<dimen name="color_swatch_small">48dip</dimen>
<dimen name="color_swatch_margins_large">8dip</dimen>
<dimen name="color_swatch_margins_small">4dip</dimen>
</resources>

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="circle_radius_multiplier" format="float" type="string">0.82</item>
<item name="circle_radius_multiplier_24HourMode" format="float" type="string">0.85</item>
<item name="selection_radius_multiplier" format="float" type="string">0.16</item>
<item name="ampm_circle_radius_multiplier" format="float" type="string">0.19</item>
<item name="numbers_radius_multiplier_normal" format="float" type="string">0.81</item>
<item name="numbers_radius_multiplier_inner" format="float" type="string">0.60</item>
<item name="numbers_radius_multiplier_outer" format="float" type="string">0.83</item>
<item name="text_size_multiplier_normal" format="float" type="string">0.17</item>
<item name="text_size_multiplier_inner" format="float" type="string">0.14</item>
<item name="text_size_multiplier_outer" format="float" type="string">0.11</item>
<dimen name="time_label_size">60sp</dimen>
<dimen name="extra_time_label_margin">-30dp</dimen>
<dimen name="ampm_label_size">16sp</dimen>
<dimen name="done_label_size">14sp</dimen>
<dimen name="ampm_left_padding">6dip</dimen>
<dimen name="separator_padding">4dip</dimen>
<dimen name="header_height">96dip</dimen>
<dimen name="footer_height">48dip</dimen>
<dimen name="minimum_margin_sides">48dip</dimen>
<dimen name="minimum_margin_top_bottom">24dip</dimen>
<dimen name="picker_dimen">270dip</dimen>
<dimen name="date_picker_component_width">270dp</dimen>
<dimen name="date_picker_header_height">30dp</dimen>
<dimen name="selected_calendar_layout_height">155dp</dimen>
<dimen name="date_picker_view_animator_height">270dp</dimen>
<dimen name="done_button_height">42dp</dimen>
<dimen name="month_list_item_header_height">50dp</dimen>
<dimen name="month_day_label_text_size">10sp</dimen>
<dimen name="day_number_select_circle_radius">16dp</dimen>
<dimen name="month_select_circle_radius">45dp</dimen>
<dimen name="selected_date_year_size">30dp</dimen>
<dimen name="selected_date_day_size">75dp</dimen>
<dimen name="selected_date_month_size">30dp</dimen>
<dimen name="date_picker_header_text_size">14dp</dimen>
<dimen name="month_label_size">16sp</dimen>
<dimen name="day_number_size">16sp</dimen>
<dimen name="year_label_height">64dp</dimen>
<dimen name="year_label_text_size">22dp</dimen>
</resources>

@ -25,20 +25,24 @@
<item name="android:orientation">vertical</item>
</style>
<style name="cardStyle">
<style name="cardBasicStyle">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:background">@drawable/card_background</item>
<item name="android:orientation">vertical</item>
<item name="android:paddingTop">16dp</item>
<item name="android:paddingBottom">16dp</item>
<item name="android:paddingLeft">16dp</item>
<item name="android:paddingRight">4dp</item>
<item name="android:layout_marginBottom">1dp</item>
<item name="android:layout_marginBottom">3dp</item>
<item name="android:layout_marginLeft">3dp</item>
<item name="android:layout_marginRight">3dp</item>
</style>
<style name="cardStyle" parent="cardBasicStyle">
<item name="android:background">@drawable/card_background</item>
<item name="android:layout_marginBottom">1dp</item>
</style>
<style name="cardHeaderStyle">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>

@ -10,11 +10,15 @@
<item name="android:background">@color/windowBackground</item>
</style>
<style name="habitsListHeaderStyle">
<style name="habitsListHeaderBasicStyle">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_alignParentTop">true</item>
<item name="android:paddingRight">4dp</item>
</style>
<style name="habitsListHeaderStyle" parent="habitsListHeaderBasicStyle">
<item name="android:background">@drawable/habits_list_header_background</item>
</style>
@ -58,13 +62,16 @@
<item name="android:padding">3dp</item>
</style>
<style name="habitsListCheckStyle">
<style name="habitsListCheckBasicStyle">
<item name="android:focusable">false</item>
<item name="android:minHeight">42dp</item>
<item name="android:minWidth">42dp</item>
<item name="android:minHeight">@dimen/check_square_size</item>
<item name="android:minWidth">@dimen/check_square_size</item>
<item name="android:gravity">center</item>
</style>
<style name="habitsListCheckStyle" parent="habitsListCheckBasicStyle">
</style>
<style name="habitsListHeaderCheckStyle" parent="habitsListCheckStyle">
<item name="android:layout_width">42dp</item>
<item name="android:layout_height">match_parent</item>

Loading…
Cancel
Save