Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cef62e00 authored by Gabor Keszthelyi's avatar Gabor Keszthelyi Committed by Marten Gajda
Browse files

Replace task details fragments instead of updating them. Fixes #624 (#630)

This solution fixes a number of actual and potential bugs around changing the content of the details pane. The view fragment can be simplified further. That's subject to another story.
parent d5496fc5
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -789,7 +789,9 @@ public class EditTaskFragment extends SupportFragment implements LoaderManager.L
                activity.finish();
                if (isNewTask)
                {
                    activity.startActivity(new Intent("android.intent.action.VIEW", mTaskUri));
                    activity.startActivity(
                            new Intent(Intent.ACTION_VIEW, mTaskUri)
                                    .putExtra(ViewTaskActivity.EXTRA_COLOR, mListColor));
                }
            }
            else
+30 −6
Original line number Diff line number Diff line
@@ -18,11 +18,13 @@ package org.dmfs.tasks;

import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import org.dmfs.android.bolts.color.colors.AttributeColor;
import org.dmfs.android.bolts.color.Color;
import org.dmfs.android.bolts.color.elementary.ValueColor;
import org.dmfs.android.retentionmagic.SupportFragment;


@@ -34,11 +36,22 @@ import org.dmfs.android.retentionmagic.SupportFragment;
 */
public class EmptyTaskFragment extends SupportFragment
{
    private static final String ARG_COLOR = "color";

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    private Color mColor;


    /**
     * @param color
     *         The color that the toolbars should take. (If available provide the actual task list color, otherwise the primary color.)
     */
    public static Fragment newInstance(Color color)
    {
        return inflater.inflate(R.layout.opentasks_fragment_empty_task, container, false);
        EmptyTaskFragment fragment = new EmptyTaskFragment();
        Bundle args = new Bundle();
        args.putInt(ARG_COLOR, color.argb());
        fragment.setArguments(args);
        return fragment;
    }


@@ -46,10 +59,21 @@ public class EmptyTaskFragment extends SupportFragment
    public void onAttach(Activity activity)
    {
        super.onAttach(activity);

        mColor = new ValueColor(getArguments().getInt(ARG_COLOR));

        if (activity instanceof ViewTaskFragment.Callback)
        {
            ((ViewTaskFragment.Callback) activity)
                    .updateColor(new AttributeColor(getContext(), R.attr.colorPrimary));
            ((ViewTaskFragment.Callback) activity).onListColorLoaded(mColor);
        }
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        View view = inflater.inflate(R.layout.opentasks_fragment_empty_task, container, false);
        view.findViewById(R.id.empty_task_fragment_appbar).setBackgroundColor(mColor.argb());
        return view;
    }
}
+1 −8
Original line number Diff line number Diff line
@@ -45,7 +45,6 @@ public class TaskGroupPagerAdapter extends FragmentStatePagerAdapter
    @SuppressWarnings("unused")
    private static final String TAG = "TaskGroupPager";
    private final Map<Integer, AbstractGroupingFactory> mGroupingFactories = new HashMap<Integer, AbstractGroupingFactory>(16);
    private boolean mTwoPaneLayout;
    private final TabConfig mTabConfig;


@@ -94,7 +93,7 @@ public class TaskGroupPagerAdapter extends FragmentStatePagerAdapter
        int pageId = mTabConfig.getVisibleItem(position).getId();
        AbstractGroupingFactory factory = getGroupingFactoryForId(pageId);

        TaskListFragment fragment = TaskListFragment.newInstance(position, mTwoPaneLayout);
        TaskListFragment fragment = TaskListFragment.newInstance(position);
        fragment.setExpandableGroupDescriptor(factory.getExpandableGroupDescriptor());
        fragment.setPageId(pageId);
        return fragment;
