• Stars
    star
    427
  • Rank 101,680 (Top 3 %)
  • Language
    Dart
  • License
    MIT License
  • Created over 2 years ago
  • Updated about 2 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A widget for observing data related to the child widgets being displayed in a ScrollView. Maintainer: @LinXunFeng

Flutter ScrollView Observer

author pub stars

Language: English | 中文

This is a library of widget that can be used to listen for child widgets those are being displayed in the scroll view.

Support me

ko-fi wechat

Chat: Join WeChat group

Article

Feature

You do not need to change the view you are currently using, just wrap a ViewObserver around the view to achieve the following features.

  • Observing child widgets those are being displayed in ScrollView
  • Support for scrolling to a specific item in ScrollView
  • Quickly implement the chat session page effect
  • Support for keeping IM message position when inserting or updating messages, avoiding jitter.

Support

  • ListView
  • SliverList
  • GridView
  • SliverGrid
  • Mixing usage of SliverPersistentHeader, SliverList and SliverGrid
  • ScrollView built by third-party package.

Installing

Add scrollview_observer to your pubspec.yaml file:

dependencies:
  scrollview_observer: latest_version

Import scrollview_observer in files that it will be used:

import 'package:scrollview_observer/scrollview_observer.dart';

Getting Started

Take ListView as an example

1、Observing child widgets those are being displayed in the scroll view

Parameter description of ListViewObserver:

Parameter Required Description
child yes Create [ListView] as a child of [ListViewObserver]
sliverListContexts no In this callback, we need to return all [BuildContext] of the [ListView] those needs to be observed. This property is only used when [BuildContext] needs to be specified exactly
onObserve no This callback can listen for information about the child widgets those are currently being displayed in the current first [Sliver]
onObserveAll no This callback can listen for information about all the children of slivers that are currently being displayed. This callback is only needed when there are more than one [Sliver]
leadingOffset no The offset of the head of scroll view. Find the first child start at this offset.
dynamicLeadingOffset no This is a callback that provides [leadingOffset], used when the leading offset in the head of the scroll view is dynamic. It has a higher priority than [leadingOffset]
toNextOverPercent no When the percentage of the first child widget is blocked reaches this value, the next child widget will be the first child that is displaying. The default value is 1
autoTriggerObserveTypes no Used to set types those can trigger observe automatically
triggerOnObserveType no Used to set the prerequisite for triggering [onObserve] callback and [onObserveAll] callback

Method 1: General (Recommended)

It is relatively simple to use and has a wide application range. In general, only this method is needed

Build ListViewObserver and pass the ListView instance to the child parameter

ListViewObserver(
  child: _buildListView(),
  onObserve: (resultModel) {
    print('firstChild.index -- ${resultModel.firstChild?.index}');
    print('displaying -- ${resultModel.displayingChildIndexList}');
  },
)

By default, ListView relevant data will only be observed when scrolling.

If needed, you can use ListObserverController triggered an observation manually.

// Create an instance of [ListObserverController]
ListObserverController controller = ListObserverController();
...

// Pass the controller instance to the 'controller' parameter of 'ListViewObserver'
ListViewObserver(
  ...
  controller: controller,
  ...
)
...

// Trigger an observation manually.
controller.dispatchOnceObserve();

Definition of dispatchOnceObserve method:

Take dispatchOnceObserve of ListObserverController as an example.

Future<ListViewOnceObserveNotificationResult> dispatchOnceObserve({
  BuildContext? sliverContext,
  bool isForce = false,
  bool isDependObserveCallback = true,
})

Parameter description of dispatchOnceObserve:

Parameter Required Description
sliverContext no The BuildContext of the scrollView is only used when CustomScrollView has multiple Sliver
isForce no Whether to enforce observation, equivalent to ObserverTriggerOnObserveType.directly
isDependObserveCallback no Whether it depends on judging whether onObserve and other callbacks are implemented. If true is passed, even if the corresponding callback is not implemented, the observation result can still be obtained

Its return value can directly get the result of observation!

Method 2: Specify BuildContext for Sliver

Relatively complex to use, the scope of application is small, there are more than one Sliver is possible to use this method

