flutterDev本周Flutter微件(持续更新)

教程备份

flutter sample中的例子~

导航:

AnimatedList  删除和新增带动画效果的列表;

从flutter sample 改写简化的例子,数据增删效果换成了FadeTransition组件,类似的动画组件有SizeTransition,AlignTransition,SlideTransition,ScaleTransion,RotationTransition


// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

class AnimatedListSample extends StatefulWidget {
@override
_AnimatedListSampleState createState() => _AnimatedListSampleState();
}

class _AnimatedListSampleState extends State<AnimatedListSample> {
final GlobalKey<AnimatedListState> _listKey = GlobalKey<AnimatedListState>();
List<int> _list;
int _selectedItem;
int _nextItem; // The next item inserted when the user presses the '+' button.

@override
void initState() {
super.initState();
_list = [0, 1, 2];
_nextItem = 3;
}

// Used to build list items that haven't been removed.
Widget _buildItem(
BuildContext context, int index, Animation<double> animation) {
return InkWell(
onTap: () {
setState(() {
_selectedItem = _list[index];
});
},
child: Card(
color: _selectedItem == _list[index] ? Colors.lightGreen : Colors.white,
child: FadeTransition(
opacity: animation.drive(Tween(begin: 0.0, end: 1.0)),
child: ListTile(
selected: _selectedItem == _list[index],
title: Text('${_list[index]}'),
),
),
),
);
}

Widget _buildRemovedItem(
int removedItem, BuildContext context, Animation<double> animation) {
return InkWell(
child: Card(
color: Colors.lightGreen,
child: FadeTransition(
opacity: animation.drive(Tween(begin: 0.0, end: 1.0)),
child: ListTile(
selected: true,
title: Text('${removedItem}'),
),
),
),
);
}

// Insert the "next item" into the list model.
void _insert() {
_list.insert(0, _nextItem++);
_listKey.currentState.insertItem(0, duration: Duration(milliseconds: 300));
}

// Remove the selected item from the list model.
void _remove() {
if (_selectedItem != null) {
int index = _list.indexOf(_selectedItem);
var removedItem = _list.removeAt(index);
print(removedItem);
_listKey.currentState.removeItem(index,
(BuildContext context, Animation<double> animation) {
return _buildRemovedItem(removedItem, context, animation);
});
setState(() {
_selectedItem = null;
});
}
}

@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('AnimatedList'),
actions: <Widget>[
IconButton(
icon: const Icon(Icons.add_circle),
onPressed: _insert,
tooltip: 'insert a new item',
),
IconButton(
icon: const Icon(Icons.remove_circle),
onPressed: _remove,
tooltip: 'remove the selected item',
),
],
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: AnimatedList(
key: _listKey,
initialItemCount: _list.length,
itemBuilder: _buildItem,
),
),
),
);
}
}

void main() {
runApp(AnimatedListSample());
}
 

ListView&&ExpansionTile  基于ExpansionTile实现可展开的ListView(树结构)

// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/material.dart'; class ExpansionTileSample extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: const Text('ExpansionTile'), ), body: ListView.builder( itemBuilder: (BuildContext context, int index) => EntryItem(data[index]), itemCount: data.length, ), ), ); } }
//元数据结构
class Entry { Entry(this.title, [this.children = const <Entry>[]]); final String title; final List<Entry> children; } //数据 final List<Entry> data = <Entry>[ Entry('Chapter A', <Entry>[ Entry('Section A0', <Entry>[ Entry('Item A0.1'), Entry('Item A0.2'), Entry('Item A0.3'), ], ), Entry('Section A1'), Entry('Section A2'), ], ), Entry('Chapter B', <Entry>[ Entry('Section B0'), Entry('Section B1'), ], ), Entry('Chapter C', <Entry>[ Entry('Section C0'), Entry('Section C1'), Entry('Section C2', <Entry>[ Entry('Item C2.0'), Entry('Item C2.1'), Entry('Item C2.2'), Entry('Item C2.3'), ], ), ], ), ]; class EntryItem extends StatelessWidget { const EntryItem(this.entry); final Entry entry; Widget _buildTiles(Entry root) { if (root.children.isEmpty) return ListTile(title: Text(root.title)); return ExpansionTile( key: PageStorageKey<Entry>(root),//保存页面滚动偏移量,重新渲染时可回到偏移量位置 title: Text(root.title), children: root.children.map<Widget>(_buildTiles).toList(), ); } @override Widget build(BuildContext context) { return _buildTiles(entry); } } void main() { runApp(ExpansionTileSample()); }

 TabBar&&TabBarView&&DefaultTabController&&TabPageSelector    标签页

例子:TabPageSelectorTabBarView结合使用,创建一个TabController添加控制;

// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

......

class _AppBarBottomSampleState extends State<AppBarBottomSample> with SingleTickerProviderStateMixin {
  TabController _tabController;

  @override
  void initState() {
    super.initState();
    _tabController = TabController(vsync: this, length: choices.length);
  }

  @override
  void dispose() {
    _tabController.dispose();
    super.dispose();
  }

  void _nextPage(int delta) {
    final int newIndex = _tabController.index + delta;
    if (newIndex < 0 || newIndex >= _tabController.length)
      return;
    _tabController.animateTo(newIndex);
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('AppBar Bottom Widget'),
          leading: IconButton(
            tooltip: 'Previous choice',
            icon: const Icon(Icons.arrow_back),
            onPressed: () { _nextPage(-1); },
          ),
          actions: <Widget>[
            IconButton(
              icon: const Icon(Icons.arrow_forward),
              tooltip: 'Next choice',
              onPressed: () { _nextPage(1); },
            ),
          ],
          bottom: PreferredSize(
            preferredSize: const Size.fromHeight(48.0),
            child: Theme(
              data: Theme.of(context).copyWith(accentColor: Colors.white),
              child: Container(
                height: 48.0,
                alignment: Alignment.center,
                child: TabPageSelector(controller: _tabController),
              ),
            ),
          ),
        ),
        body: TabBarView(
          controller: _tabController,
          children: choices.map<Widget>((Choice choice) {
            return Padding(
              padding: const EdgeInsets.all(16.0),
              child: ChoiceCard(choice: choice),
            );
          }).toList(),
        ),
      ),
    );
  }
}

......
......

例子:使用DefaultTabController默认控制页面中的TabBar和TabBarView

// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

......

class TabbedAppBarSample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: DefaultTabController(
        length: choices.length,
        child: Scaffold(
          appBar: AppBar(
            title: const Text('Tabbed AppBar'),
            bottom: TabBar(
              isScrollable: true,
              tabs: choices.map<Widget>((Choice choice) {
                return Tab(
                  text: choice.title,
                  icon: Icon(choice.icon),
                );
              }).toList(),
            ),
          ),
          body: TabBarView(
            children: choices.map<Widget>((Choice choice) {
              return Padding(
                padding: const EdgeInsets.all(16.0),
                child: ChoiceCard(choice: choice),
              );
            }).toList(),
          ),
        ),
      ),
    );
  }
}

......

posted @ 2019-12-30 14:52  Merrys  阅读(693)  评论(0编辑  收藏  举报