flutter 分层数据显示 类似于第一章的第一节显示 网络请求渲染 开源代码

效果图

![
在这里插入图片描述](https://img-blog.csdnimg.cn/20210508112618436.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lvdXRpYW5rZW5n,size_16,color_FFFFFF,t_70)

数据json格式

总StatefulWidget StudyDetailVideoPage

数据通过widget传递到内层

数据json格式

可以静态 可以通过接口获得

  List info = [
    {
      "chapter": "分治策略",
      "courseVideoList": [
        {"videoName": "分治策略的思想","videoPath":""},
        {"videoName": "分治策略2","videoPath":""},
        {"videoName": "分治策略3","videoPath":""}
      ]
    },
    {
      "chapter": "动态规划",
      "courseVideoList": [
        {"videoName": "动态规划1","videoPath":""},
        {"videoName": "动态规划3","videoPath":""},
        {"videoName": "动态规划3","videoPath":""}
      ]
    },
    {
      "chapter": "贪心法",
      "courseVideoList": [
        {"videoName": "贪心法1","videoPath":""},
        {"videoName": "贪心法2","videoPath":""},
        {"videoName": "贪心法3","videoPath":""}
      ]
    },
  ];

总Widget build中代码

CategoryList为新的StatefulWidget

必须新建这个StatefulWidget 不然做不到每个小的分层被独立

ListView.builder(
    key: UniqueKey(),
         itemCount: info.length,
         itemBuilder: (context, index) {
           return CategoryList(info[index]);
         })

CategoryList这个 StatefulWidget

里面的第一层、第二层被抽象出来变为一个widget

Container(
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          Divider(),
          buildFirstInkWell(),
          buildSecondInkWell()
        ],
      ),
    )

buildFirstInkWell核心代码

Row(
        children: <Widget>[
          Expanded(
              child: Container(
            padding: EdgeInsets.all(10),
            child: Text(
              "${widget.info['chapter']}",
              style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
            ),
          )),
          RotationTransition(
            turns: _animationController,
            child: Icon(Icons.arrow_right),
          )
        ],
      ),

buildSecondInkWell核心代码

Container(
                padding: EdgeInsets.all(12),
                child: Text("${item['videoName']}"),)

全部代码

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:loading_indicator_view/loading_indicator_view.dart';
import 'package:qituant_flutter_app/views/api/SpUtil.dart';
import '../api/api2.dart';
import '../api/FutureDioToken.dart';

String generalId;
class StudyDetailVideoPage extends StatefulWidget {
  final arguments;
  StudyDetailVideoPage({this.arguments});

  @override
  _StudyDetailVideoPageState createState() => _StudyDetailVideoPageState();
}

class _StudyDetailVideoPageState extends State<StudyDetailVideoPage> {
  // List info = [
  //   {
  //     "chapter": "分治策略",
  //     "courseVideoList": [
  //       {"videoName": "分治策略的思想","videoPath":""},
  //       {"videoName": "分治策略2","videoPath":""},
  //       {"videoName": "分治策略3","videoPath":""}
  //     ]
  //   },
  //   {
  //     "chapter": "动态规划",
  //     "courseVideoList": [
  //       {"videoName": "动态规划1","videoPath":""},
  //       {"videoName": "动态规划3","videoPath":""},
  //       {"videoName": "动态规划3","videoPath":""}
  //     ]
  //   },
  //   {
  //     "chapter": "贪心法",
  //     "courseVideoList": [
  //       {"videoName": "贪心法1","videoPath":""},
  //       {"videoName": "贪心法2","videoPath":""},
  //       {"videoName": "贪心法3","videoPath":""}
  //     ]
  //   },
  // ];

  List info=[];

  @override
  void initState() {
    super.initState();
    FutureDio('get', Api2.GetCourseVideo,{"generalId":widget.arguments['id']} ).then((res){
      print(res.data);
      setState(() {
        generalId=widget.arguments['id'];
        info=res.data['data'];
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        // appBar: new AppBar(
        //   automaticallyImplyLeading: false,
        //   centerTitle: true,
        //   title: new Text("我的学习"),
        //   backgroundColor: Color(0xff3954A3),
        // ),
        body: info.isNotEmpty? Container(
          child: ListView.builder(
              key: UniqueKey(),
              itemCount: info.length,
              itemBuilder: (context, index) {
                return CategoryList(info[index]);
              }),
        ):Center(
          child: BallSpinFadeLoaderIndicator(
            ballColor: Color(0xff3954A3),
            maxBallAlpha: 200,
            maxBallRadius: 4,
          ),
        ));
  }
}

class CategoryList extends StatefulWidget {
  final Map info;
  CategoryList(this.info);

  @override
  _CategoryListState createState() => _CategoryListState();
}

///分层数据
class _CategoryListState extends State<CategoryList> with SingleTickerProviderStateMixin {
  bool isExpand = false;
  AnimationController _animationController;
  @override
  void initState() {
    super.initState();
    _animationController =
        AnimationController(lowerBound: 0.0, upperBound: 0.25, vsync: this, duration: Duration(milliseconds: 400));
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          Divider(),
          buildFirstInkWell(),
          buildSecondInkWell()
        ],
      ),
    );
  }