Detailed instructions
BuildContext? _sliverListViewContext;

Create a ListView and record BuildContext in its builder callback

ListView _buildListView() {
  return ListView.separated(
    itemBuilder: (ctx, index) {
      if (_sliverListViewContext != ctx) {
        _sliverListViewContext = ctx;
      }
      ...
    },
    ...
  );
}

Create ListViewObserver

ListViewObserver(
  child: _buildListView(),
  sliverListContexts: () {
    return [if (_sliverListViewContext != null) _sliverListViewContext!];
  },
  onObserve: (resultMap) {
    final model = resultMap[_sliverListViewContext];
    if (model == null) return;

    // Prints the first child widget index that is currently being displayed
    print('firstChild.index -- ${model.firstChild?.index}');

    // Prints the index of all child widgets those are currently being displayed
    print('displaying -- ${model.displayingChildIndexList}');
  },
)

By default, ListView relevant data will only be observed when scrolling.

If needed, you can use ListViewOnceObserveNotification triggered an observation manually.

ListViewOnceObserveNotification().dispatch(_sliverListViewContext);

1.1、Parameter autoTriggerObserveTypes

Used to set types those can trigger observe automatically, defined as follows:

final List<ObserverAutoTriggerObserveType>? autoTriggerObserveTypes;
enum ObserverAutoTriggerObserveType {
  scrollStart,
  scrollUpdate,
  scrollEnd,
}

Defaults to [.scrollStart, .scrollUpdate, .scrollEnd].

Description of enum values as follow:

value Desc
scrollStart when a [Scrollable] widget has started scrolling.
scrollUpdate when a [Scrollable] widget has changed its scroll position.
scrollEnd when a [Scrollable] widget has stopped scrolling.

1.2、Parameter triggerOnObserveType

Used to set the prerequisite for triggering [onObserve] callback and [onObserveAll] callback, defined as follows:

final ObserverTriggerOnObserveType triggerOnObserveType;
enum ObserverTriggerOnObserveType {
  directly,
  displayingItemsChange,
}

Defaults to .displayingItemsChange.

Description of enum values as follow:

value Desc
directly The callback onObserve will be called directly when getting observed result for scrollView.
displayingItemsChange The callback onObserve will be called when child widget comes in and out or when the number of child widget changes.

1.3、Callback onObserveViewport

Only CustomScrollView is supported.

Used to observe which specified slivers are being displayed in the Viewport of CustomScrollView.

SliverViewObserver(
  child: _buildScrollView(),
  sliverContexts: () {
    return [
      if (grid1Context != null) grid1Context!,
      if (swipeContext != null) swipeContext!,
      if (grid2Context != null) grid2Context!,
    ];
  },
  onObserveViewport: (result) {
    firstChildCtxInViewport = result.firstChild.sliverContext;
    if (firstChildCtxInViewport == grid1Context) {
      debugPrint('current first sliver in viewport - gridView1');
    } else if (firstChildCtxInViewport == swipeContext) {
      debugPrint('current first sliver in viewport - swipeView');
    } else if (firstChildCtxInViewport == grid2Context) {
      debugPrint('current first sliver in viewport - gridView2');
    }
  },
)

1.4、Callback customTargetRenderSliverType

Only ListViewObserver and GridViewObserver are supported.

While maintaining the original observation logic, tell the package the RenderSliver to be observed, in order to support the observation of the list built by the third-party package.

customTargetRenderSliverType: (renderObj) {
  // Here you tell the package what type of RenderObject it needs to observe.
  return renderObj is ExtendedRenderSliverList;
},

1.5、Callback customHandleObserve

This callback is used to customize the observation logic and is used when the built-in observation logic does not meet your needs.

customHandleObserve: (context) {
  // Here you can customize the observation logic.
  final _obj = ObserverUtils.findRenderObject(context);
  if (_obj is RenderSliverList) {
    ObserverCore.handleListObserve(context: context);
  }
  if (_obj is RenderSliverGrid || _obj is RenderSliverWaterfallFlow) {
    return ObserverCore.handleGridObserve(context: context);
  }
  return null;
},

1.6、Callback extendedHandleObserve

Only SliverViewObserver is supported.

