Skip to content

Commit 2684009

Browse files
committed
BLE tile more readable
1 parent f6a83ac commit 2684009

File tree

3 files changed

+126
-116
lines changed

3 files changed

+126
-116
lines changed

lib/widgets/dropdown_card.dart

Lines changed: 123 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -31,27 +31,20 @@ class _DropdownCardState extends State<DropdownCard> {
3131
String? selectedValue;
3232
late BLEData bleData;
3333
StreamSubscription? _charSubscription;
34-
FixedExtentScrollController wheelScroller = FixedExtentScrollController(initialItem: 0);
35-
double _wheelVisibility = 0.0;
36-
Timer _wheelVisibilityTimer = Timer.periodic(Duration(milliseconds: 500), (_wheelVisibilityTimer) {});
37-
int _deviceCounter = 0;
34+
final ScrollController _scrollController = ScrollController();
3835

3936
@override
4037
void initState() {
4138
super.initState();
4239
bleData = BLEDataManager.forDevice(this.widget.device);
4340
buildDevicesMap();
4441
selectedValue = ddItems.isNotEmpty ? ddItems[0] : null;
45-
_wheelVisibilityTimer = Timer.periodic(Duration(milliseconds: 500), (_wheelVisibilityTimer) {
46-
_wheelVisibility = 1;
47-
if (mounted) setState(() {});
48-
});
4942
try {
5043
_charSubscription = this.bleData.getMyCharacteristic(this.widget.device).onValueReceived.listen((data) async {
5144
if (mounted) {
5245
buildDevicesMap();
5346
setState(() {
54-
ddItems;
47+
// Trigger rebuild
5548
});
5649
}
5750
});
@@ -62,14 +55,12 @@ class _DropdownCardState extends State<DropdownCard> {
6255

6356
@override
6457
void dispose() {
65-
super.dispose();
6658
_charSubscription?.cancel();
67-
_wheelVisibilityTimer.cancel();
59+
super.dispose();
6860
}
6961

7062
void buildDevicesMap() {
71-
_deviceCounter = ddItems.length;
72-
late List _items;
63+
List _items = [];
7364
ddItems = [this.widget.c["value"]];
7465
this
7566
.bleData
@@ -104,10 +95,6 @@ class _DropdownCardState extends State<DropdownCard> {
10495
}
10596
//remove duplicates:
10697
ddItems = ddItems.toSet().toList(); // Remove duplicates
107-
if(ddItems.length != _deviceCounter) {
108-
// If the length has changed, update the wheel scroller
109-
wheelScroller.jumpToItem(ddItems.length);
110-
}
11198
}
11299

113100
Future _changeBLEDevice(BuildContext context) async {
@@ -125,114 +112,137 @@ class _DropdownCardState extends State<DropdownCard> {
125112

126113
@override
127114
Widget build(BuildContext context) {
128-
return SingleChildScrollView(
115+
return Center(
129116
child: Container(
130117
constraints: BoxConstraints(
131-
maxHeight: MediaQuery.of(context).size.height * 0.3,
118+
maxHeight: MediaQuery.of(context).size.height * 0.6,
119+
maxWidth: MediaQuery.of(context).size.width * 0.9,
132120
),
133121
child: Card(
134-
elevation: 15,
122+
elevation: 8,
135123
shape: RoundedRectangleBorder(
136-
borderRadius: BorderRadius.circular(10),
124+
borderRadius: BorderRadius.circular(16),
137125
),
138-
child: Column(
139-
mainAxisSize: MainAxisSize.min,
140-
children: <Widget>[
141-
Padding(
142-
padding: const EdgeInsets.all(8.0),
143-
child: Text(
144-
this.widget.c["humanReadableName"],
145-
style: TextStyle(fontSize: 20),
146-
textAlign: TextAlign.left,
126+
child: Padding(
127+
padding: const EdgeInsets.symmetric(vertical: 16.0),
128+
child: Column(
129+
mainAxisSize: MainAxisSize.min,
130+
children: <Widget>[
131+
Padding(
132+
padding: const EdgeInsets.symmetric(horizontal: 16.0),
133+
child: Text(
134+
this.widget.c["humanReadableName"],
135+
style: Theme.of(context).textTheme.titleLarge?.copyWith(fontWeight: FontWeight.bold),
136+
textAlign: TextAlign.center,
137+
),
147138
),
148-
),
149-
Text(this.widget.c["value"]),
150-
SizedBox(height: 20),
151-
Expanded(
152-
child: AnimatedOpacity(
153-
opacity: _wheelVisibility,
154-
duration: const Duration(seconds: 1),
155-
child: ListWheelScrollView.useDelegate(
156-
itemExtent: 50,
157-
diameterRatio: 2.5,
158-
perspective: 0.005,
159-
clipBehavior: Clip.none,
160-
renderChildrenOutsideViewport: true,
161-
physics: FixedExtentScrollPhysics(),
162-
controller: wheelScroller,
163-
childDelegate: ListWheelChildBuilderDelegate(
164-
childCount: ddItems.length,
165-
builder: (BuildContext context, int index) {
166-
return SizedBox(
167-
width: MediaQuery.of(context).size.width * 0.65,
168-
child: Container(
169-
decoration: BoxDecoration(
170-
borderRadius: BorderRadius.circular(8),
171-
border: Border.all(
172-
color: Theme.of(context).dividerColor.withOpacity(0.3),
173-
width: 1,
174-
),
175-
),
176-
child: ListTile(
177-
enableFeedback: true,
178-
shape: RoundedRectangleBorder(
139+
SizedBox(height: 8),
140+
Padding(
141+
padding: const EdgeInsets.symmetric(horizontal: 16.0),
142+
child: Text(
143+
"Current: ${this.widget.c["value"]}",
144+
style: Theme.of(context).textTheme.bodyMedium?.copyWith(color: Colors.grey),
145+
),
146+
),
147+
Divider(height: 24),
148+
Flexible(
149+
child: ddItems.isEmpty
150+
? Padding(
151+
padding: const EdgeInsets.all(32.0),
152+
child: Center(child: Text("No devices found")),
153+
)
154+
: ScrollbarTheme(
155+
data: ScrollbarThemeData(
156+
thumbColor: WidgetStatePropertyAll(Colors.blueGrey),
157+
trackVisibility: WidgetStatePropertyAll(true),
158+
thickness: WidgetStatePropertyAll(20.0),
159+
),
160+
child: Scrollbar(
161+
controller: _scrollController,
162+
thumbVisibility: true,
163+
child: ListView.separated(
164+
controller: _scrollController,
165+
shrinkWrap: true,
166+
padding: EdgeInsets.symmetric(horizontal: 8),
167+
itemCount: ddItems.length,
168+
separatorBuilder: (ctx, i) => SizedBox(height: 4),
169+
itemBuilder: (BuildContext context, int index) {
170+
final item = ddItems[index];
171+
final isSelected = item == this.widget.c["value"];
172+
173+
return Material(
174+
color: isSelected ? Theme.of(context).primaryColor.withValues(alpha: 0.1) : Colors.transparent,
179175
borderRadius: BorderRadius.circular(8),
180-
),
181-
title: Text(
182-
ddItems[index],
183-
textAlign: TextAlign.center,
184-
textScaler: TextScaler.linear(1.1),
185-
style: TextStyle(
186-
fontWeight: FontWeight.w500,
176+
child: InkWell(
177+
borderRadius: BorderRadius.circular(8),
178+
onTap: () {
179+
selectedValue = item;
180+
_changeBLEDevice(context);
181+
},
182+
child: Padding(
183+
padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 16.0),
184+
child: Row(
185+
children: [
186+
Expanded(
187+
child: Text(
188+
item,
189+
style: TextStyle(
190+
fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
191+
fontSize: 16,
192+
color: isSelected ? Theme.of(context).primaryColor : null,
193+
),
194+
),
195+
),
196+
if (isSelected)
197+
Icon(Icons.check_circle, color: Theme.of(context).primaryColor, size: 20),
198+
],
199+
),
200+
),
187201
),
188-
),
189-
titleAlignment: ListTileTitleAlignment.center,
190-
onTap: () {
191-
selectedValue = ddItems[index];
192-
_changeBLEDevice(context);
193-
},
194-
),
202+
);
203+
},
195204
),
196-
);
197-
},
198-
),
205+
),
206+
),
207+
),
208+
Divider(height: 24),
209+
Padding(
210+
padding: const EdgeInsets.symmetric(horizontal: 16.0),
211+
child: Row(
212+
mainAxisAlignment: MainAxisAlignment.end,
213+
children: <Widget>[
214+
TextButton.icon(
215+
icon: Icon(Icons.refresh),
216+
label: const Text('SCAN'),
217+
onPressed: () {
218+
//Find the save command and execute it
219+
this
220+
.bleData
221+
.customCharacteristic
222+
.forEach((c) => this.bleData.findNSave(this.widget.device, c, scanBLEVname));
223+
}),
224+
Spacer(),
225+
TextButton(
226+
child: const Text('BACK'),
227+
onPressed: () {
228+
Navigator.pop(context);
229+
}),
230+
const SizedBox(width: 8),
231+
FilledButton(
232+
child: const Text('SAVE'),
233+
onPressed: () {
234+
//Find the save command and execute it
235+
this
236+
.bleData
237+
.customCharacteristic
238+
.forEach((c) => this.bleData.findNSave(this.widget.device, c, saveVname));
239+
Navigator.pop(context);
240+
}),
241+
],
199242
),
200243
),
201-
),
202-
SizedBox(height: 20),
203-
Row(
204-
mainAxisAlignment: MainAxisAlignment.end,
205-
children: <Widget>[
206-
TextButton(
207-
child: const Text('SCAN'),
208-
onPressed: () {
209-
//Find the save command and execute it
210-
this
211-
.bleData
212-
.customCharacteristic
213-
.forEach((c) => this.bleData.findNSave(this.widget.device, c, scanBLEVname));
214-
}),
215-
const SizedBox(width: 8),
216-
TextButton(
217-
child: const Text('BACK'),
218-
onPressed: () {
219-
Navigator.pop(context);
220-
}),
221-
const SizedBox(width: 8),
222-
TextButton(
223-
child: const Text('SAVE'),
224-
onPressed: () {
225-
//Find the save command and execute it
226-
this
227-
.bleData
228-
.customCharacteristic
229-
.forEach((c) => this.bleData.findNSave(this.widget.device, c, saveVname));
230-
Navigator.pop(context);
231-
}),
232-
const SizedBox(width: 8),
233-
],
234-
),
235-
],
244+
],
245+
),
236246
),
237247
),
238248
),

lib/widgets/setting_tile.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ class _SettingTileState extends State<SettingTile> {
9999
child: Column(
100100
children: <Widget>[
101101
Text(c["textDescription"], style: TextStyle(color: Colors.white)),
102-
SizedBox(height: 50),
102+
SizedBox(height: 10),
103103
Center(
104104
child: Hero(
105105
tag: c["vName"],
@@ -108,7 +108,7 @@ class _SettingTileState extends State<SettingTile> {
108108
type: MaterialType.transparency,
109109
)),
110110
),
111-
SizedBox(height: 50),
111+
SizedBox(height: 10),
112112
Text("Settings are immediate for the current session.\nClick save to make them persistent.",
113113
textAlign: TextAlign.center, style: TextStyle(color: Colors.white)),
114114
],

pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: ss2kconfigapp
22
description: Configures the SmartSpin2k using BLE
3-
version: 1.0.15+34
3+
version: 1.0.15+35
44
# The following line prevents the package from being accidentally published to
55
# pub.dev using `flutter pub publish`. This is preferred for private packages.
66
publish_to: "none"

0 commit comments

Comments
 (0)