Swipe task left to mark as done

Swipe task right to mark as nexted (increase cycle count)
Handles confirmation dialog (with settings)
Re-add floating add task button
Disable scrolling horizontally (except on the first task) and vertically
This commit is contained in:
2015-12-09 21:03:05 -05:00
parent 982ed80a20
commit 322c706f3d
17 changed files with 589 additions and 60 deletions

View File

@@ -14,6 +14,7 @@
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
@@ -33,6 +34,14 @@
android:name="android.support.PARENT_ACTIVITY"
android:value=".activities.MainActivity" />
</activity>
<activity
android:name=".activities.TaskDetailsActivity"
android:label="@string/task_details_activity_title"
android:parentActivityName=".activities.MainActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".activities.MainActivity" />
</activity>
</application>
</manifest>

View File

@@ -0,0 +1,99 @@
package com.wismna.geoffroy.donext.ItemTouchHelpers;
import android.content.SharedPreferences;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.FragmentManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.view.View;
import com.wismna.geoffroy.donext.activities.MainActivity;
import com.wismna.geoffroy.donext.adapters.TaskAdapter;
import com.wismna.geoffroy.donext.database.TaskDataAccess;
import com.wismna.geoffroy.donext.fragments.ConfirmDialogFragment;
/**
* Created by geoffroy on 15-12-04.
*/
public class TaskTouchHelper extends ItemTouchHelper.SimpleCallback {
private TaskAdapter taskAdapter;
private TaskDataAccess taskDataAccess;
private FragmentManager fragmentManager;
public TaskTouchHelper(TaskAdapter taskAdapter, TaskDataAccess taskDataAccess, FragmentManager fragmentManager){
// No drag moves, only swipes
super(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT);
this.taskAdapter = taskAdapter;
this.taskDataAccess = taskDataAccess;
this.fragmentManager = fragmentManager;
}
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
//TODO: Not implemented here
return false;
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(viewHolder.itemView.getContext());
int itemPosition = viewHolder.getAdapterPosition();
ConfirmDialogFragment confirmDialogFragment = ConfirmDialogFragment.newInstance(taskAdapter);
Bundle args = new Bundle();
args.putInt("ItemPosition", itemPosition);
args.putInt("Direction", direction);
confirmDialogFragment.setArguments(args);
String title = "Confirm";
switch (direction)
{
// Mark item as Done
case ItemTouchHelper.LEFT:
boolean prefConfDone = sharedPref.getBoolean("pref_conf_done", true);
title = "Done";
if (prefConfDone) confirmDialogFragment.show(fragmentManager, title);
else MainActivity.PerformSwipe(taskDataAccess, taskAdapter, itemPosition, direction);
break;
// Increase task cycle count
case ItemTouchHelper.RIGHT:
title = "Next";
boolean prefConfNext = sharedPref.getBoolean("pref_conf_next", true);
if (prefConfNext) confirmDialogFragment.show(fragmentManager, title);
else MainActivity.PerformSwipe(taskDataAccess, taskAdapter, itemPosition, direction);
break;
}
}
@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,
float dX, float dY, int actionState, boolean isCurrentlyActive) {
if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
// Get RecyclerView item from the ViewHolder
View itemView = viewHolder.itemView;
Paint p = new Paint();
if (dX > 0) {
/* 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);
// 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);
}
}
}

View File

@@ -3,7 +3,9 @@ package com.wismna.geoffroy.donext.activities;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
@@ -12,6 +14,7 @@ import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
@@ -27,12 +30,17 @@ import com.wismna.geoffroy.donext.dao.Task;
import com.wismna.geoffroy.donext.dao.TaskList;
import com.wismna.geoffroy.donext.database.TaskDataAccess;
import com.wismna.geoffroy.donext.database.TaskListDataAccess;
import com.wismna.geoffroy.donext.fragments.ConfirmDialogFragment;
import com.wismna.geoffroy.donext.fragments.NewTaskFragment;
import com.wismna.geoffroy.donext.fragments.TasksFragment;
import java.util.List;
public class MainActivity extends AppCompatActivity implements NewTaskFragment.NewTaskListener, TasksFragment.OnListFragmentInteractionListener {
public class MainActivity extends AppCompatActivity implements
NewTaskFragment.NewTaskListener,
TasksFragment.OnListFragmentInteractionListener,
ConfirmDialogFragment.ConfirmDialogListener
{
protected TaskDataAccess taskDataAccess;
/**
@@ -50,7 +58,6 @@ public class MainActivity extends AppCompatActivity implements NewTaskFragment.N
*/
private ViewPager mViewPager;
private TaskListDataAccess taskListDataAccess;
private List<TaskList> taskLists;
@Override
@@ -70,7 +77,7 @@ public class MainActivity extends AppCompatActivity implements NewTaskFragment.N
taskDataAccess.open();
// Access database to retrieve Tabs
taskListDataAccess = new TaskListDataAccess(this);
TaskListDataAccess taskListDataAccess = new TaskListDataAccess(this);
taskListDataAccess.open();
taskLists = taskListDataAccess.getAllTaskLists();
@@ -83,6 +90,16 @@ public class MainActivity extends AppCompatActivity implements NewTaskFragment.N
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
// Add Task floating button
/*FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});*/
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
@@ -136,22 +153,20 @@ public class MainActivity extends AppCompatActivity implements NewTaskFragment.N
TaskList taskList = (TaskList) listSpinner.getSelectedItem();
// Add the task to the database
Task task = taskDataAccess.createTask(
nameText.getText().toString(),
descText.getText().toString(),
priorityRadio.getText().toString(),
taskList.getId());
nameText.getText().toString(),
descText.getText().toString(),
priorityRadio.getText().toString(),
taskList.getId());
// Update the corresponding tab adapter
TasksFragment taskFragment = (TasksFragment) mSectionsPagerAdapter.getRegisteredFragment(listSpinner.getSelectedItemPosition());
TaskAdapter taskAdapter = ((TaskAdapter)((RecyclerView)taskFragment.getView()).getAdapter());
TaskAdapter taskAdapter = ((TaskAdapter)((RecyclerView)taskFragment.getView().findViewById(R.id.task_list_view)).getAdapter());
taskAdapter.add(task, taskAdapter.getItemCount());
}
@Override
public void onDialogNegativeClick(DialogFragment dialog) {
/** Called when user clicks on the New Task floating button */
public void onNewTaskClick(View view) {
OpenNewTaskDialog();
}
/** Called when the user clicks the Settings button */
public void openSettings(MenuItem menuItem) {
Intent intent = new Intent(this, SettingsActivity.class);
@@ -165,15 +180,7 @@ public class MainActivity extends AppCompatActivity implements NewTaskFragment.N
/** Called when the user clicks the New Task button */
public void openNewTaskDialog(MenuItem menuItem) {
android.app.FragmentManager manager = getFragmentManager();
NewTaskFragment newTaskFragment = new NewTaskFragment();
// Set current tab value to new task dialog
Bundle args = new Bundle();
args.putInt("list", mViewPager.getCurrentItem());
newTaskFragment.setArguments(args);
newTaskFragment.show(manager, "Create new task");
OpenNewTaskDialog();
}
/** Will be called when the delete Task button is clicked */
@@ -187,6 +194,78 @@ public class MainActivity extends AppCompatActivity implements NewTaskFragment.N
}
@Override
public void onDialogPositiveClick(android.support.v4.app.DialogFragment dialog) {
Bundle args = dialog.getArguments();
int itemPosition = args.getInt("ItemPosition");
int direction = args.getInt("Direction");
TaskAdapter taskAdapter = ((ConfirmDialogFragment)dialog).getTaskAdapter();
PerformSwipe(taskDataAccess, taskAdapter, itemPosition, direction);
}
@Override
public void onDialogNeutralClick(android.support.v4.app.DialogFragment dialog) {
Bundle args = dialog.getArguments();
int itemPosition = args.getInt("ItemPosition");
int direction = args.getInt("Direction");
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putBoolean("pref_conf_next", false);
switch (direction)
{
// Mark item as Done
case ItemTouchHelper.LEFT:
editor.putBoolean("pref_conf_done", false);
break;
// Increase task cycle count
case ItemTouchHelper.RIGHT:
editor.putBoolean("pref_conf_next", false);
break;
}
editor.commit();
TaskAdapter taskAdapter = ((ConfirmDialogFragment)dialog).getTaskAdapter();
PerformSwipe(taskDataAccess, taskAdapter, itemPosition, direction);
}
private void OpenNewTaskDialog() {
android.app.FragmentManager manager = getFragmentManager();
NewTaskFragment newTaskFragment = new NewTaskFragment();
// Set current tab value to new task dialog
Bundle args = new Bundle();
args.putInt("list", mViewPager.getCurrentItem());
newTaskFragment.setArguments(args);
newTaskFragment.show(manager, "Create new task");
}
public static void PerformSwipe(TaskDataAccess taskDataAccess, TaskAdapter taskAdapter, int itemPosition, int direction) {
long itemId = taskAdapter.getItemId(itemPosition);
taskDataAccess.open();
Task task = taskAdapter.getItem(itemPosition);
taskAdapter.remove(itemPosition);
switch (direction)
{
// Mark item as Done
case ItemTouchHelper.LEFT:
taskDataAccess.setDone(itemId);
break;
// Increase task cycle count
case ItemTouchHelper.RIGHT:
int cycle = task.getCycle();
taskDataAccess.increaseCycle(cycle, itemId);
task.setCycle(cycle + 1);
int lastPosition = taskAdapter.getItemCount();
taskAdapter.add(task, lastPosition);
break;
}
taskDataAccess.close();
}
/**
* A {@link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the sections/tabs/pages.

View File

@@ -0,0 +1,15 @@
package com.wismna.geoffroy.donext.activities;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import com.wismna.geoffroy.donext.R;
public class TaskDetailsActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_task_details);
}
}

View File

@@ -45,11 +45,11 @@ public class TaskAdapter extends RecyclerView.Adapter<TaskAdapter.ViewHolder> {
holder.mView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (null != mListener) {
// Notify the active callbacks interface (the activity, if the
// fragment is attached to one) that an item has been selected.
mListener.onListFragmentInteraction(holder.mItem);
}
if (null != mListener) {
// Notify the active callbacks interface (the activity, if the
// fragment is attached to one) that an item has been selected.
mListener.onListFragmentInteraction(holder.mItem);
}
}
});
}
@@ -59,17 +59,32 @@ public class TaskAdapter extends RecyclerView.Adapter<TaskAdapter.ViewHolder> {
return mValues.size();
}
@Override
public long getItemId(int position) {
return getItem(position).getId();
}
public void add(Task item, int position) {
mValues.add(position, item);
notifyItemInserted(position);
}
public void remove(Task item) {
int position = mValues.indexOf(item);
public void remove(int position) {
//int position = mValues.indexOf(item);
mValues.remove(position);
notifyItemRemoved(position);
}
public void update(Task item, int position)
{
mValues.set(position, item);
notifyItemChanged(position);
}
public Task getItem(int position) {
return mValues.get(position);
}
public class ViewHolder extends RecyclerView.ViewHolder {
public final View mView;
public final TextView mIdView;

View File

@@ -40,6 +40,7 @@ public class TaskDataAccess {
public void close() {
dbHelper.close();
}
public Task createTask(String name, String description, String priority, long taskList) {
ContentValues values = new ContentValues();
values.put(DatabaseHelper.TASKS_COLUMN_NAME, name);
@@ -57,6 +58,10 @@ public class TaskDataAccess {
return newTask;
}
public void deleteTask(long taskId) {
}
/*public Cursor deleteTask(Cursor taskCursor) {
Task task = cursorToTask(taskCursor);
long id = task.getId();
@@ -97,7 +102,9 @@ public class TaskDataAccess {
Cursor cursor = database.rawQuery(
"SELECT COUNT(*) " +
" FROM " + DatabaseHelper.TASKS_TABLE_NAME +
" WHERE " + DatabaseHelper.TASKS_COLUMN_LIST + " = " + id, null);
" WHERE " + DatabaseHelper.TASKS_COLUMN_LIST + " = " + id +
" AND " + DatabaseHelper.TASKS_COLUMN_DONE + " = " + 0 +
" AND " + DatabaseHelper.TASKS_COLUMN_DELETED + " = " + 0, null);
cursor.moveToFirst();
taskCount = cursor.getInt(0);
cursor.close();
@@ -107,8 +114,10 @@ public class TaskDataAccess {
int totalCycles = 0;
Cursor cursor = database.rawQuery(
"SELECT SUM(" + DatabaseHelper.TASKS_COLUMN_CYCLE + ") " +
" FROM " + DatabaseHelper.TASKS_TABLE_NAME +
" WHERE " + DatabaseHelper.TASKS_COLUMN_LIST + " = " + id, null);
" FROM " + DatabaseHelper.TASKS_TABLE_NAME +
" WHERE " + DatabaseHelper.TASKS_COLUMN_LIST + " = " + id +
" AND " + DatabaseHelper.TASKS_COLUMN_DONE + " = " + 0 +
" AND " + DatabaseHelper.TASKS_COLUMN_DELETED + " = " + 0, null);
cursor.moveToFirst();
totalCycles = cursor.getInt(0);
cursor.close();
@@ -120,8 +129,24 @@ public class TaskDataAccess {
taskColumns, DatabaseHelper.COLUMN_ID + " = " + id, null, null, null, null);
}
public Cursor getAllTasksCursor(long id) {
return database.query(DatabaseHelper.TASKS_TABLE_NAME,
taskColumns, DatabaseHelper.TASKS_COLUMN_LIST + " = " + id, null, null, null, null);
return database.query(DatabaseHelper.TASKS_TABLE_NAME, taskColumns,
DatabaseHelper.TASKS_COLUMN_LIST + " = " + id +
" AND " + DatabaseHelper.TASKS_COLUMN_DONE + " = " + 0 +
" AND " + DatabaseHelper.TASKS_COLUMN_DELETED + " = " + 0,
null, null, null,
DatabaseHelper.TASKS_COLUMN_CYCLE + ", " + DatabaseHelper.COLUMN_ID + " ASC");
}
public int setDone(long id) {
ContentValues contentValues = new ContentValues();
contentValues.put(DatabaseHelper.TASKS_COLUMN_DONE, 1);
return database.update(DatabaseHelper.TASKS_TABLE_NAME, contentValues, DatabaseHelper.COLUMN_ID + " = " + id, null);
}
public int increaseCycle(int currentCycle, long id) {
ContentValues contentValues = new ContentValues();
contentValues.put(DatabaseHelper.TASKS_COLUMN_CYCLE, currentCycle + 1);
return database.update(DatabaseHelper.TASKS_TABLE_NAME, contentValues, DatabaseHelper.COLUMN_ID + " = " + id, null);
}
private Task cursorToTask(Cursor cursor) {

View File

@@ -0,0 +1,76 @@
package com.wismna.geoffroy.donext.fragments;
import android.app.Activity;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;
import com.wismna.geoffroy.donext.R;
import com.wismna.geoffroy.donext.adapters.TaskAdapter;
public class ConfirmDialogFragment extends DialogFragment {
public interface ConfirmDialogListener {
void onDialogPositiveClick(DialogFragment dialog);
void onDialogNeutralClick(DialogFragment dialog);
}
private ConfirmDialogListener confirmDialogListener;
private TaskAdapter taskAdapter;
public static ConfirmDialogFragment newInstance(TaskAdapter taskAdapter) {
Bundle args = new Bundle();
ConfirmDialogFragment fragment = new ConfirmDialogFragment();
fragment.taskAdapter = taskAdapter;
fragment.setArguments(args);
return fragment;
}
public TaskAdapter getTaskAdapter() {
return taskAdapter;
}
public void setTaskAdapter(TaskAdapter taskAdapter) {
this.taskAdapter = taskAdapter;
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// Verify that the host activity implements the callback interface
try {
// Instantiate the NoticeDialogListener so we can send events to the host
confirmDialogListener = (ConfirmDialogListener) activity;
} catch (ClassCastException e) {
// The activity doesn't implement the interface, throw exception
throw new ClassCastException(activity.toString()
+ " must implement NewTaskListener");
}
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage(R.string.task_swipe_confirmation_done)
.setPositiveButton(R.string.task_swipe_confirmation_yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
confirmDialogListener.onDialogPositiveClick(ConfirmDialogFragment.this);
}
})
.setNegativeButton(R.string.task_swipe_confirmation_no, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// User cancelled the dialog
}
}).setNeutralButton(R.string.task_swipe_confirmation_never, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
confirmDialogListener.onDialogNeutralClick(ConfirmDialogFragment.this);
}
}
);
// Create the AlertDialog object and return it
return builder.create();
}
}

View File

@@ -13,7 +13,6 @@ import android.widget.Spinner;
import com.wismna.geoffroy.donext.R;
import com.wismna.geoffroy.donext.dao.TaskList;
import com.wismna.geoffroy.donext.database.TaskDataAccess;
import com.wismna.geoffroy.donext.database.TaskListDataAccess;
import java.util.List;
@@ -27,11 +26,11 @@ public class NewTaskFragment extends DialogFragment {
* implement this interface in order to receive event callbacks.
* Each method passes the DialogFragment in case the host needs to query it. */
public interface NewTaskListener {
public void onDialogPositiveClick(DialogFragment dialog);
public void onDialogNegativeClick(DialogFragment dialog);
void onDialogPositiveClick(DialogFragment dialog);
//void onDialogNegativeClick(DialogFragment dialog);
}
private TaskDataAccess taskDataAccess;
//private TaskDataAccess taskDataAccess;
// Use this instance of the interface to deliver action events
private NewTaskListener mListener;

View File

@@ -0,0 +1,109 @@
package com.wismna.geoffroy.donext.fragments;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.wismna.geoffroy.donext.R;
/**
* A simple {@link Fragment} subclass.
* Activities that contain this fragment must implement the
* {@link TaskDetailsFragment.OnFragmentInteractionListener} interface
* to handle interaction events.
* Use the {@link TaskDetailsFragment#newInstance} factory method to
* create an instance of this fragment.
*/
public class TaskDetailsFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private OnFragmentInteractionListener mListener;
public TaskDetailsFragment() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment TaskDetailsFragment.
*/
// TODO: Rename and change types and number of parameters
public static TaskDetailsFragment newInstance(String param1, String param2) {
TaskDetailsFragment fragment = new TaskDetailsFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_task_details, container, false);
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p/>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
}

