Flutter高仿驾考宝典之顺序练习——两个地方的配合

1,241 阅读2分钟

首先效果上图:

再上代码

now,let‘s go。

分为三节:

1、底部下拉框,用于概括全局

2、中间页面的滑动切换

3、两个地方的配合,增加阴影,点击阴影下拉框回退等

本节为第二节底部中间页面的滑动切换 先说其中的功能: 1、上拉框的时候,根据高度显示阴影深度。 2、当下拉框处于展开状态时,点击阴影可以使下拉框还原成收缩状态,并且阴影消失。 3、点击下拉框中所选题号可以跳到指定问题页。

思想:
使用Stack增加一层带有透明色的蒙层(相当于前景色)作为阴影层,当高度改变时,蒙层颜色也跟随其改变。 在蒙层上增加点击事件(设置为只有在颜色最深处,即alpha值为1时才允许点击),点击之后,调用第一节的方法endSliver(false)即可回收。
阴影改变通过回掉可以解决;调用endSliver(false),可以用Pravider改变其状态,这里我模仿普遍的Controll类写的一个控制器,读者不用在意,这里只需要notification()即可。 点击下拉框时通过改变current的序号和左边以及右边布局所要取得index即可。

这就是一切,仔细看注释
Stack(
                children: <Widget>[
                //问题区域
                  PageChangeMiddle(
                    controll: sliverSelfControll,
                  ),
                  //是否显示蒙层,蒙层是阴影,即使alpha为0,也会阻碍底层的点击事件,所以没有阴影时需要使其消失
                  isAllowShow
                      ? SizedBox()
                      : GestureDetector(
                            //当alpha=1,即下拉框完全展开时才允许点击
                          onTap: isAllowClick
                              ? () {
                                  print('top');
                                    //方法内部通知调用endSliver
                                    sliverDrawBottomControll.shrink();
                                }
                              : null,
                              //蒙层Widget
                          child: TestAlphaWidget(Container(
                            color: Colors.black38,
                          )),
                        ),
                        //底部框
                  Align(
                    alignment: Alignment.bottomCenter,
                    child: DragContainer(
                    //数据集,即问题集合
                    questionMap, 
                    //底部题号点击事件
                    (int index) {
                      questionSourceChange.current = index;
                      //一旦notifications,左边页面将会收到通知取出current--,右边一样,所以上面会产生改变。
                      questionSourceChange.notifyListeners();
                    }, 
                    //当内部发生手势update和end时会回掉,因为此时需要控制isAllowShow和isAllowClick,以及改变蒙层透明度。
                    (double veOffset) {
                      alpha = 1 - veOffset / (practiceBottomDrawerHeight - videoFixHeight);
                      //通知蒙层改变透明度
                     testAlphaChangeNotifier.changeAlpha(alpha);
                        //判断是否允许显示蒙层
                      if (alpha == 1) {
                        isAllowShow = false;
                        setState(() {});
                      } else if (alpha == 0) {
                        isAllowShow = true;
                        setState(() {});
                      } else {
                        if (isAllowShow) {
                          isAllowShow = false;
                          setState(() {});
                        }
                      }
                      //透明度=1,允许点击,反之不然
                      if (alpha == 1) {
                        isAllowClick = true;
                        setState(() {});
                      } else {
                        if (isAllowClick) {
                          isAllowClick = false;
                          setState(() {});
                        }
                      }
                    }),
                  ),
                ],
              )

  class DragContainer extends StatefulWidget {
  Map<int, UserSource> questionMap;
  Function(int index) onTap;//第二个回掉,底部题号点击事件
  Function(double offset) onOffSliver;//第三个回掉,当偏移改变时回掉

  DragContainer(this.questionMap, this.onTap,this.onOffSliver);
  void _onUpdate(DragUpdateDetails details) {
    …………
    //此处回掉
      widget.onOffSliver(offsetDistance);
      setState(() {});
   
  }
void endSliver(isShow) {
    …………
    animation = Tween(begin: start, end: end).animate(curve)
      ..addListener(() {
        offsetDistance = animation.value;
        //此处回掉
        widget.onOffSliver(offsetDistance);
        setState(() {});
      });
    animalController.forward();
  }

至此,本章完结。