Widgets

Pullable

Giriş

Pullable widget'ı, herhangi bir kaydırılabilir içeriğe çekerek yenileme ve daha fazla yükleme işlevselliği ekler. Alt widget'ınızı, birden fazla başlık animasyon stili destekleyen hareketle tetiklenen yenileme ve sayfalama davranışıyla sarar.

pull_to_refresh_flutter3 paketi üzerine inşa edilen Pullable, yaygın yapılandırmalar için adlandırılmış constructor'larla temiz bir API sunar.

Pullable(
  onRefresh: () async {
    // Fetch fresh data
    await fetchData();
  },
  child: ListView(
    children: items.map((item) => ListTile(title: Text(item))).toList(),
  ),
)

Temel Kullanım

Herhangi bir kaydırılabilir widget'ı Pullable ile sarın:

Pullable(
  onRefresh: () async {
    await loadLatestPosts();
  },
  child: ListView.builder(
    itemCount: posts.length,
    itemBuilder: (context, index) => PostCard(post: posts[index]),
  ),
)

Kullanıcı listeyi aşağı çektiğinde, onRefresh geri çağırması tetiklenir. Yenileme göstergesi, geri çağırma tamamlandığında otomatik olarak kapanır.

Constructor'lar

Pullable, yaygın yapılandırmalar için adlandırılmış constructor'lar sağlar:

Constructor Başlık Stili Açıklama
Pullable() Water Drop Varsayılan constructor
Pullable.classicHeader() Classic Klasik çekerek yenileme stili
Pullable.waterDropHeader() Water Drop Su damlası animasyonu
Pullable.materialClassicHeader() Material Classic Material Design klasik stil
Pullable.waterDropMaterialHeader() Water Drop Material Material su damlası stili
Pullable.bezierHeader() Bezier Bezier eğrisi animasyonu
Pullable.noBounce() Yapılandırılabilir ClampingScrollPhysics ile azaltılmış sıçrama
Pullable.custom() Özel widget Kendi başlık/altlık widget'larınızı kullanın
Pullable.builder() Yapılandırılabilir Tam PullableConfig kontrolü

Örnekler

// Classic header
Pullable.classicHeader(
  onRefresh: () async => await refreshData(),
  child: myListView,
)

// Material header
Pullable.materialClassicHeader(
  onRefresh: () async => await refreshData(),
  child: myListView,
)

// No bounce effect
Pullable.noBounce(
  onRefresh: () async => await refreshData(),
  headerType: PullableHeaderType.classic,
  child: myListView,
)

// Custom header widget
Pullable.custom(
  customHeader: MyCustomRefreshHeader(),
  onRefresh: () async => await refreshData(),
  child: myListView,
)

PullableConfig

Ayrıntılı kontrol için Pullable.builder() constructor'ı ile PullableConfig kullanın:

Pullable.builder(
  config: PullableConfig(
    enablePullDown: true,
    enablePullUp: true,
    headerType: PullableHeaderType.materialClassic,
    onRefresh: () async => await refreshData(),
    onLoading: () async => await loadMoreData(),
    refreshCompleteDelay: Duration(milliseconds: 500),
    loadCompleteDelay: Duration(milliseconds: 300),
    physics: BouncingScrollPhysics(),
  ),
  child: myListView,
)

Tüm Yapılandırma Seçenekleri

Özellik Tür Varsayılan Açıklama
enablePullDown bool true Aşağı çekerek yenilemeyi etkinleştir
enablePullUp bool false Yukarı çekerek daha fazla yüklemeyi etkinleştir
physics ScrollPhysics? null Özel kaydırma fiziği
onRefresh Future<void> Function()? null Yenileme geri çağırması
onLoading Future<void> Function()? null Daha fazla yükleme geri çağırması
headerType PullableHeaderType waterDrop Başlık animasyon stili
customHeader Widget? null Özel başlık widget'ı
customFooter Widget? null Özel altlık widget'ı
refreshCompleteDelay Duration Duration.zero Yenileme tamamlanmadan önceki gecikme
loadCompleteDelay Duration Duration.zero Yükleme tamamlanmadan önceki gecikme
enableOverScroll bool true Aşırı kaydırma efektine izin ver
cacheExtent double? null Kaydırma önbellek alanı
semanticChildCount int? null Semantik alt öğe sayısı
dragStartBehavior DragStartBehavior start Sürükleme hareketlerinin nasıl başlayacağı

Başlık Stilleri

Beş yerleşik başlık animasyonundan birini seçin:

enum PullableHeaderType {
  classic,           // Classic pull indicator
  waterDrop,         // Water drop animation (default)
  materialClassic,   // Material Design classic
  waterDropMaterial,  // Material water drop
  bezier,            // Bezier curve animation
}

Stili constructor veya yapılandırma üzerinden ayarlayın:

// Via named constructor
Pullable.bezierHeader(
  onRefresh: () async => await refreshData(),
  child: myListView,
)

// Via config
Pullable.builder(
  config: PullableConfig(
    headerType: PullableHeaderType.bezier,
    onRefresh: () async => await refreshData(),
  ),
  child: myListView,
)

Daha Fazla Yüklemek İçin Yukarı Çekme

