qhd-prevention-flutter/lib/customWidget/department_picker.dart

153 lines
4.4 KiB
Dart
Raw Normal View History

2025-07-03 09:45:15 +08:00
import 'package:flutter/material.dart';
class Category {
final String id;
final String title;
final List<Category> children;
Category({
required this.id,
required this.title,
this.children = const [],
});
}
class DepartmentPicker extends StatefulWidget {
final List<Category> data;
final String? initialSelectedId;
final Set<String>? initialExpandedSet;
final ValueChanged<String?> onSelected;
const DepartmentPicker({
Key? key,
required this.data,
this.initialSelectedId,
this.initialExpandedSet,
required this.onSelected,
}) : super(key: key);
@override
_DepartmentPickerState createState() => _DepartmentPickerState();
}
class _DepartmentPickerState extends State<DepartmentPicker> {
late String? selectedId;
late Set<String> expandedSet;
@override
void initState() {
super.initState();
selectedId = widget.initialSelectedId;
expandedSet = Set<String>.from(widget.initialExpandedSet ?? {});
}
Widget _buildRow(Category cat, int indent) {
final bool hasChildren = cat.children.isNotEmpty;
final bool isExpanded = expandedSet.contains(cat.id);
final bool isSelected = cat.id == selectedId;
return Column(
children: [
InkWell(
onTap: () {
setState(() {
if (hasChildren) {
if (isExpanded) {
expandedSet.remove(cat.id);
} else {
expandedSet.add(cat.id);
}
}
selectedId = cat.id;
});
},
child: Container(
color: Colors.white,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
// 左侧缩进
SizedBox(width: 16.0 * indent),
// 展开/占位图标
SizedBox(
width: 24,
child: hasChildren
? Icon(
isExpanded ? Icons.expand_less : Icons.expand_more,
size: 20,
color: Colors.grey[600],
)
: const SizedBox.shrink(),
),
const SizedBox(width: 8),
// 标题
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 12),
child: Text(cat.title),
),
),
// 单选圈保持右侧对齐
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Icon(
isSelected
? Icons.radio_button_checked
: Icons.radio_button_unchecked,
color: Colors.green,
),
),
],
),
),
),
if (hasChildren && isExpanded)
...cat.children.map((c) => _buildRow(c, indent + 1)),
// const Divider(height: 1),
],
);
}
@override
Widget build(BuildContext context) {
return Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height * 0.7,
color: Colors.transparent,
child: Column(
children: [
// 顶部操作栏
Container(
color: Colors.white,
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
GestureDetector(
onTap: () => Navigator.of(context).pop(),
child: const Text('取消', style: TextStyle(fontSize: 16)),
),
GestureDetector(
onTap: () => Navigator.of(context).pop(selectedId),
child: const Text('确定', style: TextStyle(fontSize: 16, color: Colors.green),),
),
],
),
),
const Divider(height: 1),
// 列表区
Expanded(
child: Container(
color: Colors.white,
child: ListView.builder(
itemCount: widget.data.length,
itemBuilder: (ctx, idx) => _buildRow(widget.data[idx], 0),
),
),
),
],
),
);
}
}