调整长按功能

This commit is contained in:
xingxing
2018-07-05 23:49:39 +08:00
parent bc16e2d21d
commit 396cf00b33
20 changed files with 381 additions and 166 deletions

View File

@@ -73,7 +73,7 @@ public class NoteAdapter extends RecyclerView.Adapter<NoteAdapter.NoteHolder> {
}
public void setSelected(Note note, boolean isSelected) {
if (!isSelected ) {
if (!isSelected) {
mSelectedNotes.remove(note.getId());
notifyDataSetChanged();
} else if (!mSelectedNotes.contains(note.getId())){

View File

@@ -0,0 +1,167 @@
package org.houxg.leamonax.ui;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.DialogFragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.TextView;
import org.houxg.leamonax.R;
import org.houxg.leamonax.model.Note;
import org.houxg.leamonax.utils.ScreenUtils;
import org.houxg.leamonax.utils.SkinCompatUtils;
import java.util.ArrayList;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
public class CommandDialogFragment extends DialogFragment {
public static final String TAG = "CommandDialogFragment";
public static final String ARG_NOTE = "ARG_NOTE";
@BindView(R.id.recycler_view)
RecyclerView mRecyclerView;
private Adapter mAdapter;
private int[] resIdList = new int[]{R.drawable.ic_share_black, R.drawable.ic_folder_open_black, R.drawable.ic_delete_black};
private int[] resIdWhiteList = new int[]{R.drawable.ic_share_white, R.drawable.ic_folder_open_white, R.drawable.ic_delete_white};
private String[] titleList = new String[]{"分享", "移动", "删除"};
private OnItemClickListener mOnItemClickListener;
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
mOnItemClickListener = onItemClickListener;
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = LayoutInflater.from(getContext()).inflate(R.layout.fragment_dialog_note, container, false);
ButterKnife.bind(this, view);
return view;
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mAdapter = new Adapter();
mAdapter.setData(generateData());
mAdapter.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
if (mOnItemClickListener != null) {
mOnItemClickListener.onItemClick(view, position);
}
dismiss();
}
});
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
}
@Override
public void onStart() {
super.onStart();
getDialog().getWindow()
.setLayout(ScreenUtils.getScreenWidth(getContext()) * 4 / 5,
WindowManager.LayoutParams.WRAP_CONTENT);
getDialog().getWindow().setGravity(Gravity.CENTER);
getDialog().setCanceledOnTouchOutside(true);
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(DialogFragment.STYLE_NORMAL, R.style.customDialogFragment);
}
private List<CommandItem> generateData() {
List<CommandItem> itemList = new ArrayList<>();
for (int index = 0; index < resIdList.length; index++) {
CommandItem item = new CommandItem();
item.resId = SkinCompatUtils.isThemeNight() ? resIdWhiteList[index] : resIdList[index];
item.title = titleList[index];
itemList.add(item);
}
return itemList;
}
class CommandItem {
public int resId;
public String title;
}
class Adapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
List<CommandItem> itemList = new ArrayList<>();
OnItemClickListener onItemClickListener;
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
public void setData(List<CommandItem> dataList) {
itemList = dataList;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_dialog_note_item, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, int position) {
ViewHolder viewHolder = (ViewHolder) holder;
CommandItem item = itemList.get(position);
viewHolder.iconView.setImageResource(item.resId);
viewHolder.titleView.setText(item.title);
if (onItemClickListener != null) {
viewHolder.rootView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onItemClickListener.onItemClick(v, holder.getAdapterPosition());
}
});
}
}
@Override
public int getItemCount() {
return itemList.size();
}
}
class ViewHolder extends RecyclerView.ViewHolder {
ImageView iconView;
TextView titleView;
View rootView;
public ViewHolder(View itemView) {
super(itemView);
iconView = itemView.findViewById(R.id.icon);
titleView = itemView.findViewById(R.id.title);
rootView = itemView.findViewById(R.id.root_view);
}
}
interface OnItemClickListener {
void onItemClick(View view, int position);
}
public static CommandDialogFragment newInstance(Note note) {
CommandDialogFragment fragment = new CommandDialogFragment();
Bundle args = new Bundle();
args.putSerializable(ARG_NOTE, note);
fragment.setArguments(args);
return fragment;
}
}

