首先效果上图:
now,let‘s go。
分为三节:
本节为第二节底部中间页面的滑动切换 先说其中的功能: 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();
}
至此,本章完结。