This callback is used to supplement the original observation logic, which originally only dealt with RenderSliverList, RenderSliverFixedExtentList and RenderSliverGrid.

extendedHandleObserve: (context) {
  // An extension of the original observation logic.
  final _obj = ObserverUtils.findRenderObject(context);
  if (_obj is RenderSliverWaterfallFlow) {
    return ObserverCore.handleGridObserve(context: context);
  }
  return null;
},

2、Scrolling to the specified index location

It should be used with the scrollView's cacheExtent property. Assigning an appropriate value to it can avoid unnecessary page turning. The recommendations are as follows:

  • If child widgets are fixed height in scrollView, use isFixedHeight instead of cacheExtent.
  • For scrollView such as detail page, it is recommended to set cacheExtent to double.maxFinite.
  • If child widgets are dynamic height in scrollView, it is recommended that setting cacheExtent to a large and reasonable value depending on your situation.

2.1、Basic usage

Create and use instance of ScrollController normally.

ScrollController scrollController = ScrollController();

ListView _buildListView() {
  return ListView.separated(
    controller: scrollController,
    ...
  );
}

Create an instance of ListObserverController pass it to ListViewObserver

ListObserverController observerController = ListObserverController(controller: scrollController);

ListViewObserver(
  controller: observerController,
  child: _buildListView(),
  ...
)

Now you can scroll to the specified index position

// Jump to the specified index position without animation.
observerController.jumpTo(index: 1)

// Jump to the specified index position with animation.
observerController.animateTo(
  index: 1,
  duration: const Duration(milliseconds: 250),
  curve: Curves.ease,
);

2.2、Parameter padding

If your ListView or GridView uses its padding parameter, you need to sync that value as well! Such as:

ListView.separated(padding: _padding, ...);
GridView.builder(padding: _padding, ...);
observerController.jumpTo(index: 1, padding: _padding);

⚠ Do not use SliverPadding in CustomScrollView.

2.3、Parameter isFixedHeight

If the height of a list child widget is fixed, it is recommended to use the 'isFixedHeight' parameter to improve performance.

⚠ Currently only ListView or SliverList is supported.

// Jump to the specified index position without animation.
observerController.jumpTo(index: 150, isFixedHeight: true)

// Jump to the specified index position with animation.
observerController.animateTo(
  index: 150, 
  isFixedHeight: true
  duration: const Duration(milliseconds: 250),
  curve: Curves.ease,
);

If you use CustomScrollView and its slivers contain SliverList and SliverGrid, this is also supported, but you need to use SliverViewObserver, and pass the corresponding BuildContext to distinguish the corresponding Sliver when calling the scroll method.

SliverViewObserver(
  controller: observerController,
  child: CustomScrollView(
    controller: scrollController,
    slivers: [
      _buildSliverListView1(),
      _buildSliverListView2(),
    ],
  ),
  sliverListContexts: () {
    return [
      if (_sliverViewCtx1 != null) _sliverViewCtx1!,
      if (_sliverViewCtx2 != null) _sliverViewCtx2!,
    ];
  },
  ...
)
observerController.animateTo(
  sliverContext: _sliverViewCtx2, // _sliverViewCtx1
  index: 10,
  duration: const Duration(milliseconds: 300),
  curve: Curves.easeInOut,
);

2.4、Parameter offset

Used to set the whole scrollView offset when scrolling to a specified index.

For example, in the scene with SliverAppBar, its height will change with the scrolling of ScrollView. After reaching a certain offset, it will be suspended on the top with a fixed height, and then we must pass this fixed height to the offset parameter.

SliverAppBar(
  key: appBarKey,
  pinned: true,
  expandedHeight: 200,
  flexibleSpace: FlexibleSpaceBar(
    title: const Text('AppBar'),
    background: Container(color: Colors.orange),
  ),
);
observerController.animateTo(
  ...
  offset: (offset) {
    // The height of the SliverAppBar is calculated base on target offset and is returned in the current callback.
    // The observerController internally adjusts the appropriate offset based on the return value.
    return ObserverUtils.calcPersistentHeaderExtent(
      key: appBarKey,
      offset: offset,
    );
  },
);