View File

@@ -16,7 +16,6 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import org.greenrobot.eventbus.EventBus;
import org.houxg.leamonax.Leamonax;
import org.houxg.leamonax.R;
import org.houxg.leamonax.adapter.NoteAdapter;
@@ -24,8 +23,6 @@ import org.houxg.leamonax.database.NoteDataStore;
import org.houxg.leamonax.model.Account;
import org.houxg.leamonax.model.Note;
import org.houxg.leamonax.service.NoteService;
import org.houxg.leamonax.utils.ActionModeHandler;
import org.houxg.leamonax.utils.CollectionUtils;
import org.houxg.leamonax.utils.NetworkUtils;
import org.houxg.leamonax.utils.SharedPreferenceUtils;
import org.houxg.leamonax.utils.SkinCompatUtils;
@@ -47,7 +44,7 @@ import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Func1;
import rx.schedulers.Schedulers;
public class NoteFragment extends Fragment implements NoteAdapter.NoteAdapterListener, ActionModeHandler.Callback<Note> {
public class NoteFragment extends Fragment implements NoteAdapter.NoteAdapterListener {
private static final String EXT_SCROLL_POSITION = "ext_scroll_position";
private static final String SP_VIEW_TYPE = "sp_viewType";
@@ -56,7 +53,6 @@ public class NoteFragment extends Fragment implements NoteAdapter.NoteAdapterLis
RecyclerView mNoteListView;
List<Note> mNotes;
ActionModeHandler<Note> mActionModeHandler;
NoteList mNoteList;
Mode mCurrentMode;
OnSearchFinishListener mOnSearchFinishListener;
@@ -121,23 +117,6 @@ public class NoteFragment extends Fragment implements NoteAdapter.NoteAdapterLis
return view;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mActionModeHandler = new ActionModeHandler<>(getActivity(), this, R.menu.delete);
}
@Override
public void onResume() {
super.onResume();
}
@Override
public void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
public void setMode(Mode mode) {
mCurrentMode = mode;
List<Note> notes;
@@ -194,22 +173,32 @@ public class NoteFragment extends Fragment implements NoteAdapter.NoteAdapterLis
@Override
public void onClickNote(Note note) {
if (mActionModeHandler.isActionMode()) {
boolean isSelected = mActionModeHandler.chooseItem(note);
mNoteList.setSelected(note, isSelected);
} else {
startActivity(NotePreviewActivity.getOpenIntent(getActivity(), note.getId()));
}
startActivity(NotePreviewActivity.getOpenIntent(getActivity(), note.getId()));
}
@Override
public void onLongClickNote(final Note note) {
boolean isSelected = mActionModeHandler.chooseItem(note);
mNoteList.setSelected(note, isSelected);
CommandDialogFragment dialogFragment = CommandDialogFragment.newInstance(note);
dialogFragment.setOnItemClickListener(new CommandDialogFragment.OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
switch (position) {
case 0:
break;
case 1:
break;
case 2:
showAlertDialog(note);
break;
}
}
});
dialogFragment.show(getChildFragmentManager(), CommandDialogFragment.TAG);
}
private void deleteNote(List<Note> notes) {
Observable.from(notes)
private void deleteNote(Note note) {
Observable.just(note)
.flatMap(new Func1<Note, rx.Observable<Note>>() {
@Override
public rx.Observable<Note> call(final Note note) {
@@ -225,12 +214,11 @@ public class NoteFragment extends Fragment implements NoteAdapter.NoteAdapterLis
});
}
})
.buffer(notes.size())
.flatMap(new Func1<List<Note>, Observable<Note>>() {
.flatMap(new Func1<Note, Observable<Note>>() {
@Override
public Observable<Note> call(List<Note> notes) {
public Observable<Note> call(Note note) {
NetworkUtils.checkNetwork();
return Observable.from(notes);
return Observable.just(note);
}
})
.flatMap(new Func1<Note, Observable<Note>>() {
@@ -277,16 +265,7 @@ public class NoteFragment extends Fragment implements NoteAdapter.NoteAdapterLis
setMode(mCurrentMode);
}
@Override
public boolean onAction(int actionId, List<Note> pendingItems) {
if (CollectionUtils.isEmpty(pendingItems)) {
ToastUtils.show(getActivity(), R.string.no_note_was_selected);
return false;
}
final List<Note> waitToDelete = new ArrayList<>();
for (int i = 0; i < pendingItems.size(); i++) {
waitToDelete.add(pendingItems.get(i));
}
private void showAlertDialog(final Note note) {
new AlertDialog.Builder(getActivity())
.setTitle(R.string.delete_note)
.setMessage(R.string.are_you_sure_to_delete_note)
@@ -295,9 +274,7 @@ public class NoteFragment extends Fragment implements NoteAdapter.NoteAdapterLis
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
mActionModeHandler.getPendingItems().clear();
mActionModeHandler.dismiss();
deleteNote(waitToDelete);
deleteNote(note);
}
})
.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
@@ -307,14 +284,6 @@ public class NoteFragment extends Fragment implements NoteAdapter.NoteAdapterLis
}
})
.show();
return true;
}
@Override
public void onDestroy(List<Note> pendingItems) {
if (CollectionUtils.isNotEmpty(pendingItems)) {
mNoteList.invalidateAllSelected();
}
}
public enum Mode {

View File

@@ -1,107 +0,0 @@
package org.houxg.leamonax.utils;
import android.app.Activity;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.annotation.MenuRes;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuItem;
import org.houxg.leamonax.R;
import java.util.ArrayList;
import java.util.List;
public class ActionModeHandler<T> {
private List<T> mPendingItems;
private int mMenuId;
private Callback<T> mCallback;
private ActionMode mActionMode;
private Activity mContext;
private ActionMode.Callback mActionCallback = new ActionMode.Callback() {
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
mode.getMenuInflater().inflate(mMenuId, menu);
Drawable drawable = menu.findItem(R.id.action_delete).getIcon();
if (drawable != null) {
// If we don't mutate the drawable, then all drawable's with this id will have a color
// filter applied to it.
drawable.mutate();
drawable.setColorFilter(mContext.getResources().getColor(R.color.colorPrimaryDark), PorterDuff.Mode.SRC_ATOP);
drawable.setAlpha(255);
}
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return mCallback.onAction(item.getItemId(), mPendingItems);
}
@Override
public void onDestroyActionMode(ActionMode mode) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mContext.getWindow().setStatusBarColor(mContext.getResources().getColor(R.color.colorPrimary));
}
mCallback.onDestroy(mPendingItems);
mActionMode = null;
mPendingItems = null;
}
};
public ActionModeHandler(Activity activity, Callback<T> callback, @MenuRes int menuId) {
mContext = activity;
mMenuId = menuId;
mCallback = callback;
}
public List<T> getPendingItems() {
return mPendingItems;
}
/**
*
* @param item
* @return true if the item is in pending list, false for others.
*/
public boolean chooseItem(T item) {
if (isActionMode()) {
if (mPendingItems.contains(item)) {
mPendingItems.remove(item);
return false;
} else {
mPendingItems.add(item);
return true;
}
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mContext.getWindow().setStatusBarColor(mContext.getResources().getColor(R.color.colorPrimaryDark));
}
mActionMode = mContext.startActionMode(mActionCallback);
mPendingItems = new ArrayList<>();
mPendingItems.add(item);
return true;
}
}
public void dismiss() {
mActionMode.finish();
}
public boolean isActionMode() {
return mActionMode != null;
}
public interface Callback<T> {
boolean onAction(int actionId, List<T> pendingItems);
void onDestroy(List<T> pendingItems);
}
}

