custom_ruler 1.0.0
custom_ruler: ^1.0.0 copied to clipboard
A highly customizable ruler/scale widget for Flutter with support for horizontal and vertical orientations, snapping, and custom styling.
import 'package:flutter/material.dart';
import 'package:custom_ruler/custom_ruler.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Custom Ruler Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
useMaterial3: true,
),
home: const RulerDemoPage(),
);
}
}
class RulerDemoPage extends StatefulWidget {
const RulerDemoPage({super.key});
@override
State<RulerDemoPage> createState() => _RulerDemoPageState();
}
class _RulerDemoPageState extends State<RulerDemoPage> {
double _weightKg = 70.0;
int _heightCm = 175;
final GlobalKey<CustomRulerState> _weightRulerKey = GlobalKey();
final GlobalKey<CustomRulerState> _heightRulerKey = GlobalKey();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Custom Ruler Demo'),
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
),
body: SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Weight Picker Section
_buildSectionTitle('Weight Picker (Horizontal)'),
const SizedBox(height: 8),
Center(
child: Text(
'${_weightKg.toStringAsFixed(1)} kg',
style: const TextStyle(
fontSize: 48,
fontWeight: FontWeight.bold,
),
),
),
const SizedBox(height: 16),
SizedBox(
height: 120,
child: CustomRuler(
key: _weightRulerKey,
orientation: RulerOrientation.horizontal,
minRange: 0,
maxRange: 200,
lineSpacing: 0.1,
pixelSpacing: 9,
initialValue: _weightKg,
decimalPlaces: 0,
rulerHeight: 120,
pointerLength: 120,
pointerThickness: 2,
pointerColor: Colors.blue,
barAlignment: BarAlignment.end,
majorBarColor: Colors.grey.shade600,
mediumBarColor: Colors.grey.shade400,
minorBarColor: Colors.grey.shade300,
labelColor: Colors.grey.shade500,
onChange: (value) {
setState(() => _weightKg = value);
},
),
),
const SizedBox(height: 8),
Center(
child: ElevatedButton(
onPressed: () {
_weightRulerKey.currentState?.scrollToValue(70.0);
},
child: const Text('Reset to 70 kg'),
),
),
const SizedBox(height: 32),
const Divider(),
const SizedBox(height: 32),
// Height Picker Section
_buildSectionTitle('Height Picker (Vertical)'),
const SizedBox(height: 16),
Row(
children: [
Expanded(
child: Column(
children: [
Text(
'$_heightCm',
style: const TextStyle(
fontSize: 64,
fontWeight: FontWeight.bold,
),
),
const Text(
'cm',
style: TextStyle(fontSize: 24, color: Colors.grey),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () {
_heightRulerKey.currentState?.scrollToValue(175);
},
child: const Text('Reset'),
),
],
),
),
SizedBox(
width: 120,
height: 300,
child: CustomRuler(
key: _heightRulerKey,
orientation: RulerOrientation.vertical,
barAlignment: BarAlignment.end,
alignmentPosition: AlignmentPosition.right,
minRange: 50,
maxRange: 250,
lineSpacing: 1,
pixelSpacing: 12,
initialValue: _heightCm.toDouble(),
rulerHeight: 100,
decimalPlaces: 0,
majorInterval: 10,
mediumInterval: 5,
majorBarColor: Colors.grey.shade600,
mediumBarColor: Colors.grey.shade400,
minorBarColor: Colors.grey.shade300,
labelColor: Colors.grey.shade500,
pointerColor: Colors.green,
onChange: (value) {
setState(() => _heightCm = value.round());
},
),
),
],
),
const SizedBox(height: 32),
const Divider(),
const SizedBox(height: 32),
// Custom Styled Ruler
_buildSectionTitle('Custom Styled Ruler'),
const SizedBox(height: 16),
SizedBox(
height: 100,
child: CustomRuler(
orientation: RulerOrientation.horizontal,
minRange: 0,
maxRange: 10,
lineSpacing: 0.1,
pixelSpacing: 20,
initialValue: 5,
decimalPlaces: 1,
rulerHeight: 100,
pointerWidget: Container(
width: 3,
height: 80,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(2),
gradient: const LinearGradient(
colors: [Colors.purple, Colors.blue],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
),
),
),
barAlignment: BarAlignment.center,
majorBarColor: Colors.purple,
mediumBarColor: Colors.purple.shade200,
minorBarColor: Colors.purple.shade100,
labelColor: Colors.purple,
labelStyle: const TextStyle(
color: Colors.purple,
fontSize: 14,
fontWeight: FontWeight.bold,
),
onChange: (value) {
// Handle change
},
),
),
],
),
),
);
}
Widget _buildSectionTitle(String title) {
return Text(
title,
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
);
}
}