2.5、Parameter alignment

The alignment specifies the desired position for the leading edge of the child widget. It must be a value in the range [0.0, 1.0]. Such as:

  • alignment: 0 : Scrolling to the top position of the child widget.
  • alignment: 0.5 : Scrolling to the middle position of the child widget.
  • alignment: 1 : Scrolling to the tail position of the child widget.

2.6、Property cacheJumpIndexOffset

For performance reasons, ScrollController will caches the child's information by default when the listView jump or animate to the specified location, so that it can be used next time directly.

However, in scence where the height of child widget is always changing dynamically, this will cause unnecessary trouble, so you can turn this off by setting the cacheJumpIndexOffset property to false.

2.7、Method clearIndexOffsetCache

You can use the clearIndexOffsetCache method if you want to preserve the cache function of scrolling and only want to clear the cache in certain cases.

/// Clear the offset cache that jumping to a specified index location.
clearIndexOffsetCache(BuildContext? sliverContext) {
  ...
}

The parameter sliverContext needs to be passed only if you manage ScrollView's BuildContext by yourself.

2.8、Initial index location

  • Method 1: initialIndex

The simplest way to use, directly set the location index.

observerController = ListObserverController(controller: scrollController)
  ..initialIndex = 10;
  • Method 2: initialIndexModel

You can customize the configuration of the initial index position. See the end of this section for property descriptions.

observerController = ListObserverController(controller: scrollController)
  ..initialIndexModel = ObserverIndexPositionModel(
    index: 10,
    isFixedHeight = true,
    alignment = 0.5,
  );
  • Method 3: initialIndexModelBlock

You need return ObserverIndexPositionModel object within the callback.

This method applies to some of scenarios those the parameters can't be determined from the start, such as sliverContext.

observerController = SliverObserverController(controller: scrollController)
  ..initialIndexModelBlock = () {
    return ObserverIndexPositionModel(
      index: 6,
      sliverContext: _sliverListCtx,
      offset: calcPersistentHeaderExtent,
    );
  };

The structure of ObserverIndexPositionModel :

ObserverIndexPositionModel({
  required this.index,
  this.sliverContext,
  this.isFixedHeight = false,
  this.alignment = 0,
  this.offset,
  this.padding = EdgeInsets.zero,
});
Property Type Desc
index int The index of child widget.
sliverContext BuildContext The target sliver [BuildContext].
isFixedHeight bool If the height of the child widget and the height of the separator are fixed, please pass true to this property. Defaults to false
alignment double The alignment specifies the desired position for the leading edge of the child widget. It must be a value in the range [0.0, 1.0]. Defaults to 1.0
offset double Function(double targetOffset) Use this property when locating position needs an offset.
padding EdgeInsets If your ListView or GridView uses its padding parameter, you need to sync that value as well! Otherwise it is not required.

3、Chat Observer

3.1、Basic usage

We only need three steps to implement the chat session page effect.

  • 1、All chat data are displayed at the top of the listView when there is less than one screen of chat data.
  • 2、When inserting a chat data
    • If the latest message is close to the bottom of the list, the listView will be pushed up.
    • Otherwise, the listView will be fixed to the current chat position.

Step 1: Initialize the necessary ListObserverController and ChatScrollObserver.

/// Initialize ListObserverController
observerController = ListObserverController(controller: scrollController)
  ..cacheJumpIndexOffset = false;

/// Initialize ChatScrollObserver
chatObserver = ChatScrollObserver(observerController)
  // Greater than this offset will be fixed to the current chat position.
  ..fixedPositionOffset = 5
  ..toRebuildScrollViewCallback = () {
    // Here you can use other way to rebuild the specified listView instead of [setState]
    setState(() {});
  };

Step 2: Configure ListView as follows and wrap it with ListViewObserver.

Widget _buildListView() {
  Widget resultWidget = ListView.builder(
    physics: ChatObserverClampingScrollPhysics(observer: chatObserver),
    shrinkWrap: chatObserver.isShrinkWrap,
    reverse: true,
    controller: scrollController,
    ...
  );

  resultWidget = ListViewObserver(
    controller: observerController,
    child: resultWidget,
  );
  return resultWidget;
}