View File

@@ -5,12 +5,14 @@ import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import com.wismna.geoffroy.donext.ItemTouchHelpers.TaskTouchHelper;
import com.wismna.geoffroy.donext.R;
import com.wismna.geoffroy.donext.adapters.TaskAdapter;
import com.wismna.geoffroy.donext.dao.Task;
@@ -25,7 +27,6 @@ import com.wismna.geoffroy.donext.listeners.RecyclerItemClickListener;
*/
public class TasksFragment extends Fragment {
private TaskDataAccess taskDataAccess;
private static final String TASK_LIST_ID = "task_list_id";
private long taskListId = -1;
private OnListFragmentInteractionListener mListener;
@@ -59,26 +60,13 @@ public class TasksFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_task_list, container, false);
// Set the adapter
final Context context = view.getContext();
// Set the Recycler view
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.task_list_view);
final Toast mToast = Toast.makeText(getActivity(), "", Toast.LENGTH_SHORT);
recyclerView.setLayoutManager(new LinearLayoutManager(context));
recyclerView.addOnItemTouchListener(
new RecyclerItemClickListener(context, new RecyclerItemClickListener.OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
// TODO: implement on item click event
TextView editText = (TextView) view.findViewById(R.id.task_id);
mToast.setText("Item " + editText.getText() + " clicked!");
mToast.show();
}
})
);
taskDataAccess = new TaskDataAccess(view.getContext());
TaskDataAccess taskDataAccess = new TaskDataAccess(view.getContext());
taskDataAccess.open();
// Set total cycles
@@ -92,6 +80,30 @@ public class TasksFragment extends Fragment {
// Set RecyclerView Adapter
TaskAdapter taskAdapter = new TaskAdapter(taskDataAccess.getAllTasks(taskListId), mListener);
recyclerView.setAdapter(taskAdapter);
taskDataAccess.close();
// Set ItemTouch helper in RecyclerView to handle swipe move on elements
// TODO: conflicts with ItemTouchListener, see why
ItemTouchHelper.Callback callback = new TaskTouchHelper(taskAdapter, taskDataAccess, getFragmentManager());
ItemTouchHelper helper = new ItemTouchHelper(callback);
helper.attachToRecyclerView(recyclerView);
// Implements touch listener to add click detection
// TODO: conflicts with ItemTouchHelper (maybe add swipe detection there with onFling?)
final Toast mToast = Toast.makeText(getActivity(), "", Toast.LENGTH_SHORT);
recyclerView.addOnItemTouchListener(
new RecyclerItemClickListener(context, new RecyclerItemClickListener.OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
// TODO: implement on item click event
TextView editText = (TextView) view.findViewById(R.id.task_id);
//Toast mToast = Toast.makeText(context, "Item " + editText.getText() + " clicked!", Toast.LENGTH_SHORT);
mToast.setText("Item " + editText.getText() + " clicked!");
mToast.show();
}
})
);
return view;
}