@@ -159,12 +158,6 @@ public class TaskGroupPagerAdapter extends FragmentStatePagerAdapter
    }


    public void setTwoPaneLayout(boolean twoPane)
    {
        mTwoPaneLayout = twoPane;
    }


    public int getTabIcon(int position)
    {
        return mTabConfig.getVisibleItem(position).getIcon();
+119 −110
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import android.os.Build.VERSION;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.TabLayout;
@@ -47,6 +48,8 @@ import android.view.Window;
import android.view.WindowManager;

import org.dmfs.android.bolts.color.Color;
import org.dmfs.android.bolts.color.colors.PrimaryColor;
import org.dmfs.android.bolts.color.elementary.ValueColor;
import org.dmfs.android.retentionmagic.annotations.Retain;
import org.dmfs.provider.tasks.AuthorityUtil;
import org.dmfs.tasks.contract.TaskContract.Tasks;
@@ -92,8 +95,6 @@ public class TaskListActivity extends BaseActivity implements TaskListFragment.C
     **/
    public static final String EXTRA_FORCE_LIST_SELECTION = "org.dmfs.tasks.FORCE_LIST_SELECTION";

    private static final String TAG = "TaskListActivity";

    private final static int REQUEST_CODE_NEW_TASK = 2924;

    /**
@@ -101,7 +102,7 @@ public class TaskListActivity extends BaseActivity implements TaskListFragment.C
     */
    private final static int SEARCH_UPDATE_DELAY = 400; // ms

    private final static String DETAIL_FRAGMENT_TAG = "taskListActivity.ViewTaskFragment";
    private final static String DETAILS_FRAGMENT_TAG = "details_fragment_tag";

    /**
     * Array of {@link ExpandableGroupDescriptor}s.
@@ -118,6 +119,14 @@ public class TaskListActivity extends BaseActivity implements TaskListFragment.C
    @Retain(permanent = true)
    private int mCurrentPageId;

    /**
     * The last used color for the toolbars. {@link android.graphics.Color#TRANSPARENT} represents the absent value.
     * (Used upon start/rotation until the actually selected task with its color is loaded, to avoid flashing up primary color.)
     */
    @Retain(permanent = true)
    @ColorInt
    private int mLastUsedColor = android.graphics.Color.TRANSPARENT;

    /**
     * The current pager position
     **/
@@ -148,12 +157,6 @@ public class TaskListActivity extends BaseActivity implements TaskListFragment.C
     **/
    private Uri mSelectedTaskUriOnLaunch;

    /**
     * Indicates to display the two pane layout with details
     **/
    @Retain
    private boolean mShouldShowDetails = false;

    /**
     * Indicates to show ViewTaskActivity when rotating to single pane.
     **/
@@ -180,6 +183,12 @@ public class TaskListActivity extends BaseActivity implements TaskListFragment.C
    {
        super.onCreate(savedInstanceState);

        if (mLastUsedColor == android.graphics.Color.TRANSPARENT)
        {
            // no saved color, use the primary color
            mLastUsedColor = new PrimaryColor(this).argb();
        }

        // check for single pane activity change
        mTwoPane = getResources().getBoolean(R.bool.has_two_panes);

@@ -187,10 +196,11 @@ public class TaskListActivity extends BaseActivity implements TaskListFragment.C

        if (mSelectedTaskUri != null)
        {
            if (mShouldShowDetails && mShouldSwitchToDetail)
            if (!mTwoPane && mShouldSwitchToDetail)
            {
                Intent viewTaskIntent = new Intent(Intent.ACTION_VIEW);
                viewTaskIntent.setData(mSelectedTaskUri);
                viewTaskIntent.putExtra(ViewTaskActivity.EXTRA_COLOR, mLastUsedColor);
                startActivity(viewTaskIntent);
                mShouldSwitchToDetail = false;
                mTransientState = true;
@@ -198,7 +208,7 @@ public class TaskListActivity extends BaseActivity implements TaskListFragment.C
        }
        else
        {
            mShouldShowDetails = false;
            mShouldSwitchToDetail = false;
        }

        setContentView(R.layout.activity_task_list);
@@ -211,21 +221,18 @@ public class TaskListActivity extends BaseActivity implements TaskListFragment.C

        if (findViewById(R.id.task_detail_container) != null)
        {
            // In two-pane mode, list items should be given the
            // 'activated' state when touched.

            // get list fragment
            // mTaskListFrag = (TaskListFragment) getSupportFragmentManager().findFragmentById(R.id.task_list);
            // mTaskListFrag.setListViewScrollbarPositionLeft(true);

            // mTaskListFrag.setActivateOnItemClick(true);

            loadTaskDetailFragment(mSelectedTaskUri);
            /* Note: 'savedInstanceState == null' is not used here as would be usual with fragments, because of the case of when rotation means
            switching from one-pane mode to two-pane mode on small tablets and the fragment has to added. To cover that case as well, the fragment is always replaced. */
            replaceTaskDetailsFragment(
                    mSelectedTaskUri == null ?
                            EmptyTaskFragment.newInstance(new ValueColor(mLastUsedColor))
                            : ViewTaskFragment.newInstance(mSelectedTaskUri, new ValueColor(mLastUsedColor)));
        }
        else
        {
            // When rotating the screen means switching from two-pane to single-pane mode (on small tablets), remove the obsolete fragment that gets recreated by FragmentManager:
            FragmentManager fragmentManager = getSupportFragmentManager();
            Fragment detailFragment = fragmentManager.findFragmentByTag(DETAIL_FRAGMENT_TAG);
            Fragment detailFragment = fragmentManager.findFragmentByTag(DETAILS_FRAGMENT_TAG);
            if (detailFragment != null)
            {
                fragmentManager.beginTransaction().remove(detailFragment).commit();
@@ -238,8 +245,6 @@ public class TaskListActivity extends BaseActivity implements TaskListFragment.C

        mPagerAdapter = new Unchecked<>(() -> new TaskGroupPagerAdapter(getSupportFragmentManager(), mGroupingFactories, this, R.xml.listview_tabs)).value();

        // Setup ViewPager
        mPagerAdapter.setTwoPaneLayout(mTwoPane);
        mViewPager = (ViewPager) findViewById(R.id.pager);
        mViewPager.setAdapter(mPagerAdapter);

@@ -379,20 +384,19 @@ public class TaskListActivity extends BaseActivity implements TaskListFragment.C
     * Callback method from {@link TaskListFragment.Callbacks} indicating that the item with the given ID was selected.
     */
    @Override
    public void onItemSelected(Uri uri, boolean forceReload, int pagePosition)
    public void onItemSelected(@NonNull Uri uri, @NonNull Color taskListColor, boolean forceReload, int pagePosition)
    {
        // only accept selections from the current visible task fragment or the activity itself
        if (pagePosition == -1 || pagePosition == mCurrentPagePosition)
        {
            if (mTwoPane)
            {
                mShouldShowDetails = true;
                if (forceReload)
                {
                    mSelectedTaskUri = null;
                    mSelectedTaskUri = uri;
                    mShouldSwitchToDetail = false;
                }
                loadTaskDetailFragment(uri);
                replaceTaskDetailsFragment(ViewTaskFragment.newInstance(uri, taskListColor));
            }
            else if (forceReload)
            {
@@ -402,6 +406,7 @@ public class TaskListActivity extends BaseActivity implements TaskListFragment.C
                // for the selected item ID.
                Intent detailIntent = new Intent(Intent.ACTION_VIEW);
                detailIntent.setData(uri);
                detailIntent.putExtra(ViewTaskActivity.EXTRA_COLOR, mLastUsedColor);
                startActivity(detailIntent);
                mShouldSwitchToDetail = false;
            }
@@ -409,34 +414,48 @@ public class TaskListActivity extends BaseActivity implements TaskListFragment.C
    }


    private void loadTaskDetailFragment(Uri uri)
    @Override
    public void onItemRemoved(@NonNull Uri taskUri)
    {
        Fragment detailFragment = getSupportFragmentManager().findFragmentByTag(DETAIL_FRAGMENT_TAG);

        if (uri == null)
        if (taskUri.equals(mSelectedTaskUri))
        {
            if (!(detailFragment instanceof EmptyTaskFragment))
            mSelectedTaskUri = null;
            if (mTwoPane)
            {
                replaceDetailFragment(new EmptyTaskFragment());
                replaceTaskDetailsFragment(EmptyTaskFragment.newInstance(new ValueColor(mLastUsedColor)));
            }
        }
        else
        {
            if (detailFragment instanceof ViewTaskFragment)
    }


    @Override
    public void onAddNewTask()
    {
                ((ViewTaskFragment) detailFragment).loadUri(uri);
        Intent editTaskIntent = new Intent(Intent.ACTION_INSERT);
        editTaskIntent.setData(Tasks.getContentUri(mAuthority));
        startActivityForResult(editTaskIntent, REQUEST_CODE_NEW_TASK);
    }
            else


    @Override
    public ExpandableGroupDescriptor getGroupDescriptor(int pageId)
    {
                replaceDetailFragment(ViewTaskFragment.newInstance(uri));
        for (AbstractGroupingFactory factory : mGroupingFactories)
        {
            if (factory.getId() == pageId)
            {
                return factory.getExpandableGroupDescriptor();
            }
        }
        return null;
    }


    private void replaceDetailFragment(Fragment fragment)
    private void replaceTaskDetailsFragment(@NonNull Fragment fragment)
    {
        getSupportFragmentManager().beginTransaction().replace(R.id.task_detail_container, fragment, DETAIL_FRAGMENT_TAG).commit();
        getSupportFragmentManager().beginTransaction()
                .setCustomAnimations(0, R.anim.openttasks_fade_exit, 0, 0)
                .replace(R.id.task_detail_container, fragment, DETAILS_FRAGMENT_TAG).commit();
    }


@@ -467,30 +486,6 @@ public class TaskListActivity extends BaseActivity implements TaskListFragment.C
    }


    @Override
    public void onEditTask(Uri taskUri, ContentSet data)
    {
        Intent editTaskIntent = new Intent(Intent.ACTION_EDIT);
        editTaskIntent.setData(taskUri);
        if (data != null)
        {
            Bundle extraBundle = new Bundle();
            extraBundle.putParcelable(EditTaskActivity.EXTRA_DATA_CONTENT_SET, data);
            editTaskIntent.putExtra(EditTaskActivity.EXTRA_DATA_BUNDLE, extraBundle);
        }
        startActivity(editTaskIntent);
    }


    @Override
    public void onAddNewTask()
    {
        Intent editTaskIntent = new Intent(Intent.ACTION_INSERT);
        editTaskIntent.setData(Tasks.getContentUri(mAuthority));
        startActivityForResult(editTaskIntent, REQUEST_CODE_NEW_TASK);
    }


    private void resolveIntentAction(Intent intent)
    {
        // check which task should be selected
@@ -542,14 +537,67 @@ public class TaskListActivity extends BaseActivity implements TaskListFragment.C


    @Override
    public void onDelete(Uri taskUri)
    public void onTaskEditRequested(@NonNull Uri taskUri, ContentSet data)
    {
        // nothing to do here, the loader will take care of reloading the list and the list view will take care of selecting the next element.
        Intent editTaskIntent = new Intent(Intent.ACTION_EDIT);
        editTaskIntent.setData(taskUri);
        if (data != null)
        {
            Bundle extraBundle = new Bundle();
            extraBundle.putParcelable(EditTaskActivity.EXTRA_DATA_CONTENT_SET, data);
            editTaskIntent.putExtra(EditTaskActivity.EXTRA_DATA_BUNDLE, extraBundle);
        }
        startActivity(editTaskIntent);
    }


    @Override
    public void onTaskDeleted(@NonNull Uri taskUri)
    {
        if (taskUri.equals(mSelectedTaskUri)) // Only the selected task can be deleted on the UI, but just to be safe
        {
            mSelectedTaskUri = null;
            if (mTwoPane)
            {
                // empty the detail fragment
                replaceTaskDetailsFragment(EmptyTaskFragment.newInstance(new ValueColor(mLastUsedColor)));
            }
        }
        // The loader will take care of reloading the list and the list view will take care of selecting the next element.
    }


    @Override
    public void onTaskCompleted(@NonNull Uri taskUri)
    {
        /* TODO We delegate to onTaskDeleted() which was used previously for this event, too.
        This causes the removal of details view, but the task is selected again if completed tasks are shown. This causes a flash. */
        onTaskDeleted(taskUri);
    }


    @SuppressLint("NewApi")
    @Override
    public void onListColorLoaded(@NonNull Color color)
    {
        mLastUsedColor = color.argb();
        if (mTwoPane)
        {
            loadTaskDetailFragment(null);
            int colorInt = color.argb();
            getSupportActionBar().setBackgroundDrawable(new ColorDrawable(colorInt));
            mTabs.setBackgroundColor(colorInt);

            if (mAppBarLayout != null)
            {
                mAppBarLayout.setBackgroundColor(colorInt);
            }

            if (VERSION.SDK_INT >= 21)
            {
                Window window = getWindow();
                window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
                window.setStatusBarColor(darkenColor(colorInt));
            }
        }
    }

@@ -687,20 +735,6 @@ public class TaskListActivity extends BaseActivity implements TaskListFragment.C
    }


    @Override
    public ExpandableGroupDescriptor getGroupDescriptor(int pageId)
    {
        for (AbstractGroupingFactory factory : mGroupingFactories)
        {
            if (factory.getId() == pageId)
            {
                return factory.getExpandableGroupDescriptor();
            }
        }
        return null;
    }


    /**
     * Notifies the search fragment of an update.
     */
@@ -727,31 +761,6 @@ public class TaskListActivity extends BaseActivity implements TaskListFragment.C
    }


    @SuppressLint("NewApi")
    @Override
    public void updateColor(Color color)
    {
        if (mTwoPane)
        {
            int colorInt = color.argb();
            getSupportActionBar().setBackgroundDrawable(new ColorDrawable(colorInt));
            mTabs.setBackgroundColor(colorInt);

            if (mAppBarLayout != null)
            {
                mAppBarLayout.setBackgroundColor(colorInt);
            }

            if (VERSION.SDK_INT >= 21)
            {
                Window window = getWindow();
                window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
                window.setStatusBarColor(darkenColor(colorInt));
            }
        }
    }


    public Uri getSelectedTaskUri()
    {
        if (mShouldSelectTaskListItem)
+32 −25
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.design.widget.Snackbar;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
@@ -49,6 +50,8 @@ import android.widget.ExpandableListView.OnGroupCollapseListener;
import android.widget.ListView;
import android.widget.TextView;

import org.dmfs.android.bolts.color.Color;
import org.dmfs.android.bolts.color.elementary.ValueColor;
import org.dmfs.android.retentionmagic.SupportFragment;
import org.dmfs.android.retentionmagic.annotations.Parameter;
import org.dmfs.android.retentionmagic.annotations.Retain;
@@ -62,6 +65,7 @@ import org.dmfs.tasks.groupings.filters.AbstractFilter;
import org.dmfs.tasks.groupings.filters.ConstantFilter;
import org.dmfs.tasks.model.Model;
import org.dmfs.tasks.model.Sources;
import org.dmfs.tasks.model.TaskFieldAdapters;
import org.dmfs.tasks.utils.ExpandableGroupDescriptor;
import org.dmfs.tasks.utils.ExpandableGroupDescriptorAdapter;
import org.dmfs.tasks.utils.FlingDetector;
@@ -89,7 +93,6 @@ public class TaskListFragment extends SupportFragment
    private static final String TAG = "org.dmfs.tasks.TaskListFragment";

    private final static String ARG_INSTANCE_ID = "instance_id";
    private final static String ARG_TWO_PANE_LAYOUT = "two_pane_layout";

    private static final long INTERVAL_LISTVIEW_REDRAW = 60000;

@@ -125,14 +128,13 @@ public class TaskListFragment extends SupportFragment
    @Parameter(key = ARG_INSTANCE_ID)
    private int mInstancePosition;

    @Parameter(key = ARG_TWO_PANE_LAYOUT)
    private boolean mTwoPaneLayout;

    private Loader<Cursor> mCursorLoader;
    private String mAuthority;

    private Uri mSelectedTaskUri;

    private boolean mTwoPaneLayout;

    /**
     * The child position to open when the fragment is displayed.
     **/
@@ -149,11 +151,8 @@ public class TaskListFragment extends SupportFragment
        {
            selectChildView(parent, groupPosition, childPosition, true);

            if (mExpandableListView.getChoiceMode() == ExpandableListView.CHOICE_MODE_SINGLE)
            {
            mActivatedPositionGroup = groupPosition;
            mActivatedPositionChild = childPosition;
            }
            /*
             * In contrast to a ListView an ExpandableListView does not set the activated item on it's own. So we have to do that here.
             */
@@ -189,14 +188,27 @@ public class TaskListFragment extends SupportFragment
         *
         * @param taskUri
         *         The {@link Uri} of the selected task.
         * @param taskListColor
         *         the color of the task list (used for toolbars)
         * @param forceReload
         *         Whether to reload the task or not.
         */
        void onItemSelected(Uri taskUri, boolean forceReload, int pagePosition);
        void onItemSelected(@NonNull Uri taskUri, @NonNull Color taskListColor, boolean forceReload, int pagePosition);

        ExpandableGroupDescriptor getGroupDescriptor(int position);
        /**
         * Called when a task has been removed from the list.
         * <p>
         * TODO It's only called when task is deleted by the swipe out, and not when it is completed.
         * It should probably be called that time, too. See https://github.com/dmfs/opentasks/issues/641.
         *
         * @param taskUri
         *         the content uri of the task that has been removed
         */
        void onItemRemoved(@NonNull Uri taskUri);

        void onAddNewTask();

        ExpandableGroupDescriptor getGroupDescriptor(int position);
    }


@@ -216,12 +228,11 @@ public class TaskListFragment extends SupportFragment
    });


    public static TaskListFragment newInstance(int instancePosition, boolean twoPaneLayout)
    public static TaskListFragment newInstance(int instancePosition)
    {
        TaskListFragment result = new TaskListFragment();
        Bundle args = new Bundle();
        args.putInt(ARG_INSTANCE_ID, instancePosition);
        args.putBoolean(ARG_TWO_PANE_LAYOUT, twoPaneLayout);
        result.setArguments(args);
        return result;
    }
@@ -239,6 +250,9 @@ public class TaskListFragment extends SupportFragment
    public void onAttach(Activity activity)
    {
        super.onAttach(activity);

        mTwoPaneLayout = activity.getResources().getBoolean(R.bool.has_two_panes);

        mAuthority = AuthorityUtil.taskAuthority(activity);

        mAppContext = activity.getBaseContext();
@@ -487,18 +501,11 @@ public class TaskListFragment extends SupportFragment
            {
                return;
            }
            // TODO: for now we get the id of the task, not the instance, once we support recurrence we'll have to change that
            Long selectTaskId = cursor.getLong(cursor.getColumnIndex(Instances.TASK_ID));

            if (selectTaskId != null)
            {
                // Notify the active callbacks interface (the activity, if the fragment is attached to one) that an item has been selected.

                // TODO: use the instance URI one we support recurrence
                Uri taskUri = ContentUris.withAppendedId(Tasks.getContentUri(mAuthority), selectTaskId);

                mCallbacks.onItemSelected(taskUri, force, mInstancePosition);
            }
            // TODO For now we get the id of the task, not the instance, once we support recurrence we'll have to change that, use instance URI that time
            Uri taskUri = ContentUris.withAppendedId(Tasks.getContentUri(mAuthority), (long) TaskFieldAdapters.TASK_ID.get(cursor));
            Color taskListColor = new ValueColor(TaskFieldAdapters.LIST_COLOR.get(cursor));
            mCallbacks.onItemSelected(taskUri, taskListColor, force, mInstancePosition);
        }
    }

@@ -585,7 +592,7 @@ public class TaskListFragment extends SupportFragment
                // TODO: remove the task in a background task
                mAppContext.getContentResolver().delete(taskUri, null, null);
                Snackbar.make(mExpandableListView, getString(R.string.toast_task_deleted, taskTitle), Snackbar.LENGTH_SHORT).show();
                mCallbacks.onItemSelected(null, false, -1);
                mCallbacks.onItemRemoved(taskUri);
            }
        }).setMessage(getString(R.string.confirm_delete_message_with_title, taskTitle)).create().show();
    }
Loading