Step 3: Call the [standby] method of ChatScrollObserver before inserting or removing chat data.

onPressed: () {
  chatObserver.standby();
  setState(() {
    chatModels.insert(0, ChatDataHelper.createChatModel());
  });
},
...
onRemove: () {
  chatObserver.standby(isRemove: true);
  setState(() {
    chatModels.removeAt(index);
  });
},

This feature only handles inserting one message by default. If you need to insert multiple messages at once, you can pass the changeCount parameter to the standby method.

_addMessage(int count) {
  chatObserver.standby(changeCount: count);
  setState(() {
    needIncrementUnreadMsgCount = true;
    for (var i = 0; i < count; i++) {
      chatModels.insert(0, ChatDataHelper.createChatModel());
    }
  });
}

Note: This feature relies on the latest message view before the message is inserted as a reference to calculate the offset, so if too many messages are inserted at once and the reference message view cannot be rendered, this feature will fail, and you need to try to avoid this problem by setting a reasonable value for cacheExtent of ScrollView by yourself!

3.2、The result callback for processing chat position.

chatObserver = ChatScrollObserver(observerController)
  ..onHandlePositionResultCallback = (result) {
    switch (result.type) {
      case ChatScrollObserverHandlePositionType.keepPosition:
        // Keep the current chat position.
        // updateUnreadMsgCount(changeCount: result.changeCount);
        break;
      case ChatScrollObserverHandlePositionType.none:
        // Do nothing about the chat position.
        // updateUnreadMsgCount(isReset: true);
        break;
    }
  };

This callback is mainly used to display the unread bubbles of new messages when adding chat messages.

3.3、Generative message keeps position

The generative messages like ChatGPT also need to keep the message position when looking through old messages, you only need to adjust the processing mode in the standby method.

chatObserver.standby(
  mode: ChatScrollObserverHandleMode.generative,
  // changeCount: 1,
);

Note: The referenced item will be determined internally based on changeCount, and this mode only supports the case where generative messages are continuous.

3.4、Specifies the referenced item

If your generative messages are discontinuous, or there are generative message updates and the behavior of adding and deleting messages at the same time, in this complex case, you need to specify the referenced item by yourself, and This processing mode is more flexible.

chatObserver.standby(
  changeCount: 1,
  mode: ChatScrollObserverHandleMode.specified,
  refItemRelativeIndex: 2,
  refItemRelativeIndexAfterUpdate: 2,
);
  1. Set mode to .specified.
  2. Set refItemRelativeIndex to relative index of the referenced item before the update.
  3. Set refItemRelativeIndexAfterUpdate to relative index of the referenced item after the update.

Note: The relativeIndex refers to the relative index of the item being displayed on screen, as shown below

     trailing        relativeIndex
-----------------  -----------------
|     item4     |          4
|     item3     |          3
|     item2     |          2
|     item1     |          1
|     item0     |          0 
-----------------  -----------------
     leading
     trailing        relativeIndex
-----------------  -----------------
|     item14    |          4
|     item13    |          3
|     item12    |          2
|     item11    |          1
|     item10    |          0 
-----------------  -----------------
     leading

Remember, your refItemRelativeIndex and refItemRelativeIndexAfterUpdate should point to the same message object whatever you set!

4、Model Property

ObserveModel

The base class of the observing data.

Property Type Desc
sliver RenderSliver The target sliver.
visible bool Whether this sliver should be painted.
displayingChildIndexList List<int> Stores index list for children widgets those are displaying.
axis Axis The axis of sliver.
scrollOffset double The scroll offset of sliver.

ListViewObserveModel

A special observing models which inherits from the ObserveModel for ListView and SliverList.

Property Type Desc
sliver RenderSliverMultiBoxAdaptor The target sliverList.
firstChild ListViewObserveDisplayingChildModel The observing data of the first child widget that is displaying.
displayingChildModelList List<ListViewObserveDisplayingChildModel> Stores observing model list of displaying children widgets.

GridViewObserveModel

A special observing models which inherits from the ObserveModel for GridView and SliverGrid.

