CustomScrollView
の中に SliverAppBar
でスクロールの各タイトル
SliverReorderableList
を利用した MySliverReorderableList
が各項目の中身
import 'package:flutter/material.dart'; class HomeScreen extends StatelessWidget { const HomeScreen({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return const Material( child: CustomScrollView( slivers: [ SliverAppBar( pinned: true, title: Text('title1'), ), MySliverReorderableList(), SliverAppBar( pinned: true, title: Text('title2'), ), MySliverReorderableList(), SliverAppBar( pinned: true, title: Text('title3'), ), MySliverReorderableList(), ], ), ); } } class MySliverReorderableList extends StatefulWidget { const MySliverReorderableList({ Key? key, }) : super(key: key); @override State<MySliverReorderableList> createState() => _MySliverReorderableListState(); } class _MySliverReorderableListState extends State<MySliverReorderableList> { final _items = List.generate( 10, (index) => index, ); @override Widget build(BuildContext context) { return SliverReorderableList( itemBuilder: (context, index) { return ReorderableDragStartListener( key: UniqueKey(), index: index, child: Material( child: DecoratedBox( decoration: BoxDecoration( border: Border.all( color: Colors.grey, )), child: ListTile( title: Text('Item No.${_items[index]}'), ), ), ), ); }, itemCount: _items.length, onReorder: (oldIndex, newIndex) { setState(() { if (oldIndex < newIndex) { newIndex -= 1; } final temp = _items[oldIndex]; _items ..removeAt(oldIndex) ..insert(newIndex, temp); }); }, ); } }