Scrollable widgets with easily customizable transform animations.
Features
The package contains 3 widgets:
TransformableListViewthat extendsListViewTransformableSliverListthat extendsSliverListTransformableSliverthat extendsSliverToBoxAdapter
Each of then has getTransformMatrix callback. In the callback you need to return Matrix4 that represetns transormation of the child at the current moment. If you don't need any transformations you can simply return Matrix4.identity().
In getTransformMatrix callback you receive TransformableListItem with the data about list item:
Offset offsetis main axis offset of the child. By default (with vertical, non reversed scroll view)offset.dxis always 0 whileoffset.dyis the distance between top edge of the child and top edge of the viewport.Size sizeis the child size received from itsRenderBox.SliverConstraints constraintsdescribes the current scroll state of the viewport from the point of view of the sliver receiving the constraints.int? indexis the index of the child. Will be null when usingTransformableSliver.TransformableListItemPosition positionis child position on the main axis viewport. Can be.topEdge,.middleor.bottomEdge.double visibleExtentis currently visible portion of item. For example, if item is hidden it will be0while it's completely displayed will equal tosize.heightorsize.widthdepending on axis.
Usage
First you need to add TransformableListView where you need transformations
TransformableListView.builder(
getTransformMatrix: getTransformMatrix,
itemBuilder: (context, index) {
return Container(
height: 100,
margin: const EdgeInsets.symmetric(
horizontal: 16,
vertical: 4,
),
decoration: BoxDecoration(
color: index.isEven ? Colors.grey : Colors.blueAccent,
borderRadius: BorderRadius.circular(20),
),
alignment: Alignment.center,
child: Text(index.toString()),
);
},
itemCount: 30,
),
Second you need to implement getTransformMatrix callback
Matrix4 getTransformMatrix(TransformableListItem item) {
/// final scale of child when the animation is completed
const endScaleBound = 0.3;
/// 0 when animation completed and [scale] == [endScaleBound]
/// 1 when animation starts and [scale] == 1
final animationProgress = item.visibleExtent / item.size.height;
/// result matrix
final paintTransform = Matrix4.identity();
/// animate only if item is on edge
if (item.position != TransformableListItemPosition.middle) {
final scale = endScaleBound + ((1 - endScaleBound) * animationProgress);
paintTransform
..translate(item.size.width / 2)
..scale(scale)
..translate(-item.size.width / 2);
}
return paintTransform;
}
You can implement your own callback or check more at /example folder.
Additional information
You can read more about matrix transfomations in Flutter here. Any feedback and PRs are welcome.
Developed by TBR Group.