diff --git a/DoNExt/app/build.gradle b/DoNExt/app/build.gradle index 689fb77..6f7b3d7 100644 --- a/DoNExt/app/build.gradle +++ b/DoNExt/app/build.gradle @@ -8,8 +8,8 @@ android { applicationId "com.wismna.geoffroy.donext" minSdkVersion 15 targetSdkVersion 23 - versionCode 3 - versionName "0.3" + versionCode 5 + versionName "0.5" } buildTypes { release { diff --git a/DoNExt/app/src/main/java/com/wismna/geoffroy/donext/adapters/TaskRecyclerViewAdapter.java b/DoNExt/app/src/main/java/com/wismna/geoffroy/donext/adapters/TaskRecyclerViewAdapter.java index 161100d..3e8fc19 100644 --- a/DoNExt/app/src/main/java/com/wismna/geoffroy/donext/adapters/TaskRecyclerViewAdapter.java +++ b/DoNExt/app/src/main/java/com/wismna/geoffroy/donext/adapters/TaskRecyclerViewAdapter.java @@ -17,29 +17,41 @@ import java.util.List; /** * {@link RecyclerView.Adapter} that can display a {@link Task}. */ -public class TaskRecyclerViewAdapter extends RecyclerView.Adapter { +public class TaskRecyclerViewAdapter extends RecyclerView.Adapter { private final List mValues; + private int viewType; - public TaskRecyclerViewAdapter(List items) { + public TaskRecyclerViewAdapter(List items, int viewType) { mValues = items; + this.viewType = viewType; } @Override - public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - View view = LayoutInflater.from(parent.getContext()) - .inflate(R.layout.fragment_task, parent, false); - - return new ViewHolder(view); + public SimpleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view; + switch (viewType) + { + case 1: + view = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.fragment_task_simple, parent, false); + return new SimpleViewHolder(view); + case 2: + view = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.fragment_task_detailed, parent, false); + return new DetailedViewHolder(view); + } + return null; } @Override - public void onBindViewHolder(final ViewHolder holder, int position) { + public void onBindViewHolder(final SimpleViewHolder holder, int position) { holder.mItem = mValues.get(position); holder.mIdView.setText(String.valueOf(holder.mItem.getId())); holder.mCycleView.setText(String.valueOf(holder.mItem.getCycle())); holder.mTitleView.setText(holder.mItem.getName()); - holder.mDescriptionView.setText(holder.mItem.getDescription()); + if (holder instanceof DetailedViewHolder) + ((DetailedViewHolder)holder).mDescriptionView.setText(holder.mItem.getDescription()); int priority = holder.mItem.getPriority(); // Reset task rendering @@ -67,6 +79,11 @@ public class TaskRecyclerViewAdapter extends RecyclerView.Adapter doInBackground(TaskListDataAccess... params) { TaskListDataAccess taskListDataAccess = params[0]; - taskListDataAccess.open(); - List taskLists = taskListDataAccess.getAllTaskLists(); - taskListDataAccess.close(); - return taskLists; + return taskListDataAccess.getAllTaskLists(); } @Override diff --git a/DoNExt/app/src/main/java/com/wismna/geoffroy/donext/fragments/TasksFragment.java b/DoNExt/app/src/main/java/com/wismna/geoffroy/donext/fragments/TasksFragment.java index abea386..a25aa96 100644 --- a/DoNExt/app/src/main/java/com/wismna/geoffroy/donext/fragments/TasksFragment.java +++ b/DoNExt/app/src/main/java/com/wismna/geoffroy/donext/fragments/TasksFragment.java @@ -31,6 +31,7 @@ import com.wismna.geoffroy.donext.dao.TaskList; import com.wismna.geoffroy.donext.database.TaskDataAccess; import com.wismna.geoffroy.donext.helpers.TaskTouchHelper; import com.wismna.geoffroy.donext.listeners.RecyclerItemClickListener; +import com.wismna.geoffroy.donext.widgets.DividerItemDecoration; import com.wismna.geoffroy.donext.widgets.NoScrollingLayoutManager; /** @@ -83,20 +84,20 @@ public class TasksFragment extends Fragment implements view = inflater.inflate(R.layout.fragment_tasks, container, false); final Context context = view.getContext(); + taskDataAccess = new TaskDataAccess(view.getContext()); + taskDataAccess.open(); + // Set the Recycler view recyclerView = (RecyclerView) view.findViewById(R.id.task_list_view); recyclerView.setLayoutManager(new NoScrollingLayoutManager(context)); - taskDataAccess = new TaskDataAccess(view.getContext()); - taskDataAccess.open(); - // Set RecyclerView Adapter - taskRecyclerViewAdapter = new TaskRecyclerViewAdapter(taskDataAccess.getAllTasks(taskListId)); + SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getContext()); + taskRecyclerViewAdapter = new TaskRecyclerViewAdapter( + taskDataAccess.getAllTasks(taskListId), + Integer.valueOf(sharedPref.getString("pref_conf_task_layout", "1"))); recyclerView.setAdapter(taskRecyclerViewAdapter); - // Set total cycles - UpdateCycleCount(); - // Set ItemTouch helper in RecyclerView to handle swipe move on elements ItemTouchHelper.Callback callback = new TaskTouchHelper(this); ItemTouchHelper helper = new ItemTouchHelper(callback); @@ -125,18 +126,37 @@ public class TasksFragment extends Fragment implements }) ); - // Set total count - UpdateTaskCount(); - - // Handle updating remaining task count in a listener to be sure that the layout is available + // Handle updating total counts in a listener to be sure that the layout is available recyclerView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { - UpdateRemainingTaskCount(); - recyclerView.getViewTreeObserver().removeOnPreDrawListener(this); + // Update total cycle count + int totalCycles = taskRecyclerViewAdapter.getCycleCount(); + if (totalCycles != 0) { + TextView totalCyclesView = (TextView) view.findViewById(R.id.total_task_cycles); + totalCyclesView.setText(String.valueOf(totalCycles + " cycles")); + } + + // Update total tasks + int totalTasks = taskRecyclerViewAdapter.getItemCount(); + TextView totalTasksView = (TextView) view.findViewById(R.id.total_task_count); + if (totalTasks == 0) totalTasksView.setText(getResources().getText(R.string.task_no_tasks)); + else totalTasksView.setText(String.valueOf(totalTasks + " task" + (totalTasks > 1 ? "s" : ""))); + + // Update remaining tasks + TextView remainingTasksView = (TextView) view.findViewById(R.id.remaining_task_count); + NoScrollingLayoutManager layoutManager = (NoScrollingLayoutManager) recyclerView.getLayoutManager(); + int remainingTaskCount = totalTasks - layoutManager.findLastVisibleItemPosition() - 1; + if (remainingTaskCount == 0) remainingTasksView.setText(""); + else remainingTasksView.setText(String.valueOf( + remainingTaskCount + " more task" + (remainingTaskCount > 1 ? "s" : ""))); + + //recyclerView.getViewTreeObserver().removeOnPreDrawListener(this); return true; } }); + + recyclerView.addItemDecoration(new DividerItemDecoration(getActivity())); return view; } @@ -152,31 +172,6 @@ public class TasksFragment extends Fragment implements taskDataAccess.open(); } - private void UpdateCycleCount() { - int totalCycles = taskDataAccess.getTotalCycles(taskListId); - if (totalCycles == 0) return; - TextView totalCyclesView = (TextView) view.findViewById(R.id.total_task_cycles); - totalCyclesView.setText(String.valueOf(totalCycles + " cycles")); - } - - private void UpdateTaskCount() { - int totalTasks = taskRecyclerViewAdapter.getItemCount(); - TextView totalTasksView = (TextView) view.findViewById(R.id.total_task_count); - if (totalTasks == 0) totalTasksView.setText(getResources().getText(R.string.task_no_tasks)); - else totalTasksView.setText(String.valueOf(totalTasks + " tasks")); - } - - private void UpdateRemainingTaskCount() { - TextView remainingTasksView = (TextView) view.findViewById(R.id.remaining_task_count); - NoScrollingLayoutManager layoutManager = (NoScrollingLayoutManager) recyclerView.getLayoutManager(); - int remainingTaskCount = taskRecyclerViewAdapter.getItemCount() - layoutManager.findLastVisibleItemPosition() - 1; - if (remainingTaskCount == 0) - remainingTasksView.setText(""); - else - remainingTasksView.setText(String.valueOf( - remainingTaskCount + " more task" + (remainingTaskCount > 1 ? "s" : ""))); - } - /** Performs an action on a task: done, next or delete */ public void PerformTaskAction(final int itemPosition, final int direction) { final long itemId = taskRecyclerViewAdapter.getItemId(itemPosition); @@ -203,58 +198,54 @@ public class TasksFragment extends Fragment implements // Setup the snack bar Snackbar.make(view, "Task " + action, Snackbar.LENGTH_LONG) - .setAction("Undo", new View.OnClickListener() { - @Override - public void onClick(View v) { - // Undo adapter changes - switch (direction) - { - // Nothing special to do for done - case ItemTouchHelper.LEFT: - break; - // Remove the last item - case ItemTouchHelper.RIGHT: - taskRecyclerViewAdapter.remove(taskRecyclerViewAdapter.getItemCount() - 1); - task.setCycle(task.getCycle() - 1); - break; - // Nothing special to do for delete - case -1: - break; - } - // Reset the first item - taskRecyclerViewAdapter.add(task, itemPosition); - recyclerView.scrollToPosition(0); + .setAction("Undo", new View.OnClickListener() { + @Override + public void onClick(View v) { + // Undo adapter changes + switch (direction) { + // Nothing special to do for done + case ItemTouchHelper.LEFT: + break; + // Remove the last item + case ItemTouchHelper.RIGHT: + taskRecyclerViewAdapter.remove(taskRecyclerViewAdapter.getItemCount() - 1); + task.setCycle(task.getCycle() - 1); + break; + // Nothing special to do for delete + case -1: + break; } - }).setCallback(new Snackbar.Callback() { - @Override - public void onDismissed(Snackbar snackbar, int event) { - super.onDismissed(snackbar, event); - - // When clicked on undo, do not write to DB - if (event == DISMISS_EVENT_ACTION) return; - - // Commit the changes to DB - switch (direction) - { - // Mark item as Done - case ItemTouchHelper.LEFT: - taskDataAccess.setDone(itemId); - break; - // Increase task cycle count - case ItemTouchHelper.RIGHT: - taskDataAccess.increaseCycle(task.getCycle(), itemId); - break; - case -1: - // Commit the changes to DB - taskDataAccess.deleteTask(itemId); + // Reset the first item + taskRecyclerViewAdapter.add(task, itemPosition); + recyclerView.scrollToPosition(0); } + }).setCallback(new Snackbar.Callback() { + @Override + public void onDismissed(Snackbar snackbar, int event) { + super.onDismissed(snackbar, event); - UpdateCycleCount(); + // When clicked on undo, do not write to DB + if (event == DISMISS_EVENT_ACTION) return; - UpdateTaskCount(); - UpdateRemainingTaskCount(); - } - }).show(); + // Commit the changes to DB + switch (direction) + { + // Mark item as Done + case ItemTouchHelper.LEFT: + taskDataAccess.setDone(itemId); + break; + // Increase task cycle count + case ItemTouchHelper.RIGHT: + taskDataAccess.increaseCycle(task.getCycle(), itemId); + break; + case -1: + // Commit the changes to DB + taskDataAccess.deleteTask(itemId); + } + + //UpdateCycleCount(); + } + }).show(); } @Override @@ -315,7 +306,6 @@ public class TasksFragment extends Fragment implements priorityRadio.getText().toString(), taskList.getId()); - Bundle args = dialog.getArguments(); // Should never happen because we will have to be on this tab to open the dialog if (taskRecyclerViewAdapter == null) return; @@ -324,9 +314,6 @@ public class TasksFragment extends Fragment implements if (task == null) { taskRecyclerViewAdapter.add(newTask, 0); recyclerView.scrollToPosition(0); - - // Update the task count - UpdateTaskCount(); } // Update the task else { @@ -336,13 +323,12 @@ public class TasksFragment extends Fragment implements { // Remove item from current tab taskRecyclerViewAdapter.remove(position); + //UpdateCycleCount(); // Add it to the corresponding tab provided it is already instanciated mAdapter.onTaskListChanged(newTask, listSpinner.getSelectedItemPosition()); } else taskRecyclerViewAdapter.update(newTask, position); } - - UpdateRemainingTaskCount(); } @Override diff --git a/DoNExt/app/src/main/java/com/wismna/geoffroy/donext/helpers/TaskTouchHelper.java b/DoNExt/app/src/main/java/com/wismna/geoffroy/donext/helpers/TaskTouchHelper.java index e72f875..0c3af39 100644 --- a/DoNExt/app/src/main/java/com/wismna/geoffroy/donext/helpers/TaskTouchHelper.java +++ b/DoNExt/app/src/main/java/com/wismna/geoffroy/donext/helpers/TaskTouchHelper.java @@ -1,7 +1,6 @@ package com.wismna.geoffroy.donext.helpers; import android.graphics.Canvas; -import android.graphics.Color; import android.graphics.Paint; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.helper.ItemTouchHelper; @@ -50,27 +49,27 @@ public class TaskTouchHelper extends ItemTouchHelper.SimpleCallback { View itemView = viewHolder.itemView; Paint p = new Paint(); + p.setARGB(255, 222, 222, 222); if (dX > 0) { - /* Set your color for positive displacement */ - p.setARGB(255, 204, 229, 255); + // Set your color for positive displacement + //p.setARGB(255, 204, 229, 255); // Draw Rect with varying right side, equal to displacement dX c.drawRect((float) itemView.getLeft(), (float) itemView.getTop(), dX, (float) itemView.getBottom(), p); } else { - /* Set your color for negative displacement */ - p.setARGB(255, 204, 255, 229); + // Set your color for negative displacement + //p.setARGB(255, 204, 255, 229); // Draw Rect with varying left side, equal to the item's right side plus negative displacement dX c.drawRect((float) itemView.getRight() + dX, (float) itemView.getTop(), (float) itemView.getRight(), (float) itemView.getBottom(), p); } - super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); } } - @Override + /*@Override public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) { if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) { @@ -86,5 +85,5 @@ public class TaskTouchHelper extends ItemTouchHelper.SimpleCallback { viewHolder.itemView.setAlpha(1.0f); viewHolder.itemView.setBackgroundColor(0); - } + }*/ } diff --git a/DoNExt/app/src/main/java/com/wismna/geoffroy/donext/widgets/DividerItemDecoration.java b/DoNExt/app/src/main/java/com/wismna/geoffroy/donext/widgets/DividerItemDecoration.java new file mode 100644 index 0000000..d62cb71 --- /dev/null +++ b/DoNExt/app/src/main/java/com/wismna/geoffroy/donext/widgets/DividerItemDecoration.java @@ -0,0 +1,54 @@ +package com.wismna.geoffroy.donext.widgets; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.drawable.Drawable; +import android.support.v7.widget.RecyclerView; +import android.view.View; + +/** + * Created by geoffroy on 16-01-11. + * Displays dividers between RecyclerView items + */ +public class DividerItemDecoration extends RecyclerView.ItemDecoration { + + private static final int[] ATTRS = new int[]{android.R.attr.listDivider}; + + private Drawable mDivider; + + /** + * Default divider will be used + */ + public DividerItemDecoration(Context context) { + final TypedArray styledAttributes = context.obtainStyledAttributes(ATTRS); + mDivider = styledAttributes.getDrawable(0); + styledAttributes.recycle(); + } + + /** + * Custom divider will be used + */ + /*public DividerItemDecoration(Context context, int resId) { + mDivider = ContextCompat.getDrawable(context, resId); + }*/ + + @Override + public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { + int left = parent.getPaddingLeft(); + int right = parent.getWidth() - parent.getPaddingRight(); + + int childCount = parent.getChildCount(); + for (int i = 0; i < childCount; i++) { + View child = parent.getChildAt(i); + + RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); + + int top = child.getBottom() + params.bottomMargin; + int bottom = top + mDivider.getIntrinsicHeight(); + + mDivider.setBounds(left, top, right, bottom); + mDivider.draw(c); + } + } +} diff --git a/DoNExt/app/src/main/res/drawable/task_select.xml b/DoNExt/app/src/main/res/drawable/task_select.xml index 484668f..69996f8 100644 --- a/DoNExt/app/src/main/res/drawable/task_select.xml +++ b/DoNExt/app/src/main/res/drawable/task_select.xml @@ -1,5 +1,6 @@ - + + \ No newline at end of file diff --git a/DoNExt/app/src/main/res/layout/fragment_task_confirmation.xml b/DoNExt/app/src/main/res/layout/fragment_task_confirmation.xml index 2523e5b..ce1fa6d 100644 --- a/DoNExt/app/src/main/res/layout/fragment_task_confirmation.xml +++ b/DoNExt/app/src/main/res/layout/fragment_task_confirmation.xml @@ -7,8 +7,8 @@ android:id="@+id/task_confirmation_never" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginLeft="16dp" - android:layout_marginStart="16dp" + android:layout_marginLeft="@dimen/text_margin" + android:layout_marginStart="@dimen/text_margin" android:layout_marginTop="10dp" android:text="@string/task_confirmation_never_button" /> \ No newline at end of file diff --git a/DoNExt/app/src/main/res/layout/fragment_task.xml b/DoNExt/app/src/main/res/layout/fragment_task_detailed.xml similarity index 89% rename from DoNExt/app/src/main/res/layout/fragment_task.xml rename to DoNExt/app/src/main/res/layout/fragment_task_detailed.xml index c2947fe..f439c65 100644 --- a/DoNExt/app/src/main/res/layout/fragment_task.xml +++ b/DoNExt/app/src/main/res/layout/fragment_task_detailed.xml @@ -2,7 +2,10 @@ + android:paddingTop="5dp" + android:orientation="horizontal" + android:focusable="true" + android:background="?android:attr/selectableItemBackground" > + android:layout_height="wrap_content" + android:hint="@string/new_task_name_hint" /> + + + + + diff --git a/DoNExt/app/src/main/res/layout/fragment_tasks.xml b/DoNExt/app/src/main/res/layout/fragment_tasks.xml index cefebff..ba1fe3a 100644 --- a/DoNExt/app/src/main/res/layout/fragment_tasks.xml +++ b/DoNExt/app/src/main/res/layout/fragment_tasks.xml @@ -21,13 +21,13 @@ android:name="com.wismna.geoffroy.donext.activities.TaskFragment" android:layout_width="match_parent" android:layout_height="match_parent" - android:layout_marginLeft="16dp" - android:layout_marginRight="16dp" + android:layout_marginLeft="@dimen/text_margin" + android:layout_marginRight="@dimen/text_margin" android:layout_below="@id/total_task_cycles" app:layoutManager="LinearLayoutManager" app:layout_heightPercent="90%" tools:context=".fragments.TasksFragment" - tools:listitem="@layout/fragment_task" /> + tools:listitem="@layout/fragment_task_detailed" /> New list name Create + List name cannot be blank Delete Delete task list? - List Name + New task name + Task name cannot be blank Description + Optional task description Priority Low Normal @@ -43,10 +46,21 @@ Never ask again + Tasks + Task lists Mark task as Confirm on next? Confirm on done? Confirm on delete? + Task layout: + + Simple + Detailed + + + 1 + 2 + Maximum number of lists: 1 diff --git a/DoNExt/app/src/main/res/xml/preferences.xml b/DoNExt/app/src/main/res/xml/preferences.xml index bd054d1..65c4be1 100644 --- a/DoNExt/app/src/main/res/xml/preferences.xml +++ b/DoNExt/app/src/main/res/xml/preferences.xml @@ -1,23 +1,39 @@ - - - - + + + + + + + + + + \ No newline at end of file