Hello there, I am trying to implement multiSelect on RecycleView on ToolbarLayout, just like in this picture
But I am failing
My selecting methods look like this
public void setSelecting(boolean enabled) {
TabLayout subTabs = getActivity().findViewById(R.id.sub_tabs);
TabLayout mainTabs = getActivity().findViewById(R.id.main_samsung_tabs);
ViewPager2 viewPager2 = getActivity().findViewById(R.id.viewPager2);
if (enabled) {
mSelecting = true;
adapter.notifyItemRangeChanged(0, adapter.getItemCount() - 1);
toolbarLayout.setSelectModeBottomMenu(R.menu.select_mode_menu, item -> {
item.setBadge(item.getBadge() + 1);
Toast.makeText(this, item.getTitle(), Toast.LENGTH_SHORT).show();
return true;
});
toolbarLayout.showSelectMode();
toolbarLayout.setSelectModeAllCheckedChangeListener((buttonView, isChecked) -> {
if (checkAllListening) {
for (int i = 0; i < adapter.getItemCount() - 1; i++) {
selected.put(i, isChecked);
adapter.notifyItemChanged(i);
}
}
int count = 0;
for (Boolean b : selected.values()) if (b) count++;
toolbarLayout.setSelectModeCount(count);
});
toolbarLayout.showSelectModeBottomBar(false);
subTabs.setEnabled(false);
mainTabs.setEnabled(false);
viewPager2.setUserInputEnabled(false);
onBackPressedCallback.setEnabled(true);
} else {
mSelecting = false;
mHandler.removeCallbacks(mShowBottomBarRunnable);
for (int i = 0; i < adapter.getItemCount() - 1; i++) selected.put(i, false);
adapter.notifyItemRangeChanged(0, adapter.getItemCount() - 1);
toolbarLayout.setSelectModeCount(0);
toolbarLayout.dismissSelectMode();
subTabs.setEnabled(true);
mainTabs.setEnabled(true);
viewPager2.setUserInputEnabled(true);
onBackPressedCallback.setEnabled(false);
}
}
public void toggleItemSelected(int position) {
selected.put(position, !selected.get(position));
adapter.notifyItemChanged(position);
checkAllListening = false;
int count = 0;
for (Boolean b : selected.values()) if (b) count++;
toolbarLayout.setSelectModeAllChecked(count == adapter.getItemCount() - 1);
toolbarLayout.setSelectModeCount(count);
checkAllListening = true;
}
I can secsesfully detect short and long clicks with my adapter like so
package si.wolf.sonoffc.adapters;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.TextView;
//import androidx.recyclerview.widget.RecyclerView; //Google
import de.dlyt.yanndroid.oneui.view.RecyclerView; //Samsung
import java.util.List;
import de.dlyt.yanndroid.oneui.view.Switch;
import si.wolf.sonoffc.R;
import si.wolf.sonoffc.models.Device;
// Create the basic adapter extending from RecyclerView.Adapter
// Note that we specify the custom ViewHolder which gives us access to our views
public class DevicesAdapter extends RecyclerView.Adapter<DevicesAdapter.ViewHolder> {
// Events
private ClickListener mclickListener;
private ItemCheckChangedListener mCheckChangedListener;
// ... view holder defined above...
// Store a member variable for the contacts
private List<Device> mDevices;
// Pass in the contact array into the constructor
public DevicesAdapter(List<Device> contacts) {
mDevices = contacts;
}
// Provide a direct reference to each of the views within a data item
// Used to cache the views within the item layout for fast access
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener, CompoundButton.OnCheckedChangeListener{
// Your holder should contain a member variable
// for any view that will be set as you render a row
public TextView nameTextView;
public TextView descriptionTextView;
public Switch enabledSwich;
// We also create a constructor that accepts the entire item row
// and does the view lookups to find each subview
public ViewHolder(View itemView) {
// Stores the itemView in a public final member variable that can be used
// to access the context from any ViewHolder instance.
super(itemView);
nameTextView = (TextView) itemView.findViewById(R.id.device_name);
descriptionTextView = (TextView) itemView.findViewById(R.id.device_ip);
enabledSwich = (Switch) itemView.findViewById(R.id.enabled_swich);
//Events
itemView.setOnLongClickListener(this); // long click should be set up before standard click
itemView.setOnClickListener(this);
}
//Click listener
@Override
public void onClick(View v) {
mclickListener.onItemClick(v, getAdapterPosition());
}
@Override
public boolean onLongClick(View v) {
mclickListener.onItemLongClick(v, getAdapterPosition());
// return false; // fire normal click also
return true;
}
//Check changed listener
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (mCheckChangedListener != null) mCheckChangedListener.onItemCheckedChanged(buttonView, getAdapterPosition());
}
}
// ... constructor and member variables
// Usually involves inflating a layout from XML and returning the holder
@Override
public DevicesAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
// Inflate the custom layout
View contactView = inflater.inflate(R.layout.item_contact, parent, false);
// Return a new holder instance
ViewHolder viewHolder = new ViewHolder(contactView);
return viewHolder;
}
// Involves populating data into the item through holder
@Override
public void onBindViewHolder(DevicesAdapter.ViewHolder holder, int position) {
// Get the data model based on position
Device device = mDevices.get(position);
// Set item views based on your views and data model
TextView textView_name = holder.nameTextView;
textView_name.setText(device.getName());
TextView textView_description = holder.descriptionTextView;
textView_description.setText(device.getIPAddress());
Switch enabled_switch = holder.enabledSwich;
enabled_switch.setChecked(device.isOnline());
//To implement this outside view here: https://stackoverflow.com/a/49969478/17826480
holder.enabledSwich.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
Log.d("demo", "onChecked: position: " + position + " | name: " + device.getName());
}
});
}
// Returns the total count of items in the list
@Override
public int getItemCount() {
return mDevices.size();
}
//Events
// convenience method for getting data at click position
public String getItem(int id) {
return mDevices.get(id).getName();
}
//Click events
// allows clicks events to be caught
// parent activity will implement this method to respond to click events
public void setOnItemClickListener(ClickListener listener) {
mclickListener = listener;
}
public interface ClickListener {
void onItemClick(View v, int position);
void onItemLongClick(View v, int position);
}
// parent activity will implement this method to respond to click events
public interface ItemCheckChangedListener {
void onItemCheckedChanged(View view, int position);
}
//Listens for button toggle
public void setToggleListener(CompoundButton.OnCheckedChangeListener listener)
{
}
}
then in MainActivity onCreate, you bind to them
//Handle click events
adapter.setOnItemClickListener(new DevicesAdapter.ClickListener() {
String TAG = "clicky";
@Override
public void onItemClick(View v, int position) {
Log.d(TAG, "Click: " + adapter.getItem(position));
//Toast.makeText(this, "You clicked " + adapter.getItem(position) + " on row number " + position, Toast.LENGTH_SHORT).show();
}
@Override
public void onItemLongClick(View v, int position) {
Log.d(TAG, "Long Click");
//Toast.makeText(this, "You long clicked " + adapter.getItem(position) + " on row number " + position, Toast.LENGTH_SHORT).show();
if (!mSelecting) setSelecting(true);
toggleItemSelected(position);
rvDevices.seslStartLongPressMultiSelection(); //RecycleView
}
});
My view looks like this
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<de.dlyt.yanndroid.oneui.layout.ToolbarLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/toolbar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:title="@string/app_name"
app:subtitle="@string/app_description"
app:expandable="true"
app:expanded="true"
tools:context=".MainActivity">
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/item_background_color">
<!-- Google --><!--
<androidx.recyclerview.widget.RecyclerView
-->
<!-- Samsung -->
<de.dlyt.yanndroid.oneui.view.RecyclerView
android:id="@+id/rvDevices"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</de.dlyt.yanndroid.oneui.layout.ToolbarLayout>
my recycleView row looks like this (probably doesn't matter for multiselect but just in case)
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="5dp"
android:background="?android:attr/selectableItemBackground">
<TextView
android:id="@+id/device_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:text="Relay"
android:textSize="16dp"
android:textStyle="bold"
android:layout_marginStart="@dimen/sesl_action_bar_content_inset"
app:layout_constraintEnd_toStartOf="@+id/enabled_swich"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/device_ip"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginEnd="8dp"
android:text="192.168.88.19"
android:layout_marginStart="@dimen/sesl_action_bar_content_inset"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/enabled_swich"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/device_name"
app:layout_constraintVertical_bias="0.0" />
<de.dlyt.yanndroid.oneui.view.Switch
android:id="@+id/enabled_swich"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="2dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/device_ip"
app:layout_constraintTop_toTopOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
and my bottomBar which I would like to show when multiselecting (select_mode_menu) looks like this
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/move"
android:icon="@drawable/ic_oui_move"
android:title="Move"
app:showAsAction="always" />
<item
android:id="@+id/delete"
android:icon="@drawable/ic_ouid_delete"
android:title="Delete"
app:showAsAction="always" />
<item
android:id="@+id/add"
android:icon="@drawable/ic_oui_list_add"
android:title="Add"
app:showAsAction="always" />
<item
android:id="@+id/edit"
android:icon="@drawable/ic_oui3_edit"
android:title="Edit"
app:showAsAction="always" />
<item
android:id="@+id/item1"
android:title="Menu Item 1"
app:showAsAction="never" />
<item
android:id="@+id/item2"
android:title="Menu Item 2"
app:showAsAction="never" />
<item
android:id="@+id/item3"
android:title="Menu Item 3"
app:showAsAction="never" />
</menu>
Now I have a bit of trouble, since your I have no idea what theese in setSelecting do (yea, I am trying to adapt from here: https://github.com/OneUIProject/OneUI-Design-Library/blob/062c469b35ce127eeb84c0130725ead7032fc516/app/src/main/java/de/dlyt/yanndroid/oneuiexample/tabs/IconsTab.java#L494
TabLayout subTabs = getActivity().findViewById(R.id.sub_tabs);
TabLayout mainTabs = getActivity().findViewById(R.id.main_samsung_tabs);
ViewPager2 viewPager2 = getActivity().findViewById(R.id.viewPager2);
as well as what is showSelectModeBottomBar(false); suppose to do (toolbarLayout, nor Drawer layout seem to have it)
and I don't realy know how you then handle back button press
and yea, I am still using the old oneUI library, because it has better documentation and it is the only lib that supports both OneUI3 (which I prefer) and OneUI4 theme
and I still have no idea, why there are 2 libraries
https://github.com/OneUIProject/sesl
https://github.com/OneUIProject/oneui-design
that both seam to do the same thing (which is better :smile: ?)
Hope you can help me and Thanks for Anwsering and Best Regards