-
Notifications
You must be signed in to change notification settings - Fork 552
Migrations
- From 5.0.0-RC4
▶️ To 5.X.Y - From 5.0.0-RC3
▶️ To 5.0.0-RC4 - From 5.0.0-RC2
▶️ To 5.0.0-RC3 - From 5.0.0-RC1
▶️ To 5.0.0-RC2 - From any 5.0.0-beta
▶️ To 5.0.0-RC1
The callback onItemClick has now a new parameter: View
, that will help to distinguish which view has generated the click event. Most useful for child views in the itemView. Sample usage:
// To invoke in the constructor. "This" is the ViewHolder instance
// which already implements the onClick by default
button.setOnClickListener(this);
Optional implementation for custom callbacks:
@Override
public void onClick(View view) {
if (view.getId() == R.id.buttonId) {
// Button inner-view click: do something.
// For example, call another custom callback.
} else {
// Item view click.
// Automatic callback to Activity/Fragment implementation.
super.onClick(view);
}
}
onItemClick(int position)
has been removed with this release.
@Override
public boolean onItemClick(View view, int position) {
// Is itemView or innerView? view.getId() == ....
return ...
}
Filter can now be of any type, extending the possibility to apply a multi filter simultaneously on more fields.
IFilterable
signature has now a parameter type, so the filter()
method can accept the specified custom type.
New methods substitute the old ones when managing the filter:
Old methods | New methods | |
---|---|---|
setSearchText(String) |
-> |
setFilter(Serializable) |
String getSearchText() |
-> |
MyFilter getFilter(MyFilter.class) |
boolean hasSearchText() |
-> |
boolean hasFilter() |
boolean hasNewSearchText(String) |
-> |
boolean hasNewFilter(Serializable) |
If filter object is of type String
, automatic trim and lowercase is maintained when setting it.
Filter object must be of type Serializable
in order to maintain save/restore instance state on configuration changes. String
it is.
- Old methods have been removed with this release.
- Always specify parameter class type for
FlexibleAdapter<common-item-type>
to allow to recognize also the filter type! Do it in the activity/fragment as well!
It's your choice to implement an inclusive (any match) or exclusive (all match) filter, here an exclusive example is shown:
public class ... extends ... implements IFilterable<MyFilter> {
@Override
public boolean filter(MyFilter constraint) {
boolean result = true;
if (constraint.isElectricCarSet()) {
result = this.electric == constraint.isElectric());
}
if (result && constraint.isPriceSet()) {
result = this.price <= constraint.getPrice());
}
return result;
}
@Override **WRONG**
public void bindViewHolder(FlexibleAdapter adapter, // Wrong! (missing item type)
MyViewHolder holder,
int position,
List payloads) { // Wrong! (missing list type)
// Incompatible types: Required 'com.x.y.z.MyFilter' Found 'java.io.Serializable'
MyFilter filter = adapter.getFilter(MyFilter.class);
}
@Override **CORRECT**
public void bindViewHolder(FlexibleAdapter<IFlexible> adapter, // Must be IFlexible
MyViewHolder holder,
int position,
List<Object> payloads) { // Must be Object
// getFilter() can now recognize the type and can return MyFilter type
MyFilter filter = adapter.getFilter(MyFilter.class);
}
}
Helper class to show an empty view when Recycler View has no items. To better handle FastScroller, initialize this helper class after setting FastScroller to the Adapter. This helper supports:
- Empty View in normal state.
- Empty View for no filter result.
- FastScroller handling if previously set into the Adapter.
This Helper class is very simple: User provides pre-configured empty views for data and filter results, the helper will show and hide the views in accordance with the Adapter callbacks. Usage:
Class location 👓
eu.davidea.flexibleadapter.helpers
|_ EmptyViewHelper
Include your custom layout after RecyclerView widget:
<android.support.v7.widget.RecyclerView
.../>
<!-- EmptyView layout for RV when empty -->
<include layout="@layout/empty_view"/>
<!-- EmptyView layout for RV when filter has empty result -->
<include layout="@layout/filter_view"/>
Examples: empty_view.xml, filter_view.xml
Usage (with fragments)
// Minimum usage
EmptyViewHelper.create(mAdapter, getView().findViewById(R.id.empty_view));
// Extended usage
EmptyViewHelper.create(mAdapter,
getView().findViewById(R.id.empty_view),
getView().findViewById(R.id.filter_view),
// Optional in case of further customization
(EmptyViewHelper.OnEmptyViewListener) getActivity());
I've restored the support for DiffUtil
, because it is still an acceptable solution, even though, the internal calculation seems faster on real devices but it gives worst results on emulator. However, both solutions are again available.
ℹ️ Tip: It's up to the developer, to choose which method to adopt, which flag to enable/disable in any case and sub-case.
Key methods are:
// FlexibleAdapter
boolean isAnimateChangesWithDiffUtil();
setAnimateChangesWithDiffUtil(boolean);
setDiffUtilCallback(FlexibleAdapter.DiffUtilCallback);
// IFlexible item interface
shouldNotifyChange(newItem);
Fixes and others changes can be read in 5.0.0 release page.
Some Common, Helper and Util classes have been moved to a new library: this made the Adapter library thinner and without the direct dependency of Support Design library. The package signature remains the same.
implementation 'eu.davidea:flexible-adapter-ui:x.y.z'
eu.davidea.flexibleadapter
.common
|_ FlexibleItemAnimator
|_ FlexibleItemDecoration
|_ SmoothScrollGridLayoutManager
|_ SmoothScrollLinearLayoutManager
|_ SmoothScrollStaggeredLayoutManager
|_ TopSnappedSmoothScroller
.helpers
|_ ActionModeHelper
|_ AnimatorHelper
|_ UndoHelper
.utils
|_ DrawableUtils
|_ FlexibleUtils
Some Util methods are needed by the Adapter, therefore they are kept in the main library and grouped in the new class LayoutUtils
moved from FlexibleUtils
.
❗️ Revised again UndoHelper
New behavior for Action.UPDATE
: now it doesn't remove items anymore:
- If timeout is over, user is responsible to proceed with a confirmation action (may still be a deletion).
- If undo Snackbar button is pressed, the action is cancelled and user should perform a
notifyChange
on those positions. - No change for
Action.REMOVE
, items are removed automatically.
// Class UndoHelper is now available in package UI, with same signature.
// More on this in the migration wiki page when ready.
implementation 'eu.davidea:flexible-adapter-ui:<version>'
package eu.davidea.flexibleadapter.helpers.UndoHelper;
// Renamed callback interface
from OnUndoListener to OnActionListener
// Use of the constants from annotation interface "Action" instead of class constants
constant ACTION_REMOVE to Action.REMOVE
constant ACTION_UPDATE to Action.UPDATE
// New parameter for method onActionCancelled provides the positions affected
// by the action (when the action button in Snackbar is pressed)
void onActionCanceled(@Action int action);
// to
void onActionCanceled(@Action int action, List<Integer> positions);
Also, fixed the consecutive item swiping when the option is enabled: every swiped item is correctly removed from the RecyclerView.
New methods callbacks in IFlexible
interface to support use cases of items with Audio/Video/GiFs.
AbstractFlexibleItem
has these new methods empty to speed up the development and the necessary methods abstract, so I suggest to extend from this class.
Forward scrolling and Reverse scrolling are now independent. Call these methods to enable/disable them:
// deprecated
setAnimationOnScrolling(boolean)
boolean isAnimationOnScrollingEnabled
// new
setAnimationOnForwardScrolling(boolean)
setAnimationOnReverseScrolling(boolean)
boolean isAnimationOnScrollingEnabled
boolean isAnimationOnReverseScrollingEnabled
The method removeListener(@NonNull Object listener)
can now accept the instance of the listener or the Class
object (as before) if the instance is not available.
With RC3 release, I publish also an independent library (in beta version) to support the new Android Arch library. Please, I would like you will start to use it and eventually give suggestions for improvements. The LiveData extension should simplify the transformation of live items from any Repository to any Adapter.
ℹ️ Note: Wiki page for LiveData Extension is now ready 😃
FlexibleAdapter auto-mapping is now based on the return value of getItemViewType
in IFlexible
. This gives flexibility to reuse same Layout for multiple item types as explained in #430. For who inherits from AbstractFlexibleItem
, this change is transparent.
ℹ️ Note: You should stick to implement only
getLayoutRes()
to identify an unique viewType, sincegetItemViewType
is optional for advanced usage and exceptional cases.
Different TAGs for multiple Adapter instances can now be set, usage example:
FlexibleAdapter.useTag("OverallAdapter");
mAdapter = new OverallAdapter(getActivity());
❗️ Revised UndoHelper
- Deprecated
OnActionListener
in UndoHelper alsoonPreAction()
andonPostAction()
.
New comprehensive methods name: Renamed the 2 callbacks methods inOnUndoListener
and renamed also the methodremove
series:
.withAction(int action, OnActionListener listener) >>> .withAction(@Action int action)
.remove(...) >>> .start(...) // Still returns Snackbar object
OnActionListener >>> !!deprecated!! // Please read related javaDoc
OnUndoListener.onDeleteConfirmed(int action) >>> onActionConfirmed(@Action int action, int event)
OnUndoListener.onUndoConfirmed(int action) >>> onActionCanceled(@Action int action)
- Consecutive Undo requests option & improved the general stability. New method to commit one by one the swiped items and undo only the latest action. Also, it will clear the internal memory references at the end of the dismissal event!
.withConsecutive(true/false) // Default value is false (accumulate items to undo)
- Added the type of event with the following cases:
onActionConfirmed(@Action int action, int event);
- DISMISS_EVENT_SWIPE = 0; // Snackbar was dismissed via a swipe.
- DISMISS_EVENT_TIMEOUT = 2; // Snackbar was dismissed via a timeout.
- DISMISS_EVENT_MANUAL = 3; // Snackbar was dismissed via a call to dismiss().
- DISMISS_EVENT_CONSECUTIVE = 4; // Snackbar was dismissed from a new Snackbar being shown.
- While the
onActionCanceled
is always called because of event type "action" only (user pressed on snackbar action button) and therefore not provided.
onActionCanceled(@Action int action);
- DISMISS_EVENT_ACTION = 1; // Snackbar was dismissed via an action click.
-
setStickyHeaderElevation
now accepts only dpi value! -
OnStickyHeaderChangeListener
receives also the last sticky header position. I couldn't deprecate the method.
As announced long time ago, deprecated functions and classes are now permanently removed from library. New deprecated methods in this release will be removed in final version.
- Dynamically add and remove listeners.
- New methods in IFlexible:
getItemViewType()
&getBubbleText()
; - New methods in FlexibleAdapter:
getSubPositionOf()
&getSameTypePositionOf()
. - New utility methods
highlightWords()
&highlightText()
with multi-span in same text. - Upgrade to Support Library v26.
- Remaining details of changes and fixes can be read in RC3 pre-release page.
New interesting features for FastScroller
When set, by default it auto-hides. It is now independent from FlexibleAdapter (use of a delegate). More details in issue #34.
Endless scrolling in both directions
If activated with setTopEndless()
, items can only be inserted at the top of the list, top endless is complementary to the bottom endless.
Support of Thirds Layout Managers
You can make compatible any third LayoutManagers with FlexibleAdapter
by implementing it with IFlexibleLayoutManager
and assign it to the RecyclerView
as usual.
New advanced Flexible Item Decoration
- Can add equal space to all sides of items and the offset is customizable based on the view type.
- Recognizes the sections of
FlexibleAdapter
and can add gap offset between them. - Recognizes the orientation of the current Layout.
- Supports the default and also custom dividers.
- etc....
Adapter now makes a copy of the provided list (new ArrayList(userList)
) at startup, updateDataSet and filterItems, before applying features, as consequence you should remove the copy of the list in these 3 situations.
Use the interface Mode
to pick up the selection mode (constants MODE_*
are now deprecated). For instance:
mAdapter.setMode(Mode.MULTI);
However, if you use the ActionModeHelper
, the update is already done.
Unfortunately, you will have to adapt the method createViewHolder()
in ALL of your IFlexible
implementation. Now the inflated view is already provided so it will simplify the user code. The IFlexible
interface now wants you to implement the method as following:
@Override
public MyViewHolder createViewHolder(View view, FlexibleAdapter adapter) {
return new MyViewHolder(view, adapter);
}
Method B is the classic way to implement the Adapter by overriding onCreateViewHolder()
& onBindViewHolder()
. Those methods will be now declared final
, because Method A will be the new standard.
From now on, we will use only Method A: we will delegate the previous operations to the item interfaces. Item interfaces will now mandatory implement the following methods:
getLayoutRes()
createViewHolder()
bindViewHolder()
-
onPostUpdate()
andonPostFilter()
now require to callsuper()
otherwise the emptyView won't get notified! -
updateDataSet()
andfilterItems()
have hidden items (headers & expanded items) inserted before applying the features, so they won't get notified for removing and adding same items, but only for updating. This will improve performance avoiding useless notifications. - You can choose if an item will be rebound or not:
shouldNotifyChange(IFlexible newItem)
has been added toIFlexible
interface, enabled by default. Override to change behaviour.
- Renamed
DividerItemDecoration
toFlexibleItemDecoration
. - Renamed
Utils
toFlexibleUtils
.
Starting or resetting the Filter will immediately commit the deletion and will empty the bin of the deleted items. More precisely the next sequences of use cases are removed from the library.
- Delete items > Start filter > Undo > Items were restored at the right positions and already filtered.
- Start filter > Delete items > Resetting the filter > Undo > Items were restored at their original position.
Expected use cases / behaviors:
- Delete items with Undo > Start filter > Commit is triggered > Filter is applied.
- Start filter > Delete items with Undo > Undo > Items are restored at the filtered positions.
- Start filter > Delete items with Undo > Change filter again > Commit is triggered > New Filter is applied.
From https://developer.android.com/topic/libraries/support-library/setup.html:
The support libraries are now available through Google's Maven repository. You do not need to download the support repository from the SDK Manager.
Make sure that the repositories section includes a maven section with the "https://maven.google.com" endpoint.
allprojects {
repositories {
jcenter()
maven {
url "https://maven.google.com"
}
}
}
Details of changes and fixes can be read in RC2 pre-release page.
A new big feature: Scrollable Headers and Footers.
- 2 new properties
EndlessTargetCount
&EndlessPageSize
to automatic disable the endless feature and to automatic display a message by updating the content of progressItem when the newnoMoreLoad()
method is invoked. - A new callback in the listener:
noMoreLoad(int newItemsSize)
, - The
onLoadMore
callback has now 2 new parameters(int lastPosition, int currentPage)
. The old method has been removed already! - The progressItem is now a scrollable footer.
- OnUpdateListener size: The parameter "size" now represents ONLY the main items count. Scrollable Headers and Footers are not counted if present.
- Many functions have been Refactored and deprecated. The old code will be removed in the final release. You should upgrade your code before that deadline.
For an accurate migration -> read issue #200.
// Deprecated
enableStickyHeader();
disableStickyHeaders();
getStickySectionHeadersHolder();
getStickyHeaderContainer();
setStickyHeaderContainer(ViewGroup stickyContainer);
... and more
// New
setStickyHeaders(boolean sticky);
// A custom layout can still be added
setStickyHeaders(boolean sticky, ViewGroup stickyContainer);
- Reduced XML Configuration for sticky headers: Now we can remove the
<include>
of the mini layout from ours XMLs: Thesticky_header_layout
is generated at runtime, this is particularly useful in ViewPager use case or with multiple instances of the Adapter. However, we still need aFrameLayout
to wrap theRecyclerView
in case of sticky headers: Refresh Circle and FastScroller views need to stay on the top of the sticky header, the wrapping resolves that issue:
<!-- SwipeRefreshLayout is optional.
And if you need to drag items, this layout must be disabled! -->
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipeRefreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- This FrameLayout is still mandatory ONLY IF sticky header is enabled. This
layout will help to receive the inflated layout at runtime and to display the
Refresh circle AND the FastScroll on the top of sticky_header_layout. -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:listitem="@layout/recycler_adapter_item"/>
<!-- NOT NEEDED ANYMORE!! This layout is generated at runtime when
sticky headers are enabled. So you can safely remove it. -->
<!--<include layout="@layout/sticky_header_layout"/>-->
</FrameLayout>
</android.support.v4.widget.SwipeRefreshLayout>
- Transparent header and Elevation on header. Now, it is super easy to add the tranparency and elevation to the header item, the values are taken from the header item layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#aa7e57c2" <--- transparent background
android:elevation="5dp"> <--- elevation for header item + sticky header
...
</RelativeLayout>
But if not configured in the layout or is Zero, then you have 1 new method to obtain this effect: header item flat + sticky header elevated:
setStickyHeaderElevation(float stickyElevation);
🏅 Bonus from my researches:
- Transparent Sticky Header with elevation at the same time
- Surgery precision on header swapping :-)
- Double background not visible anymore on header swapping, if transparency is set.
- Fade animation on sticky header container, when sticky is enabled or disabled.
No more notifyItemRangeChanged()
in selectAll()
and clearSelection()
methods: This means no more item binding!
Now, bound selectable ViewHolders will have the StateListDrawable
background switching status (activated/normal) when I internally invoke FlexibleViewHolder.toggleSelection()
, so that, all inner views can complete animations with no interruptions.
ℹ️ Note:
- The cached ViewHolders are removed when they are recycled by the RecyclerView.
- The ViewHolders must extend
FlexibleViewHolder
, otherwise, item binding still occurs.
Fixes and others changes can be read in RC1 pre-release page.
- Update Data Set
- Selection modes
- Headers and Sections
- Scrollable Headers and Footers
- Expandable items
- Drag&Drop and Swipe
- EndlessScroll / On Load More
- Search Filter
- FastScroller
- Adapter Animations
- Third party Layout Managers
- Payload
- Smooth Layout Managers
- Flexible Item Decoration
- Utils
- ActionModeHelper
- AnimatorHelper
- EmptyViewHelper
- UndoHelper
* = Under revision!