Property Type Desc
sliverGrid RenderSliverGrid The target sliverGrid.
firstGroupChildList List<GridViewObserveDisplayingChildModel> The observing datas of first group displaying child widgets.
displayingChildModelList List<GridViewObserveDisplayingChildModel> Stores observing model list of displaying children widgets.

ObserveDisplayingChildModel

Data information about the child widget that is currently being displayed.

Property Type Desc
sliver RenderSliver The target sliverList.
index int The index of child widget.
renderObject RenderBox The renderObject [RenderBox] of child widget.

ObserveDisplayingChildModelMixin

The currently displayed child widgets data information, is for ObserveDisplayingChildModel supplement.

Property Type Desc
axis Axis The axis of sliver.
size Size The size of child widget.
mainAxisSize double The size of child widget on the main axis.
scrollOffset double The scroll offset of sliver.
layoutOffset double The layout offset of child widget.
leadingMarginToViewport double The margin from the top of the child widget to the viewport.
trailingMarginToViewport double The margin from the bottom of the child widget to the viewport.
displayPercentage double The display percentage of the current widget.

Example

1、ListView / SliverList

2、GridView / SliverGrid

3、CustomScrollView

4、Scene

About Me

More Repositories

1

wechat_flutter

wechat_flutter is Flutter version WeChat, an excellent Flutter instant messaging IM open source library!
Dart
2,512
star
2

extended_image

A powerful official extension library of image, which support placeholder(loading)/ failed state, cache network, zoom pan image, photo view, slide out page, editor(crop,rotate,flip), paint custom etc.
Dart
1,908
star
3

NeteaseCloudMusic

Flutter - NeteaseCloudMusic Flutter 版本的网易云音乐
Dart
1,756
star
4

flutter_wechat_assets_picker

An image picker (also with video and audio) for Flutter projects based on the WeChat's UI.
Dart
1,500
star
5

flutter_smart_dialog

An elegant Flutter Dialog solution | 一种更优雅的 Flutter Dialog 解决方案
Dart
1,109
star
6

flutter_candies

custom flutter candies(widgets) for you to build flutter app easily, enjoy it
793
star
7

flutter_photo_manager

A Flutter plugin that provides images, videos, and audio abstraction management APIs without interface integration, available on Android, iOS, macOS and OpenHarmony.
Dart
675
star
8

extended_text

A powerful extended official text for Flutter, which supports Speical Text(Image,@somebody), Custom Background, Custom overFlow, Text Selection.
Dart
650
star
9

flutter_image_compress

flutter image compress
Dart
638
star
10

extended_nested_scroll_view

extended nested scroll view to fix following issues. 1.pinned sliver header issue 2.inner scrollables in tabview sync issue 3.pull to refresh is not work. 4.do without ScrollController in NestedScrollView's body
Dart
595
star
11

extended_text_field

extended official text field to quickly build special text like inline image, @somebody, custom background etc.
Dart
573
star
12

FlutterJsonBeanFactory

What I do is generate dart beans based on json, as well as generics parameters and json build instances
Kotlin
567
star
13

flutter_custom_calendar

Flutter的一个日历控件
Dart
501
star
14

like_button

Like Button is a flutter library that allows you to create a button with animation effects similar to Twitter's heart when you like something and animation effects to increase like count.
Dart
466
star
15

flutter_image_editor

Flutter plugin, support android/ios.Support crop, flip, rotate, color martix, mix image, add text. merge multi images.
Dart
410
star
16

flutter_wechat_camera_picker

A camera picker (take photos and videos) for Flutter projects based on WeChat's UI. It's a standalone module of wechat_assets_picker yet it can be run separately.
Dart
364
star
17

loading_more_list

A loading more list which supports ListView,GridView,WaterfallFlow and Slivers.
Dart
361
star
18

waterfall_flow

A Flutter grid view which supports waterfall flow layout.
Dart
358
star
19

JsonToDart

The tool to convert json to dart code, support Windows,Mac,Web.
Dart
356
star
20

extended_tabs

A powerful official extension library of Tab/TabBar/TabView, which support to scroll ancestor or child Tabs when current is overscroll, and set scroll direction and cache extent.
Dart
267
star
21

