package com.seafile.seadroid2.ui.fragment; import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.support.v4.app.ListFragment; import android.support.v7.view.ActionMode; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.animation.AnimationUtils; import android.widget.AdapterView; import android.widget.ListView; import android.widget.TextView; import com.google.common.collect.Lists; import com.seafile.seadroid2.R; import com.seafile.seadroid2.transfer.TransferService; import com.seafile.seadroid2.transfer.TransferTaskInfo; import com.seafile.seadroid2.ui.activity.TransferActivity; import com.seafile.seadroid2.ui.adapter.TransferTaskAdapter; import java.util.List; /** * Base class for transfer task fragments * */ public abstract class TransferTaskFragment extends ListFragment { private String DEBUG_TAG = "TransferTaskFragment"; protected TransferTaskAdapter adapter; protected TransferActivity mActivity = null; protected ListView mTransferTaskListView; protected TextView emptyView; private View mListContainer; private View mProgressContainer; protected final Handler mTimer = new Handler(); protected TransferService txService = null; private ActionMode mActionMode; @Override public void onAttach(Activity activity) { super.onAttach(activity); mActivity = (TransferActivity) activity; } public ActionMode getActionMode() { return mActionMode; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View root = inflater.inflate(R.layout.transfer_task_fragment, container, false); mTransferTaskListView = (ListView) root.findViewById(android.R.id.list); mTransferTaskListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { if (mActionMode == null) { mActionMode = mActivity.startSupportActionMode(new ActionModeCallback()); } return true; } }); mListContainer = root.findViewById(R.id.listContainer); mProgressContainer = root.findViewById(R.id.progressContainer); emptyView = (TextView) root.findViewById(R.id.empty); return root; } private List<Integer> convertToTaskIds(List<Integer> positions) { List<Integer> taskIds = Lists.newArrayList(); for (int position : positions) { TransferTaskInfo tti = adapter.getItem(position); taskIds.add(tti.taskID); } return taskIds; } /** * deselect all items */ public void deselectItems() { if (adapter == null) return; adapter.deselectAllItems(); updateContextualActionBar(); } protected abstract void deleteSelectedItems(List<Integer> ids); protected abstract void restartSelectedItems(List<Integer> ids); @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); showLoading(true); } private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName className, IBinder service) { // Toast.makeText(mActivity, "Stop loading animations", Toast.LENGTH_LONG).show(); showLoading(false); TransferService.TransferBinder binder = (TransferService.TransferBinder) service; txService = binder.getService(); if (isNeedUpdateProgress()) { mTransferTaskListView.setVisibility(View.VISIBLE); emptyView.setVisibility(View.GONE); setUpTransferList(); startTimer(); } } @Override public void onServiceDisconnected(ComponentName arg0) { txService = null; } }; protected abstract List<? extends TransferTaskInfo> getTransferTaskInfos(); protected abstract void setUpTransferList(); @Override public void onResume() { super.onResume(); mTransferTaskListView.setVisibility(View.GONE); emptyView.setVisibility(View.VISIBLE); } @Override public void onStart() { super.onStart(); // bind transfer service Intent bIntent = new Intent(mActivity, TransferService.class); mActivity.bindService(bIntent, mConnection, Context.BIND_AUTO_CREATE); } protected abstract boolean isNeedUpdateProgress(); @Override public void onStop() { super.onStop(); stopTimer(); if (txService != null) { mActivity.unbindService(mConnection); txService = null; } } // refresh list by mTimer private void startTimer() { Log.d(DEBUG_TAG, "timer started"); mTimer.postDelayed(new Runnable() { @Override public void run() { adapter.setTransferTaskInfos(getTransferTaskInfos()); adapter.notifyDataSetChanged(); //Log.d(DEBUG_TAG, "timer post refresh signal " + System.currentTimeMillis()); mTimer.postDelayed(this, 1 * 1000); } }, 1 * 1000); } public void stopTimer() { mTimer.removeCallbacksAndMessages(null); } private void showLoading(boolean show) { if (mActivity == null) return; if (show) { mProgressContainer.startAnimation(AnimationUtils.loadAnimation( mActivity, android.R.anim.fade_in)); mListContainer.startAnimation(AnimationUtils.loadAnimation( mActivity, android.R.anim.fade_out)); mProgressContainer.setVisibility(View.VISIBLE); mListContainer.setVisibility(View.INVISIBLE); } else { mProgressContainer.startAnimation(AnimationUtils.loadAnimation( mActivity, android.R.anim.fade_out)); mListContainer.startAnimation(AnimationUtils.loadAnimation( mActivity, android.R.anim.fade_in)); mProgressContainer.setVisibility(View.GONE); mListContainer.setVisibility(View.VISIBLE); } } @Override public void onListItemClick(ListView l, View v, int position, long id) { if (mActionMode != null) { // add or remove selection for current list item if (adapter == null) return; adapter.toggleSelection(position); updateContextualActionBar(); } } /** * update state of contextual action bar */ public void updateContextualActionBar() { boolean itemsChecked = adapter.getCheckedItemCount() > 0; if (itemsChecked && mActionMode == null) { // there are some selected items, start the actionMode mActionMode = mActivity.startSupportActionMode(new ActionModeCallback()); adapter.actionModeOn(); } if (mActionMode != null) { // Log.d(DEBUG_TAG, "mActionMode.setTitle " + adapter.getCheckedItemCount()); mActionMode.setTitle(getResources().getQuantityString( R.plurals.transfer_list_items_selected, adapter.getCheckedItemCount(), adapter.getCheckedItemCount())); } } /** * Represents a contextual mode of the user interface. * Action modes can be used to provide alternative interaction modes and replace parts of the normal UI until finished. * A Callback configures and handles events raised by a user's interaction with an action mode. */ class ActionModeCallback implements ActionMode.Callback { private boolean allItemsSelected; public ActionModeCallback() { } @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { // Inflate the menu for the contextual action bar (CAB) MenuInflater inflater = mode.getMenuInflater(); inflater.inflate(R.menu.transfer_list_multi_choice_menu, menu); if (adapter == null) return true; adapter.actionModeOn(); adapter.notifyDataSetChanged(); return true; } @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { // Here you can perform updates to the contextual action bar (CAB) due to // an invalidate() request return false; } @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { // Respond to clicks on the actions in the contextual action bar (CAB) final List<Integer> selectedIds = adapter.getSelectedIds(); if (selectedIds.isEmpty()) { if (item.getItemId() != R.id.action_mode_select_all) { mActivity.showShortToast(mActivity, R.string.action_mode_no_items_selected); return true; } } switch (item.getItemId()) { case R.id.action_mode_delete: List<Integer> ids = adapter.getSelectedIds(); if (ids != null) { if (ids.size() == 0) { mActivity.showShortToast(mActivity, R.string.action_mode_no_items_selected); return true; } deleteSelectedItems(convertToTaskIds(ids)); deselectItems(); } break; case R.id.action_mode_restart: List<Integer> restartIds = adapter.getSelectedIds(); if (restartIds != null) { if (restartIds.size() == 0) { mActivity.showShortToast(mActivity, R.string.action_mode_no_items_selected); return true; } restartSelectedItems(convertToTaskIds(restartIds)); deselectItems(); } break; case R.id.action_mode_select_all: if (!allItemsSelected) { if (adapter == null) return true; adapter.selectAllItems(); updateContextualActionBar(); } else { if (adapter == null) return true; adapter.deselectAllItems(); updateContextualActionBar(); } allItemsSelected = !allItemsSelected; break; default: return false; } return true; } @Override public void onDestroyActionMode(ActionMode mode) { if (adapter == null) return; adapter.deselectAllItems(); adapter.actionModeOff(); // Here you can make any necessary updates to the activity when // the contextual action bar (CAB) is removed. By default, selected items are deselected/unchecked. mActionMode = null; } } }