This commit is contained in:
2024-08-29 21:16:30 +02:00
commit 3d258f0e3b
36 changed files with 1852 additions and 0 deletions

47
lib/AppStateModel.dart Normal file
View File

@@ -0,0 +1,47 @@
import 'dart:async';
import 'package:bluetooth_classic/models/device.dart';
import 'package:flutter/material.dart';
class AppStateModel extends ChangeNotifier {
bool _scanning = false;
List<Device> _discoveredDevices = [];
int _deviceStatus = 0;
bool get scanning => _scanning;
List<Device> get discoveredDevices => _discoveredDevices;
int get deviceStatus => _deviceStatus;
void setScanning(bool value) {
_scanning = value;
notifyListeners();
}
void setDiscoveredDevices(List<Device> value) {
_discoveredDevices = value;
notifyListeners();
}
void addDiscoveredDevice(Device value) {
_discoveredDevices.add(value);
notifyListeners();
}
void clearDiscoveredDevices() {
_discoveredDevices.clear();
notifyListeners();
}
void setDeviceStatus(int value) {
_deviceStatus = value;
notifyListeners();
}
@override
void dispose() {
// listen?.cancel();
super.dispose();
}
}

10
lib/BluetoothUtils.dart Normal file
View File

@@ -0,0 +1,10 @@
//
// bool isAlreadyConnectedToDevice(Device device, List<Device> connectedDevices) {
// for (final connectedDevice in connectedDevices) {
// if (connectedDevice.address == device.address) {
// return true;
// }
// }
// return false;
// }

View File

@@ -0,0 +1,18 @@
import 'package:flutter/material.dart';
void showAlreadyConnectedDialog(BuildContext context) {
showDialog(context: context, builder: (context) {
return AlertDialog(
title: const Text('Already connected'),
content: const Text('This device is already connected'),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text('OK'))
],
);
});
}

View File

@@ -0,0 +1,25 @@
import 'package:bluetooth_classic/bluetooth_classic.dart';
import 'package:bluetooth_classic/models/device.dart';
class Custombluetoothservice extends BluetoothClassic {
// @override
// Stream<Uint8List> onDeviceDataReceived() {
// return _onDeviceDataReceived ??=
// super.onDeviceDataReceived().asBroadcastStream();
// }
// Stream<Uint8List>? _onDeviceDataReceived;
@override
Stream<Device> onDeviceDiscovered() =>
_onDeviceDiscovered ??= super.onDeviceDiscovered().asBroadcastStream();
Stream<Device>? _onDeviceDiscovered;
@override
Stream<int> onDeviceStatusChanged() =>
_onDeviceStatusChanged ??=
super.onDeviceStatusChanged().asBroadcastStream();
Stream<int>? _onDeviceStatusChanged;
}

119
lib/MainControlScreen.dart Normal file
View File

@@ -0,0 +1,119 @@
import 'package:flutter/material.dart';
import 'package:flutter_colorpicker/flutter_colorpicker.dart';
import 'package:provider/provider.dart';
import 'package:xapk_installer/AppStateModel.dart';
import 'package:xapk_installer/connectPage.dart';
import 'package:xapk_installer/pickers/block_picker.dart';
class Maincontrolscreen extends StatefulWidget {
const Maincontrolscreen({super.key});
@override
State<Maincontrolscreen> createState() => _MaincontrolscreenState();
}
class _MaincontrolscreenState extends State<Maincontrolscreen> {
// final _bluetoothClassicPlugin = BluetoothClassic();
List<List<Color>> gridColors = List.generate(
5,
(i) => List.generate(5, (j) => Colors.grey), // Initialize with grey color
);
// Method to toggle the color of a button
void toggleButtonColor(int i, int j) {
setState(() {
gridColors[i][j] = currentColor;
});
}
bool isConnected = false;
Color currentColor = Colors.grey;
// Widget buildStatusIcon(){
// if(Provider.of<AppStateModel>(context).name == Device.connected){
// return Icon(Icons.bluetooth_connected);
// }
// else if( == Device.connecting){
// return Icon(Icons.bluetooth_searching);
// }
// else{
// return Icon(Icons.bluetooth_disabled);
// }
// }
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Connect Page'),
actions: [
IconButton(onPressed: (){
Navigator.push(context, MaterialPageRoute(builder: (context) => ConnectPage()));
}, icon: Icon(Icons.bluetooth)),
IconButton(onPressed: (){
}, icon: Icon(Icons.upload)),
],
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: GridView.builder(
shrinkWrap: true,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 5,
childAspectRatio: 1.0,
crossAxisSpacing: 8.0,
mainAxisSpacing: 8.0,
),
itemCount: 25, // 5x5 grid
itemBuilder: (context, index) {
int row = index ~/ 5;
int col = index % 5;
return GestureDetector(
onTap: () => toggleButtonColor(row, col),
child: Container(
color: gridColors[row][col],
),
);
},
),
),
SizedBox(height: 15),
// ColorPicker(
// hexInputBar: false,
// pickerAreaBorderRadius: const BorderRadius.all(
// Radius.circular(10)),
// portraitOnly: true,
// pickerColor: currentColor,
// onColorChanged: (color) {
// currentColor = color;
// },
// enableAlpha: false,
// colorPickerWidth: 100,
// displayThumbColor: true,
//
//
// )
Center(
child: BlockPicker(
pickerColor: currentColor,
onColorChanged: (color) {
currentColor = color;
},
),
),
],
),
),
);
}
}