ncov_2019

An online query App for COVID-19 statistics developed by Flutter was used.
Dart
255
star
22

flutter-interactive-chart

A candlestick chart that supports pinch-to-zoom and panning.
Dart
210
star
23

pull_to_refresh_notification

Flutter plugin for building pull to refresh effects with PullToRefreshNotification and PullToRefreshContainer quickly.
Dart
187
star
24

flutter_drawing_board

A new Flutter package of drawing board
Dart
180
star
25

extended_sliver

A powerful extension library of Sliver, which include SliverToNestedScrollBoxAdapter, SliverPinnedPersistentHeader, SliverPinnedToBoxAdapter and ExtendedSliverAppbar.
Dart
166
star
26

flutter_interactional_widget

Dart
163
star
27

extended_image_library

package library for extended_image, extended_text and extended_text_field,provide common base class.
Dart
154
star
28

flutter_tilt

👀 Easily apply tilt parallax hover effects for Flutter, which supports tilt, light, shadow effects, and gyroscope sensors | 为 Flutter 轻松创建倾斜视差悬停效果,支持倾斜、光照、阴影效果和陀螺仪传感器
Dart
144
star
29

ff_annotation_route

Provide route generator to create route map quickly by annotations.
Dart
122
star
30

flutter_filereader

Flutter实现的本地文件(pdf word excel 等)查看插件,非在线预览
Dart
109
star
31

nav_router

flutter The lightest, easiest and most convenient route management!
Dart
103
star
32

w_popup_menu

w_popup_menu # A pop-up menu that mimics the iOS WeChat page
Dart
89
star
33

flutter_asset_generator

Generate an R file for mapping all assets. Supports preview of image.
Dart
86
star
34

stack_board

层叠控件摆放
Dart
85
star
35

left-scroll-actions

Flutter的左滑删除组件
Dart
82
star
36

extended_text_library

extended_text_library for extended_text and extended_text_field
Dart
75
star
37

flutter_hsvcolor_picker

An HSV color picker designed for your Flutter app. Pickers: RGB, HSV, Color Wheel, Palette Hue, Palette Saturation, Palette Value, Swatches.
Dart
71
star
38

flex_grid

The FlexGrid control provides a powerful and quickly way to display data in a tabular format. It is including that frozened column/row,loading more, high performance and better experience in TabBarView/PageView.
Dart
60
star
39

no-free-usage-action

A NO-FREE-USAGE action for github. (Only worked with github action.)
Dart
60
star
40

extended_list

extended list(ListView/GridView) support track collect garbage of children/viewport indexes, build lastChild as special child in the case that it is loadmore/no more item and enable to layout close to trailing.
Dart
51
star
41

fconsole

一个用于调试的面板
Dart
50
star
42

flutter_juejin

https://juejin.cn in Flutter
Dart
48
star
43

gitcandies

A GitHub Flutter application.
Dart
47
star
44

flutter_ali_auth

Flutter Ali Auth Plugin 阿里云一键登录Flutter插件
Java
47
star
45

ripple_backdrop_animate_route

A ripple animation with backdrop of route.
Dart
45
star
46

flutter_apodidae

🔥🔥 收录 Flutter 优化合集,apodidae (雨燕)是飞翔速度最快的鸟类,与 flutter (颤动)不谋而合。
40
star
47

flutter_bdface_collect

a baidu face offline collect plugin. Only Android and IOS platforms are supported. 百度人脸离线采集插件,只支持安卓和iOS。
Objective-C
38
star
48

flutter_record_mp3

flutter record mp3 using the native api
Dart
34
star
49

assets_generator

The flutter tool to generate assets‘s configs(yaml) and consts automatically for single project and multiple modules.
Dart
34
star
50

flutter_qweather

和风天气 Flutter 插件
Dart
29
star
51

flutter_draggable_container

A Draggable Widget Container
Dart
28
star
52

baidupan

Baidu net disk api for dart, 百度网盘的 dart 库
Dart
28
star
53

flutter_switch_clipper

A Flutter package that two widgets switch with clipper.
Dart
26
star
54

dash_painter

a package for flutter canvas paint dash line path easily.
Dart
25
star
55

