Flutter&OpenHarmony下拉刷新与加载更多

前言

下拉刷新和加载更多是移动应用中处理列表数据的标准交互模式。下拉刷新允许用户手动触发数据更新,获取最新内容;加载更多则在用户滚动到列表底部时自动加载下一页数据。在笔记应用中,这两个功能对于展示大量笔记列表、同步云端数据等场景非常重要。本文将详细介绍如何在Flutter和OpenHarmony平台上实现下拉刷新和加载更多功能。

Flutter下拉刷新实现

Flutter提供了RefreshIndicator组件实现下拉刷新功能。

dart 复制代码
class NotesListPage extends StatefulWidget {
  @override
  _NotesListPageState createState() => _NotesListPageState();
}

class _NotesListPageState extends State<NotesListPage> {
  List<Note> _notes = [];
  bool _isLoading = false;
  
  Future<void> _refreshNotes() async {
    setState(() => _isLoading = true);
    try {
      final notes = await NoteService.fetchNotes();
      setState(() {
        _notes = notes;
      });
    } finally {
      setState(() => _isLoading = false);
    }
  }
}

下拉刷新需要维护加载状态和数据列表。_isLoading用于显示加载指示器,_notes存储笔记数据。_refreshNotes方法是异步的,它先设置加载状态为true,然后调用服务获取数据,最后更新列表并重置加载状态。try-finally确保无论成功还是失败都会重置加载状态。这种状态管理模式是处理异步数据加载的标准做法。

dart 复制代码
@override
Widget build(BuildContext context) {
  return RefreshIndicator(
    onRefresh: _refreshNotes,
    color: Colors.blue,
    backgroundColor: Colors.white,
    child: ListView.builder(
      itemCount: _notes.length,
      itemBuilder: (context, index) {
        return NoteListItem(note: _notes[index]);
      },
    ),
  );
}

RefreshIndicator包裹可滚动的子组件,当用户下拉时显示刷新指示器。onRefresh回调必须返回Future,当Future完成时刷新指示器自动隐藏。color设置指示器的颜色,backgroundColor设置指示器背景色。ListView.builder作为子组件展示笔记列表。这种组合使用方式简洁高效,开发者只需关注数据加载逻辑,刷新动画由框架自动处理。

加载更多实现

加载更多需要监听列表滚动位置。

dart 复制代码
class _NotesListPageState extends State<NotesListPage> {
  final ScrollController _scrollController = ScrollController();
  List<Note> _notes = [];
  bool _isLoadingMore = false;
  bool _hasMore = true;
  int _page = 1;
  
  @override
  void initState() {
    super.initState();
    _scrollController.addListener(_onScroll);
    _loadNotes();
  }
  
  void _onScroll() {
    if (_scrollController.position.pixels >= 
        _scrollController.position.maxScrollExtent - 200) {
      _loadMoreNotes();
    }
  }
}

ScrollController用于监听列表的滚动事件。在initState中添加滚动监听器,_onScroll方法检查当前滚动位置是否接近底部。当距离底部小于200像素时触发加载更多。_page记录当前页码,_hasMore标记是否还有更多数据。这种提前触发的设计可以让用户在滚动过程中无缝加载新数据,提升体验流畅度。

dart 复制代码
Future<void> _loadMoreNotes() async {
  if (_isLoadingMore || !_hasMore) return;
  
  setState(() => _isLoadingMore = true);
  try {
    final newNotes = await NoteService.fetchNotes(page: _page + 1);
    setState(() {
      _notes.addAll(newNotes);
      _page++;
      _hasMore = newNotes.isNotEmpty;
    });
  } finally {
    setState(() => _isLoadingMore = false);
  }
}

_loadMoreNotes方法首先检查是否正在加载或已无更多数据,避免重复请求。加载成功后将新数据追加到列表末尾,页码加1,并根据返回数据是否为空判断是否还有更多数据。这种分页加载的模式可以有效减少单次请求的数据量,提升加载速度和用户体验。

dart 复制代码
Widget build(BuildContext context) {
  return RefreshIndicator(
    onRefresh: _refreshNotes,
    child: ListView.builder(
      controller: _scrollController,
      itemCount: _notes.length + (_hasMore ? 1 : 0),
      itemBuilder: (context, index) {
        if (index == _notes.length) {
          return _buildLoadingIndicator();
        }
        return NoteListItem(note: _notes[index]);
      },
    ),
  );
}

Widget _buildLoadingIndicator() {
  return Container(
    padding: EdgeInsets.all(16),
    alignment: Alignment.center,
    child: CircularProgressIndicator(),
  );
}

列表的itemCount在有更多数据时加1,用于显示加载指示器。itemBuilder中判断如果是最后一项则显示加载指示器,否则显示笔记项。这种设计将加载指示器作为列表的一部分,当用户滚动到底部时自然看到加载状态。CircularProgressIndicator是Material风格的圆形进度指示器,居中显示在列表底部。

OpenHarmony下拉刷新

OpenHarmony使用Refresh组件实现下拉刷新。

typescript 复制代码
@Entry
@Component
struct NotesListPage {
  @State noteList: NoteItem[] = []
  @State isRefreshing: boolean = false
  
  async loadNotes() {
    this.isRefreshing = true
    try {
      let notes = await NoteService.fetchNotes()
      this.noteList = notes
    } finally {
      this.isRefreshing = false
    }
  }
  