34
lib/NoDeviceScreen.dart Normal file
View File

@@ -0,0 +1,34 @@
import 'package:flutter/material.dart';
class NoDevicesScreen extends StatelessWidget {
const NoDevicesScreen({super.key, required this.onScanPressed});
final VoidCallback onScanPressed;
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(
Icons.bluetooth_disabled,
size: 100,
color: Colors.grey,
),
const SizedBox(height: 10),
const Text('No devices found', style: TextStyle(fontSize: 20)),
const SizedBox(height: 10),
// Button to scan for devices
ElevatedButton(
onPressed: onScanPressed,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: const Text('Scan for devices', style: TextStyle(fontSize: 15)),
),
),
],
),
);
}
}

368
lib/connectPage.dart Normal file
View File

@@ -0,0 +1,368 @@
import 'dart:async';
import 'package:bluetooth_classic/bluetooth_classic.dart';
import 'package:bluetooth_classic/models/device.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:provider/provider.dart';
import 'package:xapk_installer/AppStateModel.dart';
import 'package:xapk_installer/BluetoothUtils.dart';
import 'package:xapk_installer/ConnectionScreenDialogs.dart';
import 'package:xapk_installer/CustomBluetoothService.dart';
import 'NoDeviceScreen.dart';
class ConnectPage extends StatefulWidget {
const ConnectPage({super.key});
@override
State<ConnectPage> createState() => _ConnectPageState();
}
class _ConnectPageState extends State<ConnectPage> {
final _bluetoothClassicPlugin = Custombluetoothservice();
//a bool to hide the no devices found screen when the user presses the scan button
bool _hideNoDevicesScreen = false;
bool _scanning = false;
Icon _statusIcon = const Icon(Icons.restart_alt);
int _deviceStatus = Device.disconnected;
Device _connectedDevice = Device(name: 'Unknown', address: 'Unknown');
StreamSubscription? deviceListen;
StreamSubscription? deviceChangeListen;
//Init
@override
void initState() {
super.initState();
_bluetoothClassicPlugin.initPermissions();
_bluetoothClassicPlugin.onDeviceStatusChanged().listen((event) {
setState(() {
Provider.of<AppStateModel>(context, listen: false).setDeviceStatus(event);
_deviceStatus = event;
});
});
_bluetoothClassicPlugin.onDeviceDiscovered().listen(
(event) {
if (kDebugMode) {
print('Device discovered: ${event.name}');
}
if (_scanning) {
Provider.of<AppStateModel>(context, listen: false)
.addDiscoveredDevice(event);
//Sort list put Unknowns at the end
Provider.of<AppStateModel>(context, listen: false)
.discoveredDevices
.sort((a, b) {
if (a.name == null) {
return 1;
}
if (b.name == null) {
return -1;
}
return a.name!.compareTo(b.name!);
});
}
},
);
}
//Dispose
@override
void dispose() {
super.dispose();
// Provider.of<AppStateModel>(context, listen: false).listen?.cancel();
}
Future<void> _scan() async {
if (_scanning) {
await _bluetoothClassicPlugin.stopScan();
if (kDebugMode) {
print('Scanning stopped');
}
setState(() {
_scanning = false;
_statusIcon = const Icon(Icons.restart_alt);
});
} else {
setState(() {
Provider.of<AppStateModel>(context, listen: false).clearDiscoveredDevices();
_hideNoDevicesScreen = true;
_statusIcon = const Icon(Icons.cancel);
});
await _bluetoothClassicPlugin.startScan();
if (kDebugMode) {
print('Scanning started');
}
setState(() {
_scanning = true;
});
}
}
Future<void> _stopScan() async {
await _bluetoothClassicPlugin.stopScan();
if (kDebugMode) {
print('Scanning stopped');
}
await _bluetoothClassicPlugin.disconnect();
setState(() {
_scanning = false;
_statusIcon = const Icon(Icons.restart_alt);
});
}
Future<bool?> _showConnectConfirmDialog(
BuildContext context, String deviceName, String deviceAddress) {
return showDialog<bool?>(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('Connect'),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Text('Do you want to connect to this device?'),
Container(height: 10),
Text(deviceName,
style: const TextStyle(
fontWeight: FontWeight.bold,
decoration: TextDecoration.underline,
fontSize: 20)),
Text(deviceAddress, style: const TextStyle(fontSize: 12)),
],
),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop(false);
},
child: const Text('No')),
TextButton(
onPressed: () {
Navigator.of(context).pop(true);
},
child: const Text('Yes')),
],
);
});
}
Future<void> _connect(Device device) async {
final connect = await _showConnectConfirmDialog(
context, device.name ?? 'Unknown', device.address);
if (connect == null || !connect) {
return;
}
bool connected = false;
bool error = false;
List<Device> alreadyConnectedDevices = [];
try {
alreadyConnectedDevices =
await _bluetoothClassicPlugin.getPairedDevices();
} catch (e) {
error = true;
}
if(error){
if (context.mounted) {
if (kDebugMode) {
print('Failed to get paired devices');
}
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('Failed to get paired devices'),
content: const Text('Failed to get paired devices'),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text('OK'))
],
);
});
return;
}
}
// //If the device is already connected, tell the user
// if (alreadyConnectedDevices
// .any((element) => element.address == device.address)) {
// if (context.mounted) {
// if (kDebugMode) {
// print('Device already connected');
// }
// showAlreadyConnectedDialog(context);
// return;
// }
// }
if(_deviceStatus == Device.connected){
if (context.mounted) {
if (kDebugMode) {
print('Device already connected');
}
showAlreadyConnectedDialog(context);
return;
}
}
try {
connected = await _bluetoothClassicPlugin.connect(
device.address, "00001101-0000-1000-8000-00805f9b34fb");
} catch (e) {
error = true;
}
if (error || !connected) {
if (context.mounted) {
if (kDebugMode) {
print('Failed to connect');
}
}
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('Failed to connect'),
content: const Text('Failed to connect to the device'),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text('OK'))
],
);
});
return;
}
setState(() {
_statusIcon = const Icon(Icons.restart_alt);
_connectedDevice = device;
});
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('Connected'),
content: const Text('You are now connected to the device'),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text('OK'))
],
);
});
await _bluetoothClassicPlugin.write("setPix 1 1 255 0 0\n"); //TODO: remove this
}
Future<void> _disconnect() async {
await _bluetoothClassicPlugin.disconnect();
setState(() {
_statusIcon = const Icon(Icons.restart_alt);
_connectedDevice = Device(name: 'Unknown', address: 'Unknown');
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Connect Page'),
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () {
Navigator.of(context).pop();
},
),
actions: [
IconButton(
icon: _statusIcon,
onPressed: () {
_scan();
},
),
IconButton(
onPressed: () {
_stopScan();
Provider.of<AppStateModel>(context, listen: false)
.clearDiscoveredDevices();
},
icon: const Icon(Icons.star_purple500_outlined))
],
),
body: !_hideNoDevicesScreen
? NoDevicesScreen(onScanPressed: () {
setState(() {
_hideNoDevicesScreen = true;
});
_scan();
})
: Padding(
padding: const EdgeInsets.all(4.0),
child: Consumer<AppStateModel>(
builder: (context, appstate, child) {
final List<Device> _discoveredDevices =
appstate.discoveredDevices;
return ListView.builder(itemBuilder: (context, index) {
if (index >= _discoveredDevices.length) {
return null;
}
return ListTile(
title: Text(_discoveredDevices[index].name ?? 'Unknown', style: TextStyle(
fontWeight: _discoveredDevices[index].name == _connectedDevice.name ? FontWeight.bold : FontWeight.normal,
color: _discoveredDevices[index].name == _connectedDevice.name ? Colors.green : Colors.white
),),
subtitle: Text(_discoveredDevices[index].address),
leading: _discoveredDevices[index].name == null ? const Icon(Icons.question_mark) : const Icon(
Icons.bluetooth,
color: Colors.blueAccent,
),
style: ListTileStyle.list,
onTap: () async {
if(_discoveredDevices[index].name == _connectedDevice.name){
await _disconnect();
} else {
await _connect(_discoveredDevices[index]);
}
},
onLongPress: () async {
// if (isAlreadyConnectedToDevice(_discoveredDevices[index],
// await _bluetoothClassicPlugin.getPairedDevices())) {
// _bluetoothClassicPlugin.disconnect();
// }
Fluttertoast.showToast(
msg: Provider.of<AppStateModel>(context, listen: false).deviceStatus.toString(),
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0
);
},
);
});
}
),
),
);
}
}

