一步一步完成Flutter应用开发-掘金App文章详情, 悬浮,标题动画

1,266 阅读2分钟

这边文章主要将掘金app的文章详情界面的内容构造和效果的实现,也是完结篇,或者有兴趣的同学们可以谈论想要去实现哪个页面的或者功能都可以谈论起来。一起进步。一个人终究没有一群人会走得远。

标题部分

看了一下掘金app文章详情的效果,我的思路是自定义一个appbar然后,左半部分是一个返回按钮,右部分是点击弹出分享的悬浮窗口,中间部分根据内容列表的滑动进行改变,大体思路就是通过pageView构建中间部分,禁止手势滑动,使用主动触发滑动效果,触发机制是内容滑动改变的距离 效果如下:

tutieshi_640x1343_4s.gif

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';

class DetailPage extends StatefulWidget {
  DetailPage({Key key}) : super(key: key);

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

class _DetailPageState extends State<DetailPage> {
  PageController controller = new PageController();
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Column(
      children: [
        Container(
          width: Get.width,
          height: 80,
          decoration: BoxDecoration(color: Colors.white),
          padding: EdgeInsets.only(
              top: Get.context.mediaQueryPadding.top, left: 10, right: 10),
          child: Row(
            children: [
              InkWell(
                child: Icon(
                  CupertinoIcons.back,
                  color: Color.fromRGBO(38, 38, 40, 1),
                ),
                onTap: () {
                  print('点击了返回');
                  Get.back();
                },
              ),
              Expanded(
                  child: PageView.builder(
                itemBuilder: (context, index) {
                  if (index == 0) {
                    return Container(
                      alignment: Alignment.center,
                      child: Text('一步一步完成Flutter应用开发-掘金文章详情页面'),
                    );
                  }
                  return Container(
                    child: Row(
                      children: [
                        Container(
                          height: 20,
                          width: 20,
                          decoration: BoxDecoration(
                              color: Colors.red,
                              borderRadius: BorderRadius.circular(10)),
                        )
                      ],
                    ),
                  );
                },
                itemCount: 2,
                scrollDirection: Axis.vertical,
                physics: NeverScrollableScrollPhysics(),
                controller: controller,
              )),
              InkWell(
                child: Icon(
                  Icons.list,
                  color: Color.fromRGBO(38, 38, 40, 1),
                ),
                onTap: () {
                  controller.animateTo(40,
                      duration: Duration(milliseconds: 500),
                      curve: Curves.ease);
                },
              ),
            ],
          ),
        )
      ],
    ));
  }
}

基于这个思想接下来完成下面的内容

内容部分的构建

这部分想要知道掘金内容的返回格式是什么,是markdown内容或者是html内容,如果是html内容传送门,可以参考一下。 效果:

tutieshi_640x1343_5s.gif 这块主要是通过markdown形式展示详情内容引入

flutter_markdown: ^0.5.2

在上述代码中加入详情内容代码

ScrollController _scrollController = new ScrollController();

  @override
  void initState() {
    super.initState();
    _scrollController
      ..addListener(() {
        setState(() {
          if (_scrollController.offset > 88 && _scrollController.offset < 100) {
            controller.animateTo(30,
                duration: Duration(milliseconds: 500), curve: Curves.ease);
          } else if (_scrollController.offset <= 0) {
            controller.animateTo(0,
                duration: Duration(milliseconds: 500), curve: Curves.ease);
          }
        });
      });
  }
  
  @override
  Widget build(BuildContext context) {
      ...省略上述代码
      //_markdownData为内容常量
      Expanded(
            child: Markdown(
          data: _markdownData,
          controller: _scrollController,
        ))
  }
 

悬浮弹窗

使用getX的Get.dialog进行展示悬浮弹窗 效果:

tutieshi_640x1343_4s.gif

代码如下:

renderItem(title) {
    return Column(
      children: [
        Container(
          height: 40,
          width: 40,
          margin: EdgeInsets.only(top: 10),
          decoration: BoxDecoration(
              color: Colors.red, borderRadius: BorderRadius.circular(20)),
        ),
        Padding(padding: EdgeInsets.only(top: 8)),
        Material(
          child: Text(title),
        )
      ],
    );
  }

//调用方法
Get.dialog(
                      UnconstrainedBox(
                        alignment: Alignment.bottomCenter,
                        child: Container(
                            width: Get.width,
                            height: Get.height * 0.6,
                            decoration: BoxDecoration(
                                color: Colors.white,
                                borderRadius: BorderRadius.only(
                                    topLeft: Radius.circular(20),
                                    topRight: Radius.circular(20))),
                            child: Column(
                              children: [
                                Padding(padding: EdgeInsets.only(top: 40)),
                                Row(
                                  mainAxisAlignment:
                                      MainAxisAlignment.spaceAround,
                                  crossAxisAlignment: CrossAxisAlignment.center,
                                  children: [
                                    renderItem('卡片分享'),
                                    renderItem('微信分享'),
                                    renderItem('朋友圈分享'),
                                    renderItem('微博分享'),
                                  ],
                                ),
                                Padding(padding: EdgeInsets.only(top: 20)),
                                Divider(
                                  height: 2,
                                  color: Colors.grey,
                                ),
                                Padding(padding: EdgeInsets.only(top: 20)),
                                Row(
                                  mainAxisAlignment:
                                      MainAxisAlignment.spaceAround,
                                  crossAxisAlignment: CrossAxisAlignment.center,
                                  children: [
                                    renderItem('卡片分享'),
                                    renderItem('微信分享'),
                                    renderItem('朋友圈分享'),
                                    renderItem('微博分享'),
                                  ],
                                ),
                                Row(
                                  mainAxisAlignment:
                                      MainAxisAlignment.spaceAround,
                                  crossAxisAlignment: CrossAxisAlignment.center,
                                  children: [
                                    renderItem('卡片分享'),
                                    renderItem('微信分享'),
                                    renderItem('朋友圈分享'),
                                    renderItem('微信分享'),
                                  ],
                                ),
                                Expanded(child: Container()),
                                GestureDetector(
                                  onTap: () {
                                    Get.back();
                                  },
                                  child: Container(
                                    margin: EdgeInsets.only(
                                        bottom: Get
                                            .context.mediaQueryPadding.bottom),
                                    width: Get.width,
                                    height: 40,
                                    alignment: Alignment.center,
                                    child: Material(
                                      child: Text(
                                        '取消',
                                      ),
                                    ),
                                  ),
                                ),
                              ],
                            )),
                      ),
                      useRootNavigator: false,
                      useSafeArea: false);

over ~~~~