  build() {
    Refresh({ refreshing: this.isRefreshing }) {
      List() {
        ForEach(this.noteList, (item: NoteItem) => {
          ListItem() {
            this.NoteItemBuilder(item)
          }
        })
      }
    }
    .onRefreshing(() => {
      this.loadNotes()
    })
  }
}

OpenHarmony的Refresh组件包裹List实现下拉刷新功能。refreshing属性绑定刷新状态,当为true时显示刷新指示器。onRefreshing回调在用户下拉触发刷新时调用,开发者需要在数据加载完成后手动将isRefreshing设置为false。这种显式的状态管理方式让开发者对刷新流程有完全的控制权。

typescript 复制代码
Refresh({ refreshing: this.isRefreshing, offset: 100, friction: 100 }) {
  List() {
    ForEach(this.noteList, (item: NoteItem) => {
      ListItem() {
        this.NoteItemBuilder(item)
      }
    })
  }
}
.onRefreshing(() => {
  this.loadNotes()
})
.onStateChange((state: RefreshStatus) => {
  if (state === RefreshStatus.Done) {
    console.log('刷新完成')
  }
})

Refresh组件提供了更多配置选项。offset设置触发刷新的下拉距离阈值,friction设置下拉的阻尼系数。onStateChange回调可以监听刷新状态的变化,RefreshStatus包含Inactive、Drag、OverDrag、Refresh、Done等状态。通过这些配置和回调,开发者可以精细控制下拉刷新的行为和反馈。

OpenHarmony加载更多

typescript 复制代码
@Entry
@Component
struct NotesListPage {
  @State noteList: NoteItem[] = []
  @State isLoadingMore: boolean = false
  @State hasMore: boolean = true
  private page: number = 1
  
  build() {
    List() {
      ForEach(this.noteList, (item: NoteItem) => {
        ListItem() {
          this.NoteItemBuilder(item)
        }
      })
      
      if (this.hasMore) {
        ListItem() {
          this.LoadingIndicatorBuilder()
        }
      }
    }
    .onReachEnd(() => {
      this.loadMoreNotes()
    })
  }
}

OpenHarmony的List组件提供了onReachEnd回调,当列表滚动到底部时自动触发。这比手动监听滚动位置更加简洁。列表末尾根据hasMore状态显示加载指示器。这种声明式的写法使得加载更多的实现非常直观,开发者只需关注数据加载逻辑。

typescript 复制代码
async loadMoreNotes() {
  if (this.isLoadingMore || !this.hasMore) return
  
  this.isLoadingMore = true
  try {
    let newNotes = await NoteService.fetchNotes(this.page + 1)
    this.noteList = this.noteList.concat(newNotes)
    this.page++
    this.hasMore = newNotes.length > 0
  } finally {
    this.isLoadingMore = false
  }
}

@Builder
LoadingIndicatorBuilder() {
  Row() {
    LoadingProgress()
      .width(24)
      .height(24)
    Text('加载中...')
      .fontSize(14)
      .fontColor('#999999')
      .margin({ left: 8 })
  }
  .width('100%')
  .height(50)
  .justifyContent(FlexAlign.Center)
}

loadMoreNotes方法的逻辑与Flutter版本类似,先检查状态避免重复加载,然后请求数据并追加到列表。LoadingIndicatorBuilder使用@Builder装饰器定义加载指示器的UI,LoadingProgress是OpenHarmony提供的加载动画组件。Row水平排列加载动画和提示文字,居中显示在列表底部。

空状态处理

当列表为空时需要显示空状态提示。

dart 复制代码
Widget build(BuildContext context) {
  if (_notes.isEmpty && !_isLoading) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Icon(Icons.note, size: 64, color: Colors.grey),
          SizedBox(height: 16),
          Text('暂无笔记', style: TextStyle(color: Colors.grey)),
          SizedBox(height: 8),
          ElevatedButton(
            onPressed: _refreshNotes,
            child: Text('刷新'),
          ),
        ],
      ),
    );
  }
  return RefreshIndicator(/* ... */);
}

空状态页面显示图标、提示文字和刷新按钮,引导用户进行下一步操作。判断条件需要同时检查列表为空且不在加载中,避免在首次加载时显示空状态。这种友好的空状态设计可以提升用户体验,让用户知道当前状态并提供操作入口。

总结

下拉刷新和加载更多是列表数据展示的标准功能。Flutter和OpenHarmony都提供了便捷的实现方式,开发者需要合理管理加载状态、处理分页逻辑、提供加载反馈。通过这些功能的实现,笔记应用可以高效地展示大量数据,同时保持良好的用户体验。

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

相关推荐
2501_946233893 小时前
Flutter与OpenHarmony我的作品页面实现
android·javascript·flutter
w1395485642215 小时前
Flutter跨平台组件集成框架鸿蒙化使用指南
flutter·华为·harmonyos
圆号本昊16 小时前
Flutter Android Live2D 2026 实战:模型加载 + 集成渲染 + 显示全流程 + 10 个核心坑( OpenGL )
android·flutter·live2d
进击的前栈17 小时前
Flutter跨平台开发鸿蒙化HTTP解析工具包使用指南
flutter·http·harmonyos
BG17 小时前
Flutter超大图像导出插件:chunked_widget_to_image插件介绍
flutter
进击的前栈18 小时前
Flutter跨平台开发鸿蒙化HTTP测试工具包使用指南
flutter·http·harmonyos
圆号本昊19 小时前
【2025最新】Flutter 加载显示 Live2D 角色,实战与踩坑全链路分享
android·flutter
淡写成灰21 小时前
Flutter限制输入框只能输入中文,iOS拼音打不出来?
flutter