http_client_helper

A Flutter plugin for http request with cancel and retry fuctions.
Dart
25
star
56

flutter_live_activities

Flutter Live Activities Plugin
Dart
23
star
57

flutter_slider_view

A slider view widget that supports custom type models and various configs.
Dart
22
star
58

packages

Custom Flutter Candies (packages) for you to easily build your Flutter app. Enjoy it!
20
star
59

extra_hittest_area

Manually add the extra hitTest area of a widget without changing its size or layout.
Dart
18
star
60

flutter_learning_tests

学习 Flutter 路上的点滴及小测~
Dart
17
star
61

ios_willpop_transition_theme

A Flutter package to solve the conflict between ios sliding back and Willpop
Dart
17
star
62

saver_gallery

Kotlin
15
star
63

flutter_mlkit_scan_plugin

Kotlin
15
star
64

should_rebuild

Dart
14
star
65

candies_analyzer_plugin

The plugin to help create custom analyzer plugin quickly and provide some useful lints and get suggestion and auto import for extension member.
Dart
14
star
66

flutter_novel

一款开源免费的在线小说阅读app,使用flutter进行开发
Dart
13
star
67

flutter_candies_gallery

flutter_candies
Dart
12
star
68

scan_barcode

Barcode/QRCode scan, base of google mikit.
Dart
12
star
69

CandiesBot

Java
11
star
70

flutter_float_window

flutter_float_window是一个悬浮窗插件,具备悬浮窗权限申请等功能
Java
11
star
71

extended_list_library

package library for extended_list and waterfall_flow, it provides core classes.
Dart
10
star
72

photo_widget

Base on photo_manager, wraps up some UI components to quickly display the photo_manager as a usable widget, inserting it wherever you need it.
Dart
10
star
73

extended_keyboard

Flutter plugin for create custom keyboards quickly.
Dart
10
star
74

flutter_app_build_tool

A CLI tool that helps to build Flutter apps.
Dart
9
star
75

douget

Dart
9
star
76

coordtransform

A coord transform tool. 提供百度坐标系(BD-09)、火星坐标系(国测局坐标系、GCJ02)、WGS84坐标系的相互转换。
Dart
9
star
77

ff_native_screenshot

A Flutter plugin to take or listen screenshot(support Platform Views) for Android and iOS with native code.
Java
9
star
78

flutter_custom_inspector

A customizable inspector that can called directly through Flutter apps.
Dart
8
star
79

adaptation

Screen for adaptation.
C++
8
star
80

properties

Load properties format in dart or flutter
Dart
7
star
81

w_reorder_list

Dart
7
star
82

JsonToDartWeb

JsonToDart Web 带字体文件
7
star
83

flutter_candies_demo_library

package library for demo of flutter candies, it provides core classes.
Dart
7
star
84

sync_scroll_library

The library for extended_tabs and flex_grid
Dart
6
star
85

env2dart

A simple way to generate `dart` code from a `.env` file.
Dart
6
star
86

loading_more_list_library

dart package library for LoadingMoreList, it provides core classes.
Dart
6
star
87

ff_annotation_route_library

The library for ff_annotation_route
Dart
5
star
88

dext

Some extension for dart
Dart
5
star
89

flutter_clean

help clean all of Flutter and Dart projects
Dart
4
star
90

flutter_challenges

Just do the first one, don't do second who.
Dart
4
star
91

flutter_candies_package_tools

tool to create package and demo
Dart
4
star
92

simple_provider

flutter simple provider
Dart
3
star
93

upgrade_tool

Resolve warnings caused by xxxbinding. Instance in Flutter 3.0
Dart
3
star
94

note_edit

A library of flutter note editor plugins.
Dart
2
star
95

blue_flutter

blue_flutter是flutter的蓝牙通讯插件
Java
2
star
96

ff_annotation_route_core

The core library for ff_annotation_route
Dart
2
star
97

mvimg

For get video from motion photo for android.
Dart
2
star
98

dart_wake_on_lan

A CLI application to send Wake-On-Lan packets.
Dart
2
star
99

.github

2
star
100

maven

Organizational maven deploy;组织的maven仓库;
1
star