禁用网页浏览向上滚动
Disable pageview upward scroll
我在脚手架的正文中添加了综合浏览量(带有快照)。我希望用户只向下滚动页面,而不是向上滚动。你能帮忙吗?谢谢
您可以使用自定义滚动物理轻松实现,如下所示,
添加 CustomScrollPhysics()
作为您的 PageView()
、
的物理学
PageView(
scrollDirection: Axis.vertical,
physics: CustomScrollPhysics(), <--- here!!
controller: controller,
children: <Widget>[
//childrens
],
);
创建仅向下滚动的 CustomScrollPhysycs()
,
class CustomScrollPhysics extends ScrollPhysics {
CustomScrollPhysics({ScrollPhysics parent}) : super(parent: parent);
bool isGoingDown = false;
@override
CustomScrollPhysics applyTo(ScrollPhysics ancestor) {
return CustomScrollPhysics(parent: buildParent(ancestor));
}
@override
double applyPhysicsToUserOffset(ScrollMetrics position, double offset) {
isGoingDown = offset.sign < 0;
return offset;
}
@override
double applyBoundaryConditions(ScrollMetrics position, double value) {
//print("applyBoundaryConditions");
assert(() {
if (value == position.pixels) {
throw FlutterError(
'$runtimeType.applyBoundaryConditions() was called redundantly.\n'
'The proposed new position, $value, is exactly equal to the current position of the '
'given ${position.runtimeType}, ${position.pixels}.\n'
'The applyBoundaryConditions method should only be called when the value is '
'going to actually change the pixels, otherwise it is redundant.\n'
'The physics object in question was:\n'
' $this\n'
'The position object in question was:\n'
' $position\n');
}
return true;
}());
if (value < position.pixels && position.pixels <= position.minScrollExtent)
return value - position.pixels;
if (position.maxScrollExtent <= position.pixels && position.pixels < value)
// overscroll
return value - position.pixels;
if (value < position.minScrollExtent &&
position.minScrollExtent < position.pixels) // hit top edge
return value - position.minScrollExtent;
if (position.pixels < position.maxScrollExtent &&
position.maxScrollExtent < value) // hit bottom edge
return value - position.maxScrollExtent;
if (!isGoingDown) {
return value - position.pixels;
}
return 0.0;
}
}
通过使自定义滚动物理从 ScrollPhysics 扩展,您可以像下面一样。
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
void initState() {
super.initState();
}
emailAuthSheet(BuildContext context) {
return showModalBottomSheet(
context: context,
isScrollControlled: true,
builder: (context) {
return Container(
child: Wrap(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 150.0),
child: Divider(
thickness: 4.0,
),
),
Container(height: 450, color: Colors.blue[100]),
// Provider.of<LandingService>(context,listen: false).passwordLessSignIn(context),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
MaterialButton(
child: Text(
'Log in',
style: TextStyle(
fontSize: 18.0, fontWeight: FontWeight.bold),
),
onPressed: () {}),
MaterialButton(
child: Text(
'Sign in',
style: TextStyle(
fontSize: 18.0, fontWeight: FontWeight.bold),
),
onPressed: () {})
],
),
],
),
);
},
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: _buildBody(),
floatingActionButton: FloatingActionButton(
onPressed: () {
emailAuthSheet(context);
},
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
Widget _buildBody() {
return PageView(
scrollDirection: Axis.vertical,
physics: CustomScrollPhysics(),
children: [
Container(
height: 500,
color: Colors.red,
child: Center(
child: Text(
'Page index : 0',
style: TextStyle(fontSize: 20),
),
),
),
Container(
height: 500,
color: Colors.yellow,
child: Center(
child: Text(
'Page index : 1',
style: TextStyle(fontSize: 20),
),
),
),
Container(
height: 500,
color: Colors.red,
child: Center(
child: Text(
'Page index : 2',
style: TextStyle(fontSize: 20),
),
),
),
Container(
height: 500,
color: Colors.yellow,
child: Center(
child: Text(
'Page index : 3',
style: TextStyle(fontSize: 20),
),
),
),
],
);
}
}
class CustomScrollPhysics extends ScrollPhysics {
CustomScrollPhysics({ScrollPhysics parent}) : super(parent: parent);
bool isUp = false;
@override
CustomScrollPhysics applyTo(ScrollPhysics ancestor) {
return CustomScrollPhysics(parent: buildParent(ancestor));
}
@override
double applyPhysicsToUserOffset(ScrollMetrics position, double offset) {
isUp = offset.sign < 0;
return offset;
}
@override
double applyBoundaryConditions(ScrollMetrics position, double value) {
assert(() {
if (value == position.pixels) {
throw FlutterError(
'$runtimeType.applyBoundaryConditions() was called redundantly.\n'
'The proposed new position, $value, is exactly equal to the current position of the '
'given ${position.runtimeType}, ${position.pixels}.\n'
'The applyBoundaryConditions method should only be called when the value is '
'going to actually change the pixels, otherwise it is redundant.\n'
'The physics object in question was:\n'
' $this\n'
'The position object in question was:\n'
' $position\n');
}
return true;
}());
if (value < position.pixels && position.pixels <= position.minScrollExtent)
return value - position.pixels;
if (position.maxScrollExtent <= position.pixels && position.pixels < value)
return value - position.pixels;
if (value < position.minScrollExtent &&
position.minScrollExtent < position.pixels)
return value - position.minScrollExtent;
if (position.pixels < position.maxScrollExtent &&
position.maxScrollExtent < value)
return value - position.maxScrollExtent;
if (!isUp) {
return value - position.pixels;
}
return 0.0;
}
}
我在脚手架的正文中添加了综合浏览量(带有快照)。我希望用户只向下滚动页面,而不是向上滚动。你能帮忙吗?谢谢
您可以使用自定义滚动物理轻松实现,如下所示,
添加 CustomScrollPhysics()
作为您的 PageView()
、
PageView(
scrollDirection: Axis.vertical,
physics: CustomScrollPhysics(), <--- here!!
controller: controller,
children: <Widget>[
//childrens
],
);
创建仅向下滚动的 CustomScrollPhysycs()
,
class CustomScrollPhysics extends ScrollPhysics {
CustomScrollPhysics({ScrollPhysics parent}) : super(parent: parent);
bool isGoingDown = false;
@override
CustomScrollPhysics applyTo(ScrollPhysics ancestor) {
return CustomScrollPhysics(parent: buildParent(ancestor));
}
@override
double applyPhysicsToUserOffset(ScrollMetrics position, double offset) {
isGoingDown = offset.sign < 0;
return offset;
}
@override
double applyBoundaryConditions(ScrollMetrics position, double value) {
//print("applyBoundaryConditions");
assert(() {
if (value == position.pixels) {
throw FlutterError(
'$runtimeType.applyBoundaryConditions() was called redundantly.\n'
'The proposed new position, $value, is exactly equal to the current position of the '
'given ${position.runtimeType}, ${position.pixels}.\n'
'The applyBoundaryConditions method should only be called when the value is '
'going to actually change the pixels, otherwise it is redundant.\n'
'The physics object in question was:\n'
' $this\n'
'The position object in question was:\n'
' $position\n');
}
return true;
}());
if (value < position.pixels && position.pixels <= position.minScrollExtent)
return value - position.pixels;
if (position.maxScrollExtent <= position.pixels && position.pixels < value)
// overscroll
return value - position.pixels;
if (value < position.minScrollExtent &&
position.minScrollExtent < position.pixels) // hit top edge
return value - position.minScrollExtent;
if (position.pixels < position.maxScrollExtent &&
position.maxScrollExtent < value) // hit bottom edge
return value - position.maxScrollExtent;
if (!isGoingDown) {
return value - position.pixels;
}
return 0.0;
}
}
通过使自定义滚动物理从 ScrollPhysics 扩展,您可以像下面一样。
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
void initState() {
super.initState();
}
emailAuthSheet(BuildContext context) {
return showModalBottomSheet(
context: context,
isScrollControlled: true,
builder: (context) {
return Container(
child: Wrap(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 150.0),
child: Divider(
thickness: 4.0,
),
),
Container(height: 450, color: Colors.blue[100]),
// Provider.of<LandingService>(context,listen: false).passwordLessSignIn(context),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
MaterialButton(
child: Text(
'Log in',
style: TextStyle(
fontSize: 18.0, fontWeight: FontWeight.bold),
),
onPressed: () {}),
MaterialButton(
child: Text(
'Sign in',
style: TextStyle(
fontSize: 18.0, fontWeight: FontWeight.bold),
),
onPressed: () {})
],
),
],
),
);
},
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: _buildBody(),
floatingActionButton: FloatingActionButton(
onPressed: () {
emailAuthSheet(context);
},
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
Widget _buildBody() {
return PageView(
scrollDirection: Axis.vertical,
physics: CustomScrollPhysics(),
children: [
Container(
height: 500,
color: Colors.red,
child: Center(
child: Text(
'Page index : 0',
style: TextStyle(fontSize: 20),
),
),
),
Container(
height: 500,
color: Colors.yellow,
child: Center(
child: Text(
'Page index : 1',
style: TextStyle(fontSize: 20),
),
),
),
Container(
height: 500,
color: Colors.red,
child: Center(
child: Text(
'Page index : 2',
style: TextStyle(fontSize: 20),
),
),
),
Container(
height: 500,
color: Colors.yellow,
child: Center(
child: Text(
'Page index : 3',
style: TextStyle(fontSize: 20),
),
),
),
],
);
}
}
class CustomScrollPhysics extends ScrollPhysics {
CustomScrollPhysics({ScrollPhysics parent}) : super(parent: parent);
bool isUp = false;
@override
CustomScrollPhysics applyTo(ScrollPhysics ancestor) {
return CustomScrollPhysics(parent: buildParent(ancestor));
}
@override
double applyPhysicsToUserOffset(ScrollMetrics position, double offset) {
isUp = offset.sign < 0;
return offset;
}
@override
double applyBoundaryConditions(ScrollMetrics position, double value) {
assert(() {
if (value == position.pixels) {
throw FlutterError(
'$runtimeType.applyBoundaryConditions() was called redundantly.\n'
'The proposed new position, $value, is exactly equal to the current position of the '
'given ${position.runtimeType}, ${position.pixels}.\n'
'The applyBoundaryConditions method should only be called when the value is '
'going to actually change the pixels, otherwise it is redundant.\n'
'The physics object in question was:\n'
' $this\n'
'The position object in question was:\n'
' $position\n');
}
return true;
}());
if (value < position.pixels && position.pixels <= position.minScrollExtent)
return value - position.pixels;
if (position.maxScrollExtent <= position.pixels && position.pixels < value)
return value - position.pixels;
if (value < position.minScrollExtent &&
position.minScrollExtent < position.pixels)
return value - position.minScrollExtent;
if (position.pixels < position.maxScrollExtent &&
position.maxScrollExtent < value)
return value - position.maxScrollExtent;
if (!isUp) {
return value - position.pixels;
}
return 0.0;
}
}