View File

@@ -31,14 +31,17 @@ public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListen
@Override
public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) {
View childView = view.findChildViewUnder(e.getX(), e.getY());
int childId = view.getChildAdapterPosition(childView);
if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
mListener.onItemClick(childView, view.getChildAdapterPosition(childView));
}
return false;
// Allows swipe moves only on first element of the list
return childId != 0;
}
@Override
public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) {
}
@Override

View File

@@ -0,0 +1,32 @@
package com.wismna.geoffroy.donext.widgets;
import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
/**
* Created by geoffroy on 15-12-04.
*/
public class NonSwipeableViewPager extends ViewPager {
public NonSwipeableViewPager(Context context) {
super(context);
}
public NonSwipeableViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
// Never allow swiping to switch between pages
return false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// Never allow swiping to switch between pages
return false;
}
}

View File

@@ -30,10 +30,18 @@
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
<com.wismna.geoffroy.donext.widgets.NonSwipeableViewPager
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_margin="@dimen/fab_margin"
android:onClick="onNewTaskClick"
android:src="@android:drawable/ic_input_add" />
</android.support.design.widget.CoordinatorLayout>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.wismna.geoffroy.donext.activities.TaskDetailsActivity">
<fragment
android:name="com.wismna.geoffroy.donext.fragments.TaskDetailsFragment"
android:id="@+id/task_details_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>