View File

@@ -0,0 +1,52 @@
package org.houxg.leamonax.utils;
import android.content.Context;
import android.graphics.Point;
import android.os.Build;
import android.view.WindowManager;
public final class ScreenUtils {
private ScreenUtils() {
throw new UnsupportedOperationException("u can't instantiate me...");
}
/**
* Return the width of screen, in pixel.
*
* @return the width of screen, in pixel
*/
public static int getScreenWidth(Context context) {
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
if (wm == null) {
return context.getResources().getDisplayMetrics().widthPixels;
}
Point point = new Point();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
wm.getDefaultDisplay().getRealSize(point);
} else {
wm.getDefaultDisplay().getSize(point);
}
return point.x;
}
/**
* Return the height of screen, in pixel.
*
* @return the height of screen, in pixel
*/
public static int getScreenHeight(Context context) {
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
if (wm == null) {
return context.getResources().getDisplayMetrics().heightPixels;
}
Point point = new Point();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
wm.getDefaultDisplay().getRealSize(point);
} else {
wm.getDefaultDisplay().getSize(point);
}
return point.y;
}
}

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!-- 填充 -->
<solid android:color="@color/white_night" />
<!-- 圆角 -->
<corners android:radius="6dp" />
</shape>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#8fffffff"
android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z"/>
</vector>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 533 B

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!-- 填充 -->
<solid android:color="@color/white" />
<!-- 圆角 -->
<corners android:radius="6dp" />
</shape>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#AF000000"
android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z"/>
</vector>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#AF000000"
android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z"/>
</vector>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#8FFFFFFF"
android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z"/>
</vector>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#AF000000"
android:pathData="M20,6h-8l-2,-2L4,4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,8c0,-1.1 -0.9,-2 -2,-2zM20,18L4,18L4,8h16v10z"/>
</vector>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#8FFFFFFF"
android:pathData="M20,6h-8l-2,-2L4,4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,8c0,-1.1 -0.9,-2 -2,-2zM20,18L4,18L4,8h16v10z"/>
</vector>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#AF000000"
android:pathData="M18,16.08c-0.76,0 -1.44,0.3 -1.96,0.77L8.91,12.7c0.05,-0.23 0.09,-0.46 0.09,-0.7s-0.04,-0.47 -0.09,-0.7l7.05,-4.11c0.54,0.5 1.25,0.81 2.04,0.81 1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3 -3,1.34 -3,3c0,0.24 0.04,0.47 0.09,0.7L8.04,9.81C7.5,9.31 6.79,9 6,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3c0.79,0 1.5,-0.31 2.04,-0.81l7.12,4.16c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.61 1.31,2.92 2.92,2.92 1.61,0 2.92,-1.31 2.92,-2.92s-1.31,-2.92 -2.92,-2.92z"/>
</vector>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#8FFFFFFF"
android:pathData="M18,16.08c-0.76,0 -1.44,0.3 -1.96,0.77L8.91,12.7c0.05,-0.23 0.09,-0.46 0.09,-0.7s-0.04,-0.47 -0.09,-0.7l7.05,-4.11c0.54,0.5 1.25,0.81 2.04,0.81 1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3 -3,1.34 -3,3c0,0.24 0.04,0.47 0.09,0.7L8.04,9.81C7.5,9.31 6.79,9 6,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3c0.79,0 1.5,-0.31 2.04,-0.81l7.12,4.16c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.61 1.31,2.92 2.92,2.92 1.61,0 2.92,-1.31 2.92,-2.92s-1.31,-2.92 -2.92,-2.92z"/>
</vector>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:background="@drawable/bg_shape_radius"
android:layout_height="wrap_content">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>

View File

@@ -10,7 +10,7 @@
android:id="@+id/check"
android:layout_width="36dp"
android:scaleType="center"
android:src="@drawable/ic_pop_checked"
android:src="@drawable/ic_check_black"
android:layout_height="match_parent" />
<TextView xmlns:android="http://schemas.android.com/apk/res/android"

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:clickable="true"
android:focusable="true"
android:background="?android:attr/selectableItemBackground"
android:paddingBottom="10dp"
android:paddingTop="10dp">
<ImageView
android:id="@+id/icon"
android:layout_marginLeft="16dp"
android:layout_width="24dp"
android:layout_height="24dp" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:textColor="@color/primary_text_light"
android:textSize="14sp" />
</LinearLayout>

View File

@@ -62,4 +62,11 @@
<item name="android:textColorHint">@color/hint_text_light</item>
</style>
<style name="customDialogFragment" parent="AppTheme">
<item name="android:windowNoTitle">true</item>
<item name="android:backgroundDimEnabled">true</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowBackground">@color/transparent</item>
</style>
</resources>