Yukarı çekerek yükleme ile sayfalamayı etkinleştirin:

Pullable.builder(
  config: PullableConfig(
    enablePullDown: true,
    enablePullUp: true,
    onRefresh: () async {
      // Reset to page 1
      page = 1;
      items = await fetchItems(page: page);
      setState(() {});
    },
    onLoading: () async {
      // Load next page
      page++;
      List<Item> more = await fetchItems(page: page);
      items.addAll(more);
      setState(() {});
    },
  ),
  child: ListView.builder(
    itemCount: items.length,
    itemBuilder: (context, index) => ItemTile(item: items[index]),
  ),
)

Özel Başlıklar ve Altlıklar

Kendi başlık ve altlık widget'larınızı sağlayın:

Pullable.custom(
  customHeader: Container(
    height: 60,
    alignment: Alignment.center,
    child: CircularProgressIndicator(),
  ),
  customFooter: Container(
    height: 40,
    alignment: Alignment.center,
    child: Text("Loading more..."),
  ),
  enablePullUp: true,
  onRefresh: () async => await refreshData(),
  onLoading: () async => await loadMore(),
  child: myListView,
)

Controller

Programatik kontrol için bir RefreshController kullanın:

final RefreshController _controller = RefreshController();

Pullable(
  controller: _controller,
  onRefresh: () async => await refreshData(),
  child: myListView,
)

// Trigger refresh programmatically
_controller.triggerRefresh();

// Trigger loading programmatically
_controller.triggerLoading();

// Check state
bool refreshing = _controller.isRefreshing;
bool loading = _controller.isLoading;

RefreshController Üzerindeki Extension Metotları

Metot/Getter Dönüş Türü Açıklama
triggerRefresh() void Manuel olarak yenilemeyi tetikle
triggerLoading() void Manuel olarak daha fazla yüklemeyi tetikle
isRefreshing bool Yenileme aktif mi
isLoading bool Yükleme aktif mi

Extension Metodu

Herhangi bir widget .pullable() extension'ı ile çekerek yenileme özelliğiyle sarılabilir:

ListView(
  children: items.map((item) => ListTile(title: Text(item.name))).toList(),
).pullable(
  onRefresh: () async {
    await fetchItems();
  },
)

Özel yapılandırma ile:

myListView.pullable(
  onRefresh: () async => await refreshData(),
  pullableConfig: PullableConfig(
    headerType: PullableHeaderType.classic,
    enablePullUp: true,
    onLoading: () async => await loadMore(),
  ),
)

CollectionView Entegrasyonu

CollectionView, yerleşik sayfalama ile pullable varyantları sağlar:

CollectionView.pullable

CollectionView<User>.pullable(
  data: (iteration) async => api.getUsers(page: iteration),
  builder: (context, item) => UserTile(user: item.data),
  onRefresh: () => print('Refreshed!'),
  headerStyle: 'WaterDropHeader',
)

CollectionView.pullableSeparated

CollectionView<User>.pullableSeparated(
  data: (iteration) async => api.getUsers(page: iteration),
  builder: (context, item) => UserTile(user: item.data),
  separatorBuilder: (context, index) => Divider(),
)

CollectionView.pullableGrid

CollectionView<Product>.pullableGrid(
  data: (iteration) async => api.getProducts(page: iteration),
  builder: (context, item) => ProductCard(product: item.data),
  crossAxisCount: 2,
  mainAxisSpacing: 8,
  crossAxisSpacing: 8,
)

Pullable'a Özel Parametreler

Parametre Tür Açıklama
data Function(int iteration) Sayfalanmış veri geri çağırması (iteration 1'den başlar)
onRefresh Function()? Yenilemeden sonra geri çağırma
beforeRefresh Function()? Yenileme başlamadan önceki kanca
afterRefresh Function(dynamic)? Verilerle birlikte yenilemeden sonraki kanca
headerStyle String? Başlık türü adı (örn. 'WaterDropHeader', 'ClassicHeader')
footerLoadingIcon Widget? Altlık için özel yükleme göstergesi

Örnekler

Yenilemeli Sayfalanmış Liste

class _PostListState extends NyState<PostListPage> {
  List<Post> posts = [];
  int page = 1;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Pullable.builder(
        config: PullableConfig(
          enablePullDown: true,
          enablePullUp: true,
          headerType: PullableHeaderType.materialClassic,
          onRefresh: () async {
            page = 1;
            posts = await api<PostApiService>((request) => request.getPosts(page: page));
            setState(() {});
          },
          onLoading: () async {
            page++;
            List<Post> more = await api<PostApiService>((request) => request.getPosts(page: page));
            posts.addAll(more);
            setState(() {});
          },
        ),
        child: ListView.builder(
          itemCount: posts.length,
          itemBuilder: (context, index) => PostCard(post: posts[index]),
        ),
      ),
    );
  }
}

Extension ile Basit Yenileme

ListView(
  children: notifications
    .map((n) => ListTile(
      title: Text(n.title),
      subtitle: Text(n.body),
    ))
    .toList(),
).pullable(
  onRefresh: () async {
    notifications = await fetchNotifications();
    setState(() {});
  },
)