package net.osmand.plus.quickaction; import android.content.DialogInterface; import android.content.res.Resources; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.design.widget.FloatingActionButton; import android.support.v4.content.ContextCompat; import android.support.v4.view.MotionEventCompat; import android.support.v7.app.AlertDialog; import android.support.v7.view.ContextThemeWrapper; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.support.v7.widget.helper.ItemTouchHelper; import android.util.Log; import android.util.TypedValue; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.base.BaseOsmAndFragment; import java.util.ArrayList; import java.util.Collections; import java.util.List; import static android.util.TypedValue.COMPLEX_UNIT_DIP; /** * Created by okorsun on 20.12.16. */ public class QuickActionListFragment extends BaseOsmAndFragment implements QuickActionRegistry.QuickActionUpdatesListener{ public static final String TAG = QuickActionListFragment.class.getSimpleName(); RecyclerView quickActionRV; FloatingActionButton fab; QuickActionAdapter adapter; ItemTouchHelper touchHelper; QuickActionRegistry quickActionRegistry; @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.quick_action_list, container, false); quickActionRV = (RecyclerView) view.findViewById(R.id.recycler_view); fab = (FloatingActionButton) view.findViewById(R.id.fabButton); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { AddQuickActionDialog dialog = new AddQuickActionDialog(); dialog.show(getFragmentManager(), AddQuickActionDialog.TAG); } }); return view; } @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); quickActionRegistry = getMapActivity().getMapLayers().getQuickActionRegistry(); setUpToolbar(view); setUpQuickActionRV(); } private void setUpQuickActionRV() { adapter = new QuickActionAdapter(new OnStartDragListener() { @Override public void onStartDrag(RecyclerView.ViewHolder viewHolder) { touchHelper.startDrag(viewHolder); } }); quickActionRV.setAdapter(adapter); quickActionRV.setLayoutManager(new LinearLayoutManager(getContext())); ItemTouchHelper.Callback touchHelperCallback = new QuickActionItemTouchHelperCallback(adapter); touchHelper = new ItemTouchHelper(touchHelperCallback); touchHelper.attachToRecyclerView(quickActionRV); adapter.addItems(quickActionRegistry.getFilteredQuickActions()); quickActionRV.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { if (dy > 0 && fab.getVisibility() == View.VISIBLE) fab.hide(); else if (dy < 0 && fab.getVisibility() != View.VISIBLE) fab.show(); } }); } private void setUpToolbar(View view) { Toolbar toolbar = (Toolbar) view.findViewById(R.id.custom_toolbar); Drawable back = getMyApplication().getIconsCache().getIcon(R.drawable.abc_ic_ab_back_mtrl_am_alpha); back.setColorFilter(ContextCompat.getColor(getContext(), R.color.color_white), PorterDuff.Mode.MULTIPLY); toolbar.setNavigationIcon(back); toolbar.setNavigationContentDescription(R.string.access_shared_string_navigate_up); toolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { getActivity().onBackPressed(); } }); toolbar.setTitle(R.string.configure_screen_quick_action); toolbar.setTitleTextColor(ContextCompat.getColor(getContext(), R.color.color_white)); } @Override public void onResume() { super.onResume(); getMapActivity().disableDrawer(); quickActionRegistry.setUpdatesListener(this); } @Override public void onPause() { super.onPause(); getMapActivity().enableDrawer(); quickActionRegistry.setUpdatesListener(null); } private MapActivity getMapActivity() { return (MapActivity) getActivity(); } private void saveQuickActions(){ quickActionRegistry.updateQuickActions(adapter.getQuickActions()); } void createAndShowDeleteDialog(final int itemPosition, final String itemName) { AlertDialog.Builder builder = new AlertDialog.Builder(new ContextThemeWrapper(getContext(), R.style.OsmandLightTheme)); builder.setTitle(R.string.quick_actions_delete); builder.setMessage(getResources().getString(R.string.quick_actions_delete_text, itemName)); builder.setIcon(getMyApplication().getIconsCache().getThemedIcon(R.drawable.ic_action_delete_dark)); builder.setPositiveButton(R.string.shared_string_yes, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { adapter.deleteItem(itemPosition); dialog.dismiss(); } }); builder.setNegativeButton(R.string.shared_string_no, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.dismiss(); } }); AlertDialog dialog = builder.show(); dialog.getButton(DialogInterface.BUTTON_NEGATIVE).setTextColor(ContextCompat.getColor(getContext(), R.color.dashboard_blue)); dialog.getButton(DialogInterface.BUTTON_POSITIVE).setTextColor(ContextCompat.getColor(getContext(), R.color.dashboard_blue)); } @Override public void onActionsUpdated() { adapter.addItems(quickActionRegistry.getFilteredQuickActions()); } public class QuickActionAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements QuickActionItemTouchHelperCallback.OnItemMoveCallback { public static final int SCREEN_ITEM_TYPE = 1; public static final int SCREEN_HEADER_TYPE = 2; private static final int ITEMS_IN_GROUP = 6; private List<QuickAction> itemsList = new ArrayList<>(); private final OnStartDragListener onStartDragListener; public QuickActionAdapter(OnStartDragListener onStartDragListener) { this.onStartDragListener = onStartDragListener; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { LayoutInflater inflater = LayoutInflater.from(parent.getContext()); if (viewType == SCREEN_ITEM_TYPE) return new QuickActionItemVH(inflater.inflate(R.layout.quick_action_list_item, parent, false)); else return new QuickActionHeaderVH(inflater.inflate(R.layout.quick_action_list_header, parent, false)); } @Override public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) { int viewType = getItemViewType(position); final QuickAction item = QuickActionFactory.produceAction(itemsList.get(position)); if (viewType == SCREEN_ITEM_TYPE) { final QuickActionItemVH itemVH = (QuickActionItemVH) holder; itemVH.title.setText(item.getName(getContext())); itemVH.subTitle.setText(getResources().getString(R.string.quick_action_item_action, getActionPosition(position))); itemVH.icon.setImageDrawable(getMyApplication().getIconsCache().getThemedIcon(item.getIconRes(getContext()))); itemVH.handleView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN) { onStartDragListener.onStartDrag(itemVH); } return false; } }); itemVH.closeBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { createAndShowDeleteDialog(holder.getAdapterPosition(), getResources().getString(item.getNameRes())); } }); itemVH.container.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { CreateEditActionDialog dialog = CreateEditActionDialog.newInstance(item.id); dialog.show(getFragmentManager(), AddQuickActionDialog.TAG); } }); LinearLayout.LayoutParams dividerParams = (LinearLayout.LayoutParams) itemVH.divider.getLayoutParams(); //noinspection ResourceType dividerParams.setMargins(!isLongDivider(position) ? dpToPx(56f) : 0, 0, 0, 0); itemVH.divider.setLayoutParams(dividerParams); } else { QuickActionHeaderVH headerVH = (QuickActionHeaderVH) holder; headerVH.headerName.setText(getResources().getString(R.string.quick_action_item_screen, position / (ITEMS_IN_GROUP + 1) + 1)); } } @Override public int getItemCount() { return itemsList.size(); } @Override public int getItemViewType(int position) { return itemsList.get(position).type == 0 ? SCREEN_HEADER_TYPE : SCREEN_ITEM_TYPE; } public void deleteItem(int position) { if (position == -1 || position >= itemsList.size()) return; itemsList.remove(position); notifyItemRemoved(position); moveHeaders(position); showFABIfNotScrollable(); saveQuickActions(); } private void moveHeaders(int position) { for (int i = position; i < itemsList.size(); i++) { if (getItemViewType(i) == SCREEN_HEADER_TYPE) { if (i != itemsList.size() - 2) { Collections.swap(itemsList, i, i + 1); notifyItemMoved(i, i + 1); i++; } else { itemsList.remove(i); notifyItemRemoved(i); } } } notifyItemRangeChanged(position, itemsList.size() - position); int lastPosition = itemsList.size() - 1; if (getItemViewType(lastPosition) == SCREEN_HEADER_TYPE){ itemsList.remove(lastPosition); notifyItemRemoved(lastPosition); } } private void showFABIfNotScrollable() { LinearLayoutManager layoutManager = (LinearLayoutManager) quickActionRV.getLayoutManager(); int lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition(); if ((lastVisibleItemPosition == itemsList.size() - 1 || lastVisibleItemPosition == itemsList.size()) && layoutManager.findFirstVisibleItemPosition() == 0 && fab.getVisibility() != View.VISIBLE || itemsList.size() == 0) fab.show(); } public List<QuickAction> getQuickActions() { List<QuickAction> result = new ArrayList<>(); for (int i = 0; i < itemsList.size(); i++) { if (getItemViewType(i) == SCREEN_ITEM_TYPE) result.add(itemsList.get(i)); } return result; } public void addItems(List<QuickAction> data) { List<QuickAction> resultList = new ArrayList<>(); for (int i = 0; i < data.size(); i++) { if (i % ITEMS_IN_GROUP == 0) resultList.add(createHeader()); resultList.add(data.get(i)); } itemsList = resultList; notifyDataSetChanged(); } public void addItem(QuickAction item) { int oldSize = itemsList.size(); if (oldSize % (ITEMS_IN_GROUP + 1) == 0) itemsList.add(createHeader()); itemsList.add(item); notifyItemRangeInserted(oldSize, itemsList.size() - oldSize); } private QuickAction createHeader() { return new QuickAction(); } private int getActionPosition(int globalPosition) { return globalPosition % (ITEMS_IN_GROUP + 1); } private boolean isLongDivider(int globalPosition) { return getActionPosition(globalPosition) == ITEMS_IN_GROUP || globalPosition == getItemCount() - 1; } private int dpToPx(float dp) { Resources r = getActivity().getResources(); return (int) TypedValue.applyDimension( COMPLEX_UNIT_DIP, dp, r.getDisplayMetrics() ); } @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { if (viewHolder.getItemViewType() == SCREEN_HEADER_TYPE || target.getItemViewType() == SCREEN_HEADER_TYPE) return false; else { int selectedPosition = viewHolder.getAdapterPosition(); int targetPosition = target.getAdapterPosition(); Log.v(TAG, "selected: " + selectedPosition + ", target: " + targetPosition); if (selectedPosition < 0 || targetPosition < 0) return false; Collections.swap(itemsList, selectedPosition, targetPosition); if (selectedPosition - targetPosition < -1) { notifyItemMoved(selectedPosition, targetPosition); notifyItemMoved(targetPosition - 1, selectedPosition); } else if (selectedPosition - targetPosition > 1) { notifyItemMoved(selectedPosition, targetPosition); notifyItemMoved(targetPosition + 1, selectedPosition); } else { notifyItemMoved(selectedPosition, targetPosition); } notifyItemChanged(selectedPosition); notifyItemChanged(targetPosition); return true; } } @Override public void onViewDropped(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { saveQuickActions(); } public class QuickActionItemVH extends RecyclerView.ViewHolder { public TextView title; public TextView subTitle; public ImageView icon; public View divider; public ImageView handleView; public ImageView closeBtn; public View container; public QuickActionItemVH(View itemView) { super(itemView); // AndroidUtils.setListItemBackground(itemView.getContext(), itemView, getMyApplication().getDaynightHelper().isNightMode()); title = (TextView) itemView.findViewById(R.id.title); subTitle = (TextView) itemView.findViewById(R.id.subtitle); icon = (ImageView) itemView.findViewById(R.id.imageView); divider = itemView.findViewById(R.id.divider); handleView = (ImageView) itemView.findViewById(R.id.handle_view); closeBtn = (ImageView) itemView.findViewById(R.id.closeImageButton); container = itemView.findViewById(R.id.searchListItemLayout); handleView.setImageDrawable(getMyApplication().getIconsCache().getThemedIcon(R.drawable.ic_action_reorder)); closeBtn.setImageDrawable(getMyApplication().getIconsCache().getThemedIcon(R.drawable.ic_action_remove_dark)); } } public class QuickActionHeaderVH extends RecyclerView.ViewHolder { public TextView headerName; public QuickActionHeaderVH(View itemView) { super(itemView); headerName = (TextView) itemView.findViewById(R.id.header); } } } public interface OnStartDragListener { void onStartDrag(RecyclerView.ViewHolder viewHolder); } }