界面布局:第一层是左右结构, 左边只能上下滑动, 右边既可以水平滑动又可以上下滑动, 而且左边和右边的上下滑动同步。
其中包含ListView去掉边界水波纹的设置。
这里先添加Google开发团队开发的依赖库 linked_scroll_controller 。
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
linked_scroll_controller: ^0.2.0
完整代码如下
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:linked_scroll_controller/linked_scroll_controller.dart';
// import 'package:my_main/common/util/base_util.dart';
void main() {
// BaseUtil.logToConsole('main_begin');
//如果size是0, 则设置回调, 在回调中runApp。
if (window.physicalSize.isEmpty) {
window.onMetricsChanged = () {
//在回调中, size仍然有可能是0。
if (!window.physicalSize.isEmpty) {
window.onMetricsChanged = null;
runApp(MyApp());
}
};
} else {
//如果size非0, 则直接runApp。
runApp(MyApp());
}
// BaseUtil.logToConsole('main_end');
}
class MyApp extends StatelessWidget {
MyApp({Key? key}) : super(key: key) {
// BaseUtil.logToConsole('MyApp');
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Welcome to Flutter',
home: Scaffold(
appBar: AppBar(
title: const Text('ScrollView'),
),
backgroundColor: const Color(0xfff3f3f3),
//body占屏幕的大部分。
body: const MyScrollWidget(),
),
);
}
}
class MyScrollWidget extends StatefulWidget {
const MyScrollWidget({super.key});
@override
State<StatefulWidget> createState() => _MyScrollWidgetState();
}
class _MyScrollWidgetState extends State<MyScrollWidget> {
static const double _textRowH = 40.0;
static const double _leftRowSeparatorH = 1.0;
static const int _leftRowCount = 23;
late LinkedScrollControllerGroup _controllers;
late ScrollController _controllerForL;
late ScrollController _controllerForR;
@override
void dispose() {
_controllerForL.dispose();
_controllerForR.dispose();
super.dispose();
}
@override
void initState() {
super.initState();
_controllers = LinkedScrollControllerGroup();
_controllerForL = _controllers.addAndGet();
_controllerForR = _controllers.addAndGet();
}
/// 注: Flutter中的ScrollView是抽象类, 因此不能直接用来创建对象。
/// Flutter也提供了它的子类, 如 ListView、PageView、GridView、CustomScrollView 。
/// 下面的布局:第一层是左右结构, 左边只能上下滑动, 右边既可以水平滑动又可以上下滑动, 而且左边和右边的上下滑动同步。
@override
Widget build(BuildContext context) {
// 注: MediaQuery.of(context).size 要放在build中调用。
final boxSize = MediaQuery.of(context).size;
const mainLeftViewW = 80.0;
return Row(
children: [
_buildMainLeftView(mainLeftViewW),
_buildMainRightView(boxSize.width + 200),
],
);
}
Widget _buildMainLeftView(double width) {
return Container(
width: width,
color: const Color(0xfff0f0f0),
child: ListView.separated(
controller: _controllerForL,
itemCount: _leftRowCount,
itemBuilder: (BuildContext context, int index) {
return Container(
height: _textRowH,
alignment: Alignment.centerLeft,
child: Text('左侧栏-行' + (index + 1).toString()),
);
},
separatorBuilder: (BuildContext context, int index) {
return Container(
height: _leftRowSeparatorH, color: const Color(0xff999999));
},
),
);
}
Widget _buildMainRightView(double contentW) {
const double eachSpaceH = (_textRowH * (_leftRowCount - 3) +
_leftRowSeparatorH * (_leftRowCount - 1)) /
2.0;
return Expanded(
flex: 1,
child: ListView(
scrollDirection: Axis.horizontal,
children: [
SizedBox(
width: contentW,
child: ListView(
controller: _controllerForR,
children: [
SizedBox(
height: _textRowH,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: const [
Text('== == == BeginLeft == == =='),
Text('== == == BeginRight == == =='),
],
),
),
const SizedBox(height: eachSpaceH),
const SizedBox(
height: _textRowH,
child: Text('== == == 既可以水平滑动又可以上下滑动 == == =='),
),
const SizedBox(height: eachSpaceH),
const SizedBox(
height: _textRowH,
child: Text(
'== == == End == == ==',
textAlign: TextAlign.center,
),
),
],
),
),
],
),
);
}
}
/// ListView去掉边界水波纹, 使用示例:
/// ScrollConfiguration(
/// behavior: MyScrollBehavior(),
/// child: ListView.builder( . . . ),
/// );
class MyScrollBehavior extends ScrollBehavior {
@override
Widget buildOverscrollIndicator(
BuildContext context, Widget child, ScrollableDetails details) {
switch (getPlatform(context)) {
case TargetPlatform.iOS:
return child;
case TargetPlatform.android:
case TargetPlatform.fuchsia:
return GlowingOverscrollIndicator(
child: child,
// 不显示头部水波纹
showLeading: false,
// 不显示尾部水波纹
showTrailing: false,
axisDirection: details.direction,
color: Colors.red,
);
case TargetPlatform.linux:
break;
case TargetPlatform.macOS:
break;
case TargetPlatform.windows:
break;
}
return child;
}
}