View File

@@ -1,8 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
android:layout_width="match_parent"
android:layout_height="?listPreferredItemHeight"
android:orientation="horizontal"
android:foreground="?selectableItemBackground" >
<TextView
android:id="@+id/task_id"
android:layout_width="wrap_content"

View File

@@ -0,0 +1,18 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.wismna.geoffroy.donext.fragments.TaskDetailsFragment">
<EditText
android:id="@+id/task_details_name"
android:layout_width="300dp"
android:layout_height="50dp"
android:text="@string/hello_blank_fragment" />
<EditText
android:id="@+id/task_details_description"
android:layout_width="300dp"
android:layout_height="50dp"
android:layout_below="@id/task_details_name"
android:text="@string/hello_blank_fragment" />
</RelativeLayout>

View File

@@ -26,6 +26,16 @@
<string name="new_task_save">Save</string>
<string name="new_task_cancel">Cancel</string>
<!-- String related to task details activity -->
<string name="task_details_activity_title">Details</string>
<!-- String related to task list Recycler View -->
<string name="task_swipe_confirmation_title">Confirm</string>
<string name="task_swipe_confirmation_done">Mark task as Done?</string>
<string name="task_swipe_confirmation_next">Mark task as Nexted?</string>
<string name="task_swipe_confirmation_yes">Yes</string>
<string name="task_swipe_confirmation_no">No</string>
<string name="task_swipe_confirmation_never">Never ask again</string>
<!-- Strings related to Settings -->
<string name="settings_confirm_donext">Confirm on DoNext?</string>
@@ -42,4 +52,7 @@
<item>7</item>
</string-array>
<string name="title_activity_task_list">TaskListActivity</string>
<!-- TODO: Remove or change this placeholder text -->
<string name="hello_blank_fragment">Hello blank fragment</string>
</resources>