  InkWell buildFirstInkWell() {
    return InkWell(
      onTap: () {
        if (_animationController.isCompleted) {
          isExpand=false;
          _animationController.reverse();
        }
        else {
          isExpand=true;
          _animationController.reset();
          _animationController.forward();
        }
        setState(() {
        });
      },
      child: Row(
        children: <Widget>[
          Expanded(
              child: Container(
            padding: EdgeInsets.all(10),
            child: Text(
              "${widget.info['chapter']}",
              style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
            ),
          )),
          RotationTransition(
            turns: _animationController,
            child: Icon(Icons.arrow_right),
          )
        ],
      ),
    );
  }

  buildSecondInkWell() {
    if (!isExpand) {
      return Container();
    }
    return ListView.builder(
        shrinkWrap: true,
        itemCount: widget.info['courseVideoList'].length,
        itemBuilder: (context, index) {
          Map item = widget.info['courseVideoList'][index];
          return InkWell(
            onTap: (){
                 FutureDio('post', Api2.RecordWatchVideo,{
                   "chapterName": widget.info['chapter'],
                   "coursePicture": SpUtil.preferences.getString("coursePicture"),
                   "courseTitle": SpUtil.preferences.getString("courseTitle"),
                   "generalId": generalId,
                   "orderId": SpUtil.preferences.getString("orderId"),
                   "userId": SpUtil.preferences.getString("user_id"),
                   "videoName": item['videoName'],
                   "videoPath": item['videoPath']
                 }
                 ).then((res){
                  print(res.data);
                });
                Navigator.pushNamed(context, '/videoScreen',arguments: {"id":item['videoPath'],"name":item['videoName']});
            },
            child:Container(
                padding: EdgeInsets.all(12),
                child: Text("${item['videoName']}"),)
          );
        });
  }
}

第一层右边箭头效果

点击箭头后箭头可以转90度

主要代码

 onTap: () {
        if (_animationController.isCompleted) {
          isExpand=false;
          _animationController.reverse();
        }
        else {
          isExpand=true;
          _animationController.reset();
          _animationController.forward();
        }
        setState(() {
        });
      },
要实现异步请求网络数据显示加载中demo,我们可以使用Flutter框架的http插件和状态管理来完成。 首先,我们需要在pubspec.yaml文件中添加http插件的依赖。 ``` dependencies: flutter: sdk: flutter http: ^0.13.0 ``` 然后,在需要显示加载中的页面中,创建一个有状态的组件。在该组件的状态中定义一个布尔值isLoading来表示数据是否正在加载中。 ```dart import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; class LoadingDemo extends StatefulWidget { @override _LoadingDemoState createState() => _LoadingDemoState(); } class _LoadingDemoState extends State<LoadingDemo> { bool isLoading = false; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Loading Demo'), ), body: Center( child: isLoading ? CircularProgressIndicator() : RaisedButton( child: Text('加载数据'), onPressed: () { fetchData(); }, ), ), ); } void fetchData() async { setState(() { isLoading = true; }); var response = await http.get('https://api.example.com/data'); if (response.statusCode == 200) { // 请求成功 var data = json.decode(response.body); // 处理数据 } else { // 请求失败 } setState(() { isLoading = false; }); } } ``` 在上述代码中,isLoading初始值为false,当点击加载数据按钮时,调用fetchData函数来请求数据。在请求数据时,将isLoading设置为true来显示加载动画,请求完成后再将其设置为false。 为了能够在Flutter显示加载动画,我们使用了CircularProgressIndicator小部件,它会在屏幕中间显示一个圆形的进度指示器。 通过上述代码,我们可以实现一个简单的加载中demo,用于异步请求网络数据显示加载状态。当点击加载数据按钮时,会显示加载动画,请求完成后隐藏加载动画。只需简单几步即可实现这样的功能。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值