39
lib/main.dart Normal file
View File

@@ -0,0 +1,39 @@
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:provider/provider.dart';
import 'package:xapk_installer/MainControlScreen.dart';
import 'package:xapk_installer/connectPage.dart';
import 'AppStateModel.dart';
void main() {
runApp(ChangeNotifierProvider(
create: (context) => AppStateModel(),
child: const MyApp(),
));
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
darkTheme: ThemeData.dark(),
debugShowCheckedModeBanner: false,
home: Maincontrolscreen(),
);
}
}

View File

@@ -0,0 +1,419 @@
import 'package:flutter/material.dart';
import 'package:flutter_colorpicker/flutter_colorpicker.dart';
const List<Color> colors = [
Colors.red,
Colors.pink,
Colors.purple,
Colors.deepPurple,
Colors.indigo,
Colors.blue,
Colors.lightBlue,
Colors.cyan,
Colors.teal,
Colors.green,
Colors.lightGreen,
Colors.lime,
Colors.yellow,
Colors.amber,
Colors.orange,
Colors.deepOrange,
Colors.brown,
Colors.grey,
Colors.blueGrey,
Colors.black,
];
class BlockColorPickerExample extends StatefulWidget {
const BlockColorPickerExample({
Key? key,
required this.pickerColor,
required this.onColorChanged,
required this.pickerColors,
required this.onColorsChanged,
required this.colorHistory,
}) : super(key: key);
final Color pickerColor;
final ValueChanged<Color> onColorChanged;
final List<Color> pickerColors;
final ValueChanged<List<Color>> onColorsChanged;
final List<Color> colorHistory;
@override
State<BlockColorPickerExample> createState() => _BlockColorPickerExampleState();
}
class _BlockColorPickerExampleState extends State<BlockColorPickerExample> {
int _portraitCrossAxisCount = 4;
int _landscapeCrossAxisCount = 5;
double _borderRadius = 30;
double _blurRadius = 5;
double _iconSize = 24;
Widget pickerLayoutBuilder(BuildContext context, List<Color> colors, PickerItem child) {
Orientation orientation = MediaQuery.of(context).orientation;
return SizedBox(
width: 300,
height: orientation == Orientation.portrait ? 360 : 240,
child: GridView.count(
crossAxisCount: orientation == Orientation.portrait ? _portraitCrossAxisCount : _landscapeCrossAxisCount,
crossAxisSpacing: 5,
mainAxisSpacing: 5,
children: [for (Color color in colors) child(color)],
),
);
}
Widget pickerItemBuilder(Color color, bool isCurrentColor, void Function() changeColor) {
return Container(
margin: const EdgeInsets.all(8),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(_borderRadius),
color: color,
boxShadow: [BoxShadow(color: color.withOpacity(0.8), offset: const Offset(1, 2), blurRadius: _blurRadius)],
),
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: changeColor,
borderRadius: BorderRadius.circular(_borderRadius),
child: AnimatedOpacity(
duration: const Duration(milliseconds: 250),
opacity: isCurrentColor ? 1 : 0,
child: Icon(
Icons.done,
size: _iconSize,
color: useWhiteForeground(color) ? Colors.white : Colors.black,
),
),
),
),
);
}
@override
Widget build(BuildContext context) {
return ListView(
children: [
const SizedBox(height: 20),
Center(
child: ElevatedButton(
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
titlePadding: const EdgeInsets.all(0),
contentPadding: const EdgeInsets.all(25),
content: SingleChildScrollView(
child: Text(
'''
Widget pickerLayoutBuilder(BuildContext context, List<Color> colors, PickerItem child) {
Orientation orientation = MediaQuery.of(context).orientation;
return SizedBox(
width: 300,
height: orientation == Orientation.portrait ? 360 : 240,
child: GridView.count(
crossAxisCount: orientation == Orientation.portrait ? $_portraitCrossAxisCount : $_landscapeCrossAxisCount,
crossAxisSpacing: 5,
mainAxisSpacing: 5,
children: [for (Color color in colors) child(color)],
),
);
}
''',
),
),
);
},
);
},
child: Icon(Icons.code, color: useWhiteForeground(widget.pickerColor) ? Colors.white : Colors.black),
style: ElevatedButton.styleFrom(
backgroundColor: widget.pickerColor,
shadowColor: widget.pickerColor.withOpacity(1),
elevation: 10,
),
),
),
ListTile(
title: const Text('Portrait Cross Axis Count'),
subtitle: Text(_portraitCrossAxisCount.toString()),
trailing: SizedBox(
width: 200,
child: Slider(
value: _portraitCrossAxisCount.toDouble(),
min: 1,
max: 10,
divisions: 9,
label: _portraitCrossAxisCount.toString(),
onChanged: (double value) => setState(() => _portraitCrossAxisCount = value.round()),
),
),
),
ListTile(
title: const Text('Landscape Cross Axis Count'),
subtitle: Text(_landscapeCrossAxisCount.toString()),
trailing: SizedBox(
width: 200,
child: Slider(
value: _landscapeCrossAxisCount.toDouble(),
min: 1,
max: 10,
divisions: 9,
label: _landscapeCrossAxisCount.toString(),
onChanged: (double value) => setState(() => _landscapeCrossAxisCount = value.round()),
),
),
),
const Divider(),
const SizedBox(height: 20),
Center(
child: ElevatedButton(
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
titlePadding: const EdgeInsets.all(0),
contentPadding: const EdgeInsets.all(25),
content: SingleChildScrollView(
child: Text(
'''
Widget pickerItemBuilder(Color color, bool isCurrentColor, void Function() changeColor) {
return Container(
margin: const EdgeInsets.all(8),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular($_borderRadius),
color: color,
boxShadow: [BoxShadow(color: color.withOpacity(0.8), offset: const Offset(1, 2), blurRadius: $_blurRadius)],
),
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: changeColor,
borderRadius: BorderRadius.circular(_borderRadius),
child: AnimatedOpacity(
duration: const Duration(milliseconds: 250),
opacity: isCurrentColor ? 1 : 0,
child: Icon(
Icons.done,
size: $_iconSize,
color: useWhiteForeground(color) ? Colors.white : Colors.black,
),
),
),
),
);
}
''',
),
),
);
},
);
},
child: Icon(Icons.code, color: useWhiteForeground(widget.pickerColor) ? Colors.white : Colors.black),
style: ElevatedButton.styleFrom(
backgroundColor: widget.pickerColor,
shadowColor: widget.pickerColor.withOpacity(1),
elevation: 10,
),
),
),
ListTile(
title: const Text('Border Radius'),
subtitle: Text(_borderRadius.toString()),
trailing: SizedBox(
width: 200,
child: Slider(
value: _borderRadius,
min: 0,
max: 30,
divisions: 30,
label: _borderRadius.toString(),
onChanged: (double value) => setState(() => _borderRadius = value.round().toDouble()),
),
),
),
ListTile(
title: const Text('Blur Radius'),
subtitle: Text(_blurRadius.toString()),
trailing: SizedBox(
width: 200,
child: Slider(
value: _blurRadius,
min: 0,
max: 5,
divisions: 5,
label: _blurRadius.toString(),
onChanged: (double value) => setState(() => _blurRadius = value.round().toDouble()),
),
),
),
ListTile(
title: const Text('Icon Size'),
subtitle: Text(_iconSize.toString()),
trailing: SizedBox(
width: 200,
child: Slider(
value: _iconSize,
min: 1,
max: 50,
divisions: 49,
label: _iconSize.toString(),
onChanged: (double value) => setState(() => _iconSize = value.round().toDouble()),
),
),
),
const Divider(),
const SizedBox(height: 20),
Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Select a color'),
content: SingleChildScrollView(
child: BlockPicker(
pickerColor: widget.pickerColor,
onColorChanged: widget.onColorChanged,
availableColors: widget.colorHistory.isNotEmpty ? widget.colorHistory : colors,
layoutBuilder: pickerLayoutBuilder,
itemBuilder: pickerItemBuilder,
),
),
);
},
);
},
child: Text(
'Blocky Color Picker',
style: TextStyle(color: useWhiteForeground(widget.pickerColor) ? Colors.white : Colors.black),
),
style: ElevatedButton.styleFrom(
backgroundColor: widget.pickerColor,
shadowColor: widget.pickerColor.withOpacity(1),
elevation: 10,
),
),
const SizedBox(width: 20),
ElevatedButton(
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) {
return const AlertDialog(
titlePadding: EdgeInsets.all(0),
contentPadding: EdgeInsets.all(25),
content: SingleChildScrollView(
child: Text(
'''
BlockPicker(
pickerColor: color,
onColorChanged: changeColor,
availableColors: colors,
layoutBuilder: pickerLayoutBuilder,
itemBuilder: pickerItemBuilder,
)
''',
),
),
);
},
);
},
child: Icon(Icons.code, color: useWhiteForeground(widget.pickerColor) ? Colors.white : Colors.black),
style: ElevatedButton.styleFrom(
backgroundColor: widget.pickerColor,
shadowColor: widget.pickerColor.withOpacity(1),
elevation: 10,
),
),
],
),
const SizedBox(height: 20),
const Divider(),
const SizedBox(height: 20),
Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Select colors'),
content: SingleChildScrollView(
child: MultipleChoiceBlockPicker(
pickerColors: widget.pickerColors,
onColorsChanged: widget.onColorsChanged,
availableColors: widget.colorHistory.isNotEmpty ? widget.colorHistory : colors,
layoutBuilder: pickerLayoutBuilder,
itemBuilder: pickerItemBuilder,
),
),
);
},
);
},
child: Text(
'Multiple selection Blocky Color Picker',
style: TextStyle(color: useWhiteForeground(widget.pickerColor) ? Colors.white : Colors.black),
),
style: ElevatedButton.styleFrom(
backgroundColor: widget.pickerColor,
shadowColor: widget.pickerColor.withOpacity(1),
elevation: 10,
),
),
const SizedBox(width: 20),
ElevatedButton(
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) {
return const AlertDialog(
titlePadding: EdgeInsets.all(0),
contentPadding: EdgeInsets.all(25),
content: SingleChildScrollView(
child: Text(
'''
MultipleChoiceBlockPicker(
pickerColors: colors,
onColorsChanged: changeColors,
availableColors: colors,
layoutBuilder: pickerLayoutBuilder,
itemBuilder: pickerItemBuilder,
)
''',
),
),
);
},
);
},
child: Icon(Icons.code, color: useWhiteForeground(widget.pickerColor) ? Colors.white : Colors.black),
style: ElevatedButton.styleFrom(
backgroundColor: widget.pickerColor,
shadowColor: widget.pickerColor.withOpacity(1),
elevation: 10,
),
),
],
),
const SizedBox(height: 80),
],
);
}
}

0
lib/widgets.dart Normal file
View File