VOOZH about

URL: https://www.nuget.org/packages/MvxExpandableRecyclerView.Core/

⇱ NuGet Gallery | MvxExpandableRecyclerView.Core 3.1.1




MvxExpandableRecyclerView.Core 3.1.1

Suggested Alternatives

MvxSectionedRecyclerView

dotnet add package MvxExpandableRecyclerView.Core --version 3.1.1
 
 
NuGet\Install-Package MvxExpandableRecyclerView.Core -Version 3.1.1
 
 
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="MvxExpandableRecyclerView.Core" Version="3.1.1" />
 
 
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="MvxExpandableRecyclerView.Core" Version="3.1.1" />
 
Directory.Packages.props
<PackageReference Include="MvxExpandableRecyclerView.Core" />
 
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add MvxExpandableRecyclerView.Core --version 3.1.1
 
 
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: MvxExpandableRecyclerView.Core, 3.1.1"
 
 
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package MvxExpandableRecyclerView.Core@3.1.1
 
 
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=MvxExpandableRecyclerView.Core&version=3.1.1
 
Install as a Cake Addin
#tool nuget:?package=MvxExpandableRecyclerView.Core&version=3.1.1
 
Install as a Cake Tool
The NuGet Team does not provide support for this client. Please contact its maintainers for support.

Android MvxExpandableRecyclerView

This is an unofficial package that contains an expandable AndroidX RecyclerView supported for MvvmCross. This view allows us to bind a collection of items (objects, ViewModels, etc) to the ItemsSource property. It works similarly to a RecyclerView. However, this comes with out-of-the-box functionality such as grouping items with collapsible/expandable headers. Additional functionality can be implemented such as dragging items up and down and swiping them by binding a boolean property to EnableDrag and EnableSwipe respectively.

All original functionality of MvxRecyclerView is also available and it is highly encouraged that you read the documentation before proceeding.

Getting Started

You need to ensure that you have the MvxExpandableRecyclerView.Core and MvxExpandableRecyclerView.DroidX NuGet packages installed in your .Core and .Droid projects respectively.

The general steps to implement this control:

  1. We want to create an app where people are grouped by their appointment dates. Firstly, in our .Core project, we create an entity class to hold our data: Person.cs.
public class Person
{
 public Person(string firstName, string lastName, DateTime? appointment)
 {
 FirstName = firstName;
 LastName = lastName;
 Appointment = appointment;
 }

 public string FirstName { get; set; }

 public string LastName { get; set; }

 public DateTime? Appointment { get; set; }
}
  1. We then create a class that inherits TaskItem<Person, DateTime?> named PersonItem.cs. This will allow the control to know how to group our Person.cs objects.
public class PersonItem : TaskItem<Person, DateTime?>
{
 public PersonItem(Person model) 
 : base(model)
 { }

 public override DateTime? Header { get => Model.Appointment; set => Model.Appointment = value; }
}
  1. In our ViewModel (where we will add the MvxExpandableRecyclerView to the corresponding view), we will initialise a list that will hold PersonItems for binding.
public MvxObservableCollection<ITaskItem> People { get; private set; }
  1. For the rest of the steps, everything will be done in our .Droid project. We will create a layout to display our PersonItem.cs objects inside the MvxExpandableRecyclerView. We'll name the layout PersonItem.xml.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
 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="wrap_content"
 android:orientation="horizontal"
 android:gravity="center">
 <TextView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 app:MvxBind="Text Format('{0} {1} - {2:d}', Model.FirstName, Model.LastName, Model.Appointment);"/>
 <TextView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_marginHorizontal="4sp"
 android:textColor="?android:attr/colorAccent"
 app:MvxBind="Text Sequence;"/>
</LinearLayout>

Notice that "Model" is prepended to our binded properties. This allows us to access properties in the underlying entity class. In this example, "Model" refers to the Person.cs entity class and we are binding Person.FirstName, Person.LastName and Person.Appointment to the TextView. We also have another TextView that binds to TaskItem<TModel, THeader>.Sequence, if you want to show the ordering of each item.

  1. We then create another layout for our headers, if we want to display something other than a SimpleListItem1[^1]. In this example: TaskHeader.xml displays an ImageView showing an arrow up or down depending on the TaskHeader.IsCollapsed property and uses a TextView to bind to TaskHeader.Name. There's also another TextView that display the number of items under the said header using TaskHeader.Count.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
 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="wrap_content"
 android:orientation="horizontal"
 android:padding="8sp"
 android:gravity="center">
 <FrameLayout
 android:layout_width="wrap_content"
 android:layout_height="wrap_content">
 <ImageView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:src="@android:drawable/arrow_down_float"
 app:MvxBind="Visible IsCollapsed;"/>
 <ImageView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:src="@android:drawable/arrow_up_float"
 app:MvxBind="Visible !IsCollapsed;"/>
 </FrameLayout>
 <TextView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 style="@style/Base.TextAppearance.AppCompat.Headline"
 app:MvxBind="Text Name;"/>
 <TextView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_marginHorizontal="4sp"
 android:textColor="@android:color/holo_red_dark"
 app:MvxBind="Text Count;"/>
