java - 选择和删除多个 RecyclerView 项目 - AndroidX
问题描述
我已经编写了一个应用程序,它在回收视图中显示项目列表,并且还在 setOnLongClickListener 中添加了删除选项,但现在我想在“setOnLongClickListener”中添加一个选项,其中项目被选中,然后用户可以根据需要选择尽可能多的项目然后将它们全部删除,但似乎无法找出方法。
这是我的适配器:
public class TextTypingCustomAdapter extends RecyclerView.Adapter<TextTypingCustomAdapter.ViewHolder> implements Filterable {
private LayoutInflater mLayoutInflater;
private List<TextTypingObject> mTextTypingObjectList, mTextTypingObjectFilteredList;
public TextTypingCustomAdapter(@NonNull Context context, @NonNull List<TextTypingObject> textTypingObjectList) {
try {
mLayoutInflater = LayoutInflater.from(context);
} catch (Exception e) {
e.printStackTrace();
}
if (mLayoutInflater == null) {
try {
mLayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
} catch (Exception e) {
e.printStackTrace();
}
}
mTextTypingObjectList = mTextTypingObjectFilteredList = textTypingObjectList;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
return new ViewHolder(mLayoutInflater.inflate(R.layout.item_text_typing, viewGroup, false));
}
@Override
public void onBindViewHolder(@NonNull ViewHolder viewHolder, int i) {
TextTypingObject textTypingObject = mTextTypingObjectFilteredList.get(i);
if (textTypingObject != null) {
viewHolder.onBindViewHolder(textTypingObject, i == mTextTypingObjectFilteredList.size() - 1);
}
}
@Override
public int getItemCount() {
return mTextTypingObjectFilteredList != null ? mTextTypingObjectFilteredList.size() : 0;
}
// ----
class ViewHolder extends RecyclerView.ViewHolder {
TextView applicationNameTextView;
ImageView applicationIconImageView;
TextView dateTimeTextView;
TextView textTypingTextView;
TextView itemPackageNameSt;
View dividerView;
ViewHolder(@NonNull View itemView) {
super(itemView);
// ----
applicationNameTextView = itemView.findViewById(R.id.item_text_typing_application_name); // Text view
applicationIconImageView = itemView.findViewById(R.id.item_text_typing_application_icon); // Image view
dateTimeTextView = itemView.findViewById(R.id.item_text_typing_date_time); // Text view
textTypingTextView = itemView.findViewById(R.id.item_text_typing_text_typing); // Text view
dividerView = itemView.findViewById(R.id.item_clips_divider_view); // View
itemPackageNameSt = itemView.findViewById(R.id.content_input_event_package_name); // Text view
}
void onBindViewHolder(@NonNull TextTypingObject textTypingObject, boolean isLastItem) {
itemView.setOnClickListener(v -> {
Intent intent = new Intent(itemView.getContext(), TextTypingActivity.class);
intent.putExtra("id", textTypingObject.getEventId());
itemView.getContext().startActivity(intent);
});
itemView.setOnLongClickListener(v -> {
CFAlertDialog.Builder builder = new CFAlertDialog.Builder(v.getContext());
builder.setDialogStyle(CFAlertDialog.CFAlertStyle.ALERT);
builder.setHeaderView(R.layout.more_dialog_typed_text);
builder.setDialogBackgroundColor(Color.parseColor("#191919"));
builder.setTextColor(Color.parseColor("#FFFFFF"));
builder.setItems(new String[]{"Preview", "Delete"}, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int index) {
dialogInterface.dismiss();
switch (index) {
case 0: // "Preview"
Intent intent = new Intent(itemView.getContext(), TextTypingActivity.class);
intent.putExtra("id", textTypingObject.getEventId());
itemView.getContext().startActivity(intent);
break;
case 1: // "Delete"
deleteInputEvent(itemView.getContext(), textTypingObject);
break;
}
}
});
builder.show();
return true;
});
// ----
applicationNameTextView.setText(textTypingObject.getName());
applicationIconImageView.setImageDrawable(textTypingObject.getIcon());
// ----
String dateTime = null;
if (!DateFormat.is24HourFormat(itemView.getContext())) {
try {
dateTime = new SimpleDateFormat("hh:mm:ss a - E dd/MM/yy", Locale.getDefault()).format(new Date(textTypingObject.getTimestamp()));
} catch (Exception e) {
e.printStackTrace();
}
} else {
try {
dateTime = new SimpleDateFormat("HH:mm:ss - E dd/MM/yy", Locale.getDefault()).format(new Date(textTypingObject.getTimestamp()));
} catch (Exception e) {
e.printStackTrace();
}
}
// ----
String textTyping = textTypingObject.getTextTyping();
if (textTyping != null) {
if (textTyping.isEmpty() || textTyping.trim().isEmpty()) {
textTyping = "Blank space(s)";
textTypingTextView.setTextColor(ResourceUtil.getColor(itemView.getContext(), R.color.colorAccent));
}
}
// ----
dateTimeTextView.setText(dateTime != null ? dateTime : itemView.getContext().getString(R.string.date_time) + ": N/A");
textTypingTextView.setText(textTyping != null ? textTyping : itemView.getContext().getString(R.string.text_typing) + ": N/A");
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
dividerView.setVisibility(View.GONE);
} else if (isLastItem) {
dividerView.setVisibility(View.GONE);
}
String packageName = textTypingObject.getPackageName();
if (packageName != null) {
String itemPackageName = null;
// ----
PackageInfo packageInfo = null;
try {
packageInfo = itemView.getContext().getPackageManager().getPackageInfo(packageName, 0);
} catch (Exception e) {
e.printStackTrace();
}
if (packageInfo != null) {
ApplicationInfo applicationInfo = packageInfo.applicationInfo;
if (applicationInfo != null) {
itemPackageName = applicationInfo.packageName;
}
// ----
}
// ----
if (itemPackageName == null) {
itemPackageName = packageName;
}
// ----
itemPackageNameSt.setText(itemPackageName);
}
}
}
// ----
@Override
public Filter getFilter() {
return new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
String query = constraint != null ? constraint.toString() : null;
// ----
if (query != null && !query.isEmpty()) {
ArrayList<TextTypingObject> newFilteredTextTypingObjectArrayList = new ArrayList<>();
for (TextTypingObject textTypingObject : mTextTypingObjectList) {
if (textTypingObject.getTextTyping().toLowerCase(Locale.getDefault()).contains(query.toLowerCase(Locale.getDefault()))) {
newFilteredTextTypingObjectArrayList.add(textTypingObject);
}
}
// ----
mTextTypingObjectFilteredList = newFilteredTextTypingObjectArrayList;
} else {
mTextTypingObjectFilteredList = mTextTypingObjectList;
}
// ----
FilterResults filterResults = new FilterResults();
filterResults.values = mTextTypingObjectFilteredList;
filterResults.count = mTextTypingObjectFilteredList.size();
return filterResults;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults filterResults) {
/*if (filterResults.count == 0) {
// There is no "notifyDataSetInvalidated()" method in RecyclerView.Adapter
} else {*/
mTextTypingObjectFilteredList = (ArrayList<TextTypingObject>) filterResults.values;
// ----
notifyDataSetChanged();
/*}*/
}
};
}
private void deleteInputEvent(@NonNull Context context, @NonNull TextTypingObject textTypingObject) {
CFAlertDialog.Builder builder = new CFAlertDialog.Builder(context)
.setDialogStyle(CFAlertDialog.CFAlertStyle.ALERT)
.setDialogBackgroundColor(Color.parseColor("#191919"))
.setHeaderView(R.layout.delete_dialog)
.addButton("Yes, delete", Color.parseColor("#FFFFFF"), Color.parseColor("#1976d3"), CFAlertDialog.CFAlertActionStyle.POSITIVE, CFAlertDialog.CFAlertActionAlignment.JUSTIFIED, (dialog, which) -> {
dialog.dismiss();
Realm realm = null;
RealmResults<TypeViewTextChangedEventObject> mTypeViewTextChangedEventObjectRealmResults = null;
try {
realm = Realm.getDefaultInstance();
} catch (Exception e) {
e.printStackTrace();
}
if (realm != null && !realm.isClosed()) {
InputEventObject clipboardObject = null;
try {
clipboardObject = realm.where(InputEventObject.class).equalTo("id", textTypingObject.getEventId()).findFirst();
} catch (Exception e) {
e.printStackTrace();
}
if (clipboardObject != null) {
try {
realm.beginTransaction(); // Begin transaction
if (mTypeViewTextChangedEventObjectRealmResults != null) {
mTypeViewTextChangedEventObjectRealmResults.deleteAllFromRealm();
mTypeViewTextChangedEventObjectRealmResults = null;
}
clipboardObject.deleteFromRealm();
realm.commitTransaction(); // Commit transaction
// Refresh adapter
mTextTypingObjectList.remove(textTypingObject);
mTextTypingObjectFilteredList.remove(textTypingObject);
notifyDataSetChanged();
// - Refresh adapter
// ----
// Toast.makeText(context, "Typed text deleted successfully.", Toast.LENGTH_SHORT).show();
DynamicToast.make(context, "Deleted successfully",
context.getResources().getDrawable(R.drawable.ic_delete),
context.getResources().getColor(R.color.white),
context.getResources().getColor(R.color.successToast), Toast.LENGTH_LONG).show();
} catch (Exception e) {
e.printStackTrace();
// ----
// Toast.makeText(context, "Typed text could not be deleted.", Toast.LENGTH_SHORT).show();
DynamicToast.make(context, "Could not be deleted",
context.getResources().getDrawable(R.drawable.ic_baseline_block_24px),
context.getResources().getColor(R.color.white),
context.getResources().getColor(R.color.errorToast), Toast.LENGTH_LONG).show();
}
} else {
// Toast.makeText(context, "Typed text could not be deleted.", Toast.LENGTH_SHORT).show();
DynamicToast.make(context, "Could not be deleted",
context.getResources().getDrawable(R.drawable.ic_baseline_block_24px),
context.getResources().getColor(R.color.white),
context.getResources().getColor(R.color.errorToast), Toast.LENGTH_LONG).show();
}
}
});
builder.addButton(context.getString(android.R.string.no), Color.parseColor("#000000"), Color.parseColor("#FFFFFF"), CFAlertDialog.CFAlertActionStyle.DEFAULT, CFAlertDialog.CFAlertActionAlignment.JUSTIFIED, (dialog, which) -> {
dialog.dismiss();
});
builder.create().show();
}
}
这是我的片段:
public class TextTypingTabFragment extends Fragment implements TabLayoutFragmentPagerAdapter.ITabLayoutIconFragmentPagerAdapter {
private static final String TAG = TextTypingTabFragment.class.getSimpleName();
private final TextTypingLoaderCallbacks mLoaderCallbacks = new TextTypingLoaderCallbacks();
private TextTypingCustomAdapter mTextTypingCustomAdapter;
private View mView;
private ProgressBar mProgressBar;
private ScrollView mScrollView;
private RecyclerView mRecyclerView;
public TextTypingTabFragment() {
// Required empty public constructor
}
// ----
private Context getContextNonNull() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
return Objects.requireNonNull(getContext());
} else {
return getContext();
}
}
// ----
private int mItemCount = -1;
private int mFirstVisibleItemPosition = -1, mFirstCompletelyVisibleItemPosition = -1;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LogUtil.d(TAG, "Fragment create");
Bundle bundle = new Bundle();
bundle.putString(AppEnvr.EXTRA_PACKAGE_NAME_KEY, MainActivity.sSelectedPackageName);
getLoaderManager().initLoader(1, bundle, mLoaderCallbacks); // Init with 1
setHasOptionsMenu(true);
// ----
LocalBroadcastManager.getInstance(getContextNonNull()).registerReceiver(mSelectedPackageNameChangedCustomReceiver, new IntentFilter(AppEnvr.ACTION_SELECTED_PACKAGE_NAME_CHANGED));
}
@Override
public void onResume() {
super.onResume();
LogUtil.d(TAG, "Fragment resume");
Bundle bundle = new Bundle();
bundle.putString(AppEnvr.EXTRA_PACKAGE_NAME_KEY, MainActivity.sSelectedPackageName);
getLoaderManager().restartLoader(1, bundle, mLoaderCallbacks); // Restart with 1
}
@Override
public void onPause() {
super.onPause();
LogUtil.d(TAG, "Fragment pause");
if (mTextTypingCustomAdapter != null) {
mItemCount = mTextTypingCustomAdapter.getItemCount();
}
if (mRecyclerView != null) {
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) mRecyclerView.getLayoutManager();
if (linearLayoutManager != null) {
mFirstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition();
mFirstCompletelyVisibleItemPosition = linearLayoutManager.findFirstCompletelyVisibleItemPosition();
}
}
}
@Override
public void onDestroy() {
super.onDestroy();
LogUtil.d(TAG, "Fragment destroy");
LocalBroadcastManager.getInstance(getContextNonNull()).unregisterReceiver(mSelectedPackageNameChangedCustomReceiver);
}
// ----
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
return inflater.inflate(R.layout.fragment_text_typing_tab, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mView = view;
mProgressBar = view.findViewById(R.id.fragment_text_typing_tab_progress_bar);
mScrollView = view.findViewById(R.id.fragment_text_typing_tab_scroll_view);
mRecyclerView = view.findViewById(R.id.fragment_text_typing_tab_recycler_view);
}
// ----
@Override
public Fragment getItem() {
return this;
}
@Override
public CharSequence getPageTitle() {
return "History";
}
@Override
public int getIcon() {
return R.drawable.ic_typesave;
}
@Override
public void onCreateOptionsMenu(@NonNull Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.search_menu, menu);
final SearchView searchView = new SearchView(getActivity());
searchView.setQuery(null, true);
searchView.setQueryHint("Search Text");
try {
Field mDrawable = SearchView.class.getDeclaredField("mSearchHintIcon");
mDrawable.setAccessible(true);
Drawable drawable = (Drawable) mDrawable.get(searchView);
drawable.setTint(Color.DKGRAY);
drawable.setTintMode(PorterDuff.Mode.SRC_IN);
} catch (Exception e) {
e.printStackTrace();
}
ImageView searchCloseIcon = searchView.findViewById(androidx.appcompat.R.id.search_close_btn);
searchCloseIcon.setImageResource(R.drawable.ic_close);
EditText searchEditText = searchView.findViewById(androidx.appcompat.R.id.search_src_text);
View v = searchView.findViewById(androidx.appcompat.R.id.search_plate);
v.setBackgroundColor(Color.TRANSPARENT);
searchEditText.setTextColor(getResources().getColor(R.color.white));
searchEditText.setHintTextColor(getResources().getColor(R.color.drawerSecondaryText));
Typeface myCustomFont = Typeface.createFromAsset(getActivity().getAssets(),"fonts/regular.ttf");
searchEditText.setTypeface(myCustomFont);
searchEditText.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimensionPixelSize(R.dimen.search_text));
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String s) {
if(mTextTypingCustomAdapter != null) {
Filter filter = mTextTypingCustomAdapter.getFilter();
if (filter != null) {
filter.filter(s);
return true;
}
}
return false;
}
@Override
public boolean onQueryTextChange(String s) {
if(mTextTypingCustomAdapter != null) {
Filter filter = mTextTypingCustomAdapter.getFilter();
if (filter != null) {
filter.filter(s);
return true;
}
}
return false;
}
});
menu.findItem(R.id.action_search).setActionView(searchView);
}
// ----
private final BroadcastReceiver mSelectedPackageNameChangedCustomReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
LogUtil.d(TAG, "Receiver receive");
// ----
if (context == null || intent == null) {
if (context == null) {
LogUtil.w(TAG, "Receiver receive: Context lack");
}
if (intent == null) {
LogUtil.w(TAG, "Receiver receive: Intent lack");
}
return;
}
// ----
String intentAction = null;
try {
intentAction = intent.getAction();
} catch (Exception e) {
LogUtil.e(TAG, e.getMessage());
LogUtil.e(TAG, e.toString());
e.printStackTrace();
}
if (intentAction == null || !intentAction.equals(AppEnvr.ACTION_SELECTED_PACKAGE_NAME_CHANGED)) {
if (intentAction == null) {
LogUtil.w(TAG, "Receiver receive: Intent action lack");
} else if (!intentAction.equals(AppEnvr.ACTION_SELECTED_PACKAGE_NAME_CHANGED)) {
LogUtil.w(TAG, "Receiver receive: Intent action mismatch");
}
return;
}
// ----
LogUtil.d(TAG, "Receiver receive: OK");
// ----
Bundle extras = null;
try {
extras = intent.getExtras();
} catch (Exception e) {
LogUtil.e(TAG, e.getMessage());
LogUtil.e(TAG, e.toString());
e.printStackTrace();
}
if (extras != null) {
if (extras.containsKey(AppEnvr.EXTRA_PACKAGE_NAME_KEY)) {
String packageName = extras.getString(AppEnvr.EXTRA_PACKAGE_NAME_KEY, null);
// ----
Bundle bundle = new Bundle();
bundle.putString(AppEnvr.EXTRA_PACKAGE_NAME_KEY, packageName);
getLoaderManager().restartLoader(1, bundle, mLoaderCallbacks); // Restart with 1
}
}
}
};
// ----
private final class TextTypingLoaderCallbacks implements LoaderManager.LoaderCallbacks<ArrayList<TextTypingObject>> {
private String mPackageName = null;
@NonNull
@Override
public Loader<ArrayList<TextTypingObject>> onCreateLoader(int i, @Nullable Bundle bundle) {
if (mScrollView != null) {
mScrollView.setVisibility(View.GONE);
}
if (mRecyclerView != null) {
mRecyclerView.setVisibility(View.GONE);
}
if (mProgressBar != null) {
mProgressBar.setVisibility(View.VISIBLE);
}
// ----
if (bundle != null) {
mPackageName = bundle.getString(AppEnvr.EXTRA_PACKAGE_NAME_KEY, null);
}
// ----
return new TextTypingLoader(getContextNonNull(), mPackageName);
}
@Override
public void onLoadFinished(@NonNull Loader<ArrayList<TextTypingObject>> loader, @Nullable ArrayList<TextTypingObject> textTypingObjectArrayList) {
if (textTypingObjectArrayList != null && !textTypingObjectArrayList.isEmpty()) {
mTextTypingCustomAdapter = new TextTypingCustomAdapter(getContextNonNull(), textTypingObjectArrayList);
} else {
if (mTextTypingCustomAdapter != null) {
mTextTypingCustomAdapter = null;
}
// ----
if (mPackageName != null && MainActivity.sSelectedPackageName != null) {
mPackageName = null;
MainActivity.sSelectedPackageName = null;
getLoaderManager().restartLoader(1, null, mLoaderCallbacks); // Restart with 1
return;
}
}
// ----
if (mProgressBar != null) {
mProgressBar.setVisibility(View.GONE);
}
if (mTextTypingCustomAdapter != null) {
if (mRecyclerView != null) {
int scrollToPosition = -1;
// ----
if (mItemCount != -1 && mFirstVisibleItemPosition != -1) {
int newItemCount = mTextTypingCustomAdapter.getItemCount();
// ----
if (newItemCount == mItemCount) { // No added/removed events
scrollToPosition = mFirstVisibleItemPosition;
} else if (newItemCount > mItemCount) { // Added events found
if (mFirstVisibleItemPosition != 0) {
int addedEventsCount = newItemCount - mItemCount;
scrollToPosition = mFirstVisibleItemPosition + addedEventsCount;
// ----
if (addedEventsCount >= 1 && mFirstVisibleItemPosition >= 1) {
Snackbar snackbar = Snackbar.make(mView, getContextNonNull().getString(R.string.new_events_found, addedEventsCount) + " (item)", Snackbar.LENGTH_SHORT);
snackbar.setAction(getContextNonNull().getString(R.string.scroll), v -> mRecyclerView.smoothScrollToPosition(0));
snackbar.show();
}
}
} else /*if (newItemCount < mItemCount)*/ { // Removed events found
scrollToPosition = mFirstVisibleItemPosition;
}
// ----
mFirstVisibleItemPosition = -1;
mItemCount = -1;
}
// ----
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(mRecyclerView.getContext());
linearLayoutManager.setOrientation(RecyclerView.VERTICAL);
if (scrollToPosition != -1) {
linearLayoutManager.scrollToPosition(scrollToPosition);
}
mRecyclerView.setLayoutManager(linearLayoutManager);
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
mRecyclerView.setAdapter(mTextTypingCustomAdapter);
// ----
mRecyclerView.setVisibility(View.VISIBLE);
// ----
}
} else {
if (mScrollView != null) {
mScrollView.setVisibility(View.VISIBLE);
}
}
// ----
if (mPackageName != null) {
mPackageName = null;
}
}
@Override
public void onLoaderReset(@NonNull Loader loader) {
}
}
}
任何帮助表示赞赏,谢谢!
解决方案
您可以维护所有选定项目的列表。当用户长按项目保存列表中的项目位置并且当用户单击其他项目时,然后将这些项目位置也添加到列表中。您可以在操作栏中向用户显示删除选项,当用户单击该删除选项时,删除列表中存在的所有位置项。
推荐阅读
- java - orElseThrow 中的 lambda 表达式替代了什么?
- mysql - 使用 continue id(not null) 将现有行克隆到同一个表中
- javascript - 如何在 React 中的功能组件之间传递数据?
- php - WP - 尝试使用 `wp_dropdown_users( )` 作为自定义用户配置文件字段
- ios - 为什么 CALayer 的“transform.scale”的值与其变换比例不匹配?
- stm32 - STM32 DeInit SPI 然后 Init SPI 再次不起作用
- python - 使用 Google Co-lab 连接到远程 MySql 实例
- r - 从 SSRS 运行 R 脚本
- node.js - 未找到创建 React Native App 命令
- python - 将 Keypress 从程序发送到 Google Slides 幻灯片