</LinearLayout>
  1. We then create a custom Item Template Selector to handle displaying layouts for the corresponding item(s). In this example, if an item doesn't have a corresponding layout, it will default to PersonItem.xml.
public class AppointmentTemplateSelector : MvxTemplateSelector<ITaskItem>
{
 public override int GetItemLayoutId(int fromViewType)
 {
 return fromViewType switch
 {
 1 => Resource.Layout.TaskHeader,
 _ => Resource.Layout.PersonItem,
 };
 }

 protected override int SelectItemViewType(ITaskItem forItemObject)
 {
 if (forItemObject is ITaskHeader)
 return 1;
 else
 return -1;
 }
}
  1. Finally, adding MvxExpandableRecyclerView to one of your View.xml is very simple. In this example, we have AppointmentView.xml and add:
<MvvmCross.ExpandableRecyclerView.DroidX.MvxExpandableRecyclerView
 android:id="@+id/appointment_recyclerview"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 local:MvxTemplateSelector="AppointmentPlanner.Droid.Components.AppointmentTemplateSelector, AppointmentPlanner.Droid"
 local:MvxBind="ItemsSource People;"/>

Important: MvxExpandableRecyclerView will require you to bind a MvxObservableCollection<ITaskItem> to ItemsSource and will need to have your custom MvxTemplateSelector for it to display your headers and items correctly.

For more information, MvvmCross provides documentation for MvxTemplateSelector. If you want to display complex objects for both/either headers and/or items, it is strongly recommended to use MvxTemplateSelector to show different types of views.

Dragging Items

To enable the dragging feature, we need to modify our xml and bind EnableDrag to true.

<MvvmCross.ExpandableRecyclerView.DroidX.MvxExpandableRecyclerView
 android:id="@+id/appointment_recyclerview"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 local:MvxTemplateSelector="AppointmentPlanner.Droid.Components.AppointmentTemplateSelector, AppointmentPlanner.Droid"
 local:MvxBind="ItemsSource People;
		 EnableDrag true;"/>

Swiping Items

To enable the swiping feature, we need to modify our xml and bind EnableSwipe to true.

<MvvmCross.ExpandableRecyclerView.DroidX.MvxExpandableRecyclerView
 android:id="@+id/appointment_recyclerview"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 local:MvxTemplateSelector="AppointmentPlanner.Droid.Components.AppointmentTemplateSelector, AppointmentPlanner.Droid"
 local:MvxBind="ItemsSource People;
		 EnableSwipe true;
		 ItemSwipeRight UnplanPersonCommand;
		 ItemSwipeLeft RemovePersonCommand;"/>

Swipe actions are bindable and can have 2 different actions depending on the direction of the swipe. ItemSwipeLeft and ItemSwipeRight are bindable and are done in the same way as MvxRecyclerView's ItemClickCommand and ItemLongClickCommand.

We can also show different backgrounds for an item depending on the swipe direction. In this example, we create 2 new layout files UnplanTaskItemBackground.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto"
 android:tag="swipe_right_background"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="horizontal"
 android:gravity="start"
 android:background="@android:color/holo_green_light">
 <ImageView
 android:layout_width="30dp"
 android:layout_height="30dp"
 android:layout_centerVertical="true"
 android:layout_marginRight="10sp"
 android:background="@drawable/abc_ic_ab_back_material"/>
</LinearLayout>

And DeleteTaskItemBackground.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto"
 android:tag="swipe_left_background"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="horizontal"
 android:gravity="end"
 android:background="@android:color/holo_red_light">
 <ImageView
 android:layout_width="30dp"
 android:layout_height="30dp"
 android:layout_centerVertical="true"
 android:layout_marginLeft="10sp"
 android:background="@drawable/abc_ic_clear_material"/>
</LinearLayout>

Important: The important thing to notice in these files is that each layout has an android:tag attribute. This is important for the control because it identifies which layout to show when swiping left or right, or not swiping at all. The android:tags needed for the control are android:tag="swipe_right_background" (show layout when swiping right), android:tag="swipe_left_background" (show layout when swiping left) and android:tag="swipe_foreground" (show layout for item when user is not swiping).

We then modify our PersonItem.xml to include these layouts and make sure to wrap everything in a FrameLayout, making sure the background layouts are added first. We also need to add android:tag="swipe_foreground" to the nested FrameLayout tag holding all our PersonItem bindings for it show the layout when the user isn't swiping.

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
 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="wrap_content">
 <include
 layout="@layout/unplantaskitembackground"/>
 <include
 layout="@layout/deletetaskitembackground"/>
 <FrameLayout
 android:tag="swipe_foreground"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:background="@android:color/white">
 <LinearLayout
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="horizontal"
 android:gravity="center"
 android:background="@drawable/appointment_recyclerview_item_background"
 app:MvxBind="Selected IsSelected">
 <TextView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 app:MvxBind="Text Format('{0} {1} - {2:d}', Model.FirstName, Model.LastName, Model.Appointment);"/>
 <TextView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_marginHorizontal="4sp"
 android:textColor="?android:attr/colorAccent"
 app:MvxBind="Text Sequence;"/>
 </LinearLayout>
 </FrameLayout>
</FrameLayout>

Hide Sticky Header

A sticky header is always shown by default, however we can hide the sticky header by modifying our xml and bind ShowStickyHeader to false.

<MvvmCross.ExpandableRecyclerView.DroidX.MvxExpandableRecyclerView
 android:id="@+id/appointment_recyclerview"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 local:MvxTemplateSelector="AppointmentPlanner.Droid.Components.AppointmentTemplateSelector, AppointmentPlanner.Droid"
 local:MvxBind="ItemsSource People;
		 ShowStickyHeader false;"/>

Android MvxExpandableRecyclerViewSample

The MvxExpandableRecyclerViewSample demonstrates how to implement the MvxExpandableRecyclerView package into a simple project.

[^1]: If you don’t provide an item template selector MvxExpandableRecyclerView will fall back to using a SimpleListItem1, which is a built in Android Resource. It will also just call ToString() on your item that you are supplying. A custom view should be used for headers, if items aren't grouped using a string.

Product Versions Compatible and additional computed target framework versions.
.NET net5.0 net5.0 was computed.  net5.0-windows net5.0-windows was computed.  net6.0 net6.0 was computed.  net6.0-android net6.0-android was computed.  net6.0-ios net6.0-ios was computed.  net6.0-maccatalyst net6.0-maccatalyst was computed.  net6.0-macos net6.0-macos was computed.  net6.0-tvos net6.0-tvos was computed.  net6.0-windows net6.0-windows was computed.  net7.0 net7.0 was computed.  net7.0-android net7.0-android was computed.  net7.0-ios net7.0-ios was computed.  net7.0-maccatalyst net7.0-maccatalyst was computed.  net7.0-macos net7.0-macos was computed.  net7.0-tvos net7.0-tvos was computed.  net7.0-windows net7.0-windows was computed.  net8.0 net8.0 was computed.  net8.0-android net8.0-android was computed.  net8.0-browser net8.0-browser was computed.  net8.0-ios net8.0-ios was computed.  net8.0-maccatalyst net8.0-maccatalyst was computed.  net8.0-macos net8.0-macos was computed.  net8.0-tvos net8.0-tvos was computed.  net8.0-windows net8.0-windows was computed.  net9.0 net9.0 was computed.  net9.0-android net9.0-android was computed.  net9.0-browser net9.0-browser was computed.  net9.0-ios net9.0-ios was computed.  net9.0-maccatalyst net9.0-maccatalyst was computed.  net9.0-macos net9.0-macos was computed.  net9.0-tvos net9.0-tvos was computed.  net9.0-windows net9.0-windows was computed.  net10.0 net10.0 was computed.  net10.0-android net10.0-android was computed.  net10.0-browser net10.0-browser was computed.  net10.0-ios net10.0-ios was computed.  net10.0-maccatalyst net10.0-maccatalyst was computed.  net10.0-macos net10.0-macos was computed.  net10.0-tvos net10.0-tvos was computed.  net10.0-windows net10.0-windows was computed. 
.NET Core netcoreapp2.0 netcoreapp2.0 was computed.  netcoreapp2.1 netcoreapp2.1 was computed.  netcoreapp2.2 netcoreapp2.2 was computed.  netcoreapp3.0 netcoreapp3.0 was computed.  netcoreapp3.1 netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 netstandard2.0 is compatible.  netstandard2.1 netstandard2.1 was computed. 
.NET Framework net461 net461 was computed.  net462 net462 was computed.  net463 net463 was computed.  net47 net47 was computed.  net471 net471 was computed.  net472 net472 was computed.  net48 net48 was computed.  net481 net481 was computed. 
MonoAndroid monoandroid monoandroid was computed. 
MonoMac monomac monomac was computed. 
MonoTouch monotouch monotouch was computed. 
Tizen tizen40 tizen40 was computed.  tizen60 tizen60 was computed. 
Xamarin.iOS xamarinios xamarinios was computed. 
Xamarin.Mac xamarinmac xamarinmac was computed. 
Xamarin.TVOS xamarintvos xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.0

    • No dependencies.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on MvxExpandableRecyclerView.Core:

Package Downloads
MvxExpandableRecyclerView.DroidX

MvvmCross is the .NET MVVM framework for cross-platform solutions, including Xamarin iOS, Xamarin Android, Xamarin Forms, Windows and Mac. This is an unofficial package that contains an expandable AndroidX RecyclerView supported for MvvmCross.

GitHub repositories

This package is not used by any popular GitHub repositories.