1 | // Copyright 2014 The Flutter Authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | import 'package:flutter/material.dart'; |
6 | |
7 | /// Flutter code example for [DecoratedSliver] |
8 | /// with clipping turned off in a parent [CustomScrollView]. |
9 | |
10 | void main() => runApp(const DecoratedSliverClipExampleApp()); |
11 | |
12 | class DecoratedSliverClipExampleApp extends StatelessWidget { |
13 | const DecoratedSliverClipExampleApp({super.key}); |
14 | |
15 | @override |
16 | Widget build(BuildContext context) { |
17 | return MaterialApp( |
18 | title: 'DecoratedSliver Clip Example' , |
19 | theme: ThemeData(colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple)), |
20 | home: const DecoratedSliverClipExample(), |
21 | ); |
22 | } |
23 | } |
24 | |
25 | class DecoratedSliverClipExample extends StatefulWidget { |
26 | const DecoratedSliverClipExample({super.key}); |
27 | |
28 | @override |
29 | State<DecoratedSliverClipExample> createState() => _DecoratedSliverClipExampleState(); |
30 | } |
31 | |
32 | class _DecoratedSliverClipExampleState extends State<DecoratedSliverClipExample> { |
33 | double _height = 225.0; |
34 | bool _isClipped = false; |
35 | |
36 | @override |
37 | Widget build(BuildContext context) { |
38 | return Scaffold( |
39 | backgroundColor: const Color(0xFF1C1C1C), |
40 | body: Column( |
41 | children: <Widget>[ |
42 | Row( |
43 | mainAxisAlignment: MainAxisAlignment.spaceEvenly, |
44 | children: <Widget>[ |
45 | Switch( |
46 | inactiveTrackColor: Colors.cyan, |
47 | activeColor: Colors.pink, |
48 | onChanged: (bool value) { |
49 | setState(() { |
50 | _isClipped = value; |
51 | }); |
52 | }, |
53 | value: _isClipped, |
54 | ), |
55 | Slider( |
56 | activeColor: Colors.pink, |
57 | inactiveColor: Colors.cyan, |
58 | onChanged: (double value) { |
59 | setState(() { |
60 | _height = value; |
61 | }); |
62 | }, |
63 | value: _height, |
64 | min: 150, |
65 | max: 225, |
66 | ), |
67 | ], |
68 | ), |
69 | const SizedBox(height: 20.0), |
70 | Stack( |
71 | children: <Widget>[ |
72 | Padding( |
73 | padding: const EdgeInsets.all(24.0), |
74 | child: SizedBox( |
75 | width: 400, |
76 | height: _height, |
77 | child: ResizableCustomScrollView(isClipped: _isClipped), |
78 | ), |
79 | ), |
80 | Positioned( |
81 | top: _height, |
82 | left: 0, |
83 | right: 0, |
84 | child: SizedBox( |
85 | height: MediaQuery.of(context).size.height - _height, |
86 | width: double.infinity, |
87 | ), |
88 | ), |
89 | ], |
90 | ), |
91 | ], |
92 | ), |
93 | ); |
94 | } |
95 | } |
96 | |
97 | class ResizableCustomScrollView extends StatelessWidget { |
98 | const ResizableCustomScrollView({super.key, required this.isClipped}); |
99 | |
100 | final bool isClipped; |
101 | |
102 | @override |
103 | Widget build(BuildContext context) { |
104 | return CustomScrollView( |
105 | // The clip behavior defaults to Clip.hardEdge if no argument is provided. |
106 | clipBehavior: isClipped ? Clip.hardEdge : Clip.none, |
107 | slivers: <Widget>[ |
108 | DecoratedSliver( |
109 | decoration: const ShapeDecoration( |
110 | color: Color(0xFF2C2C2C), |
111 | shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(6))), |
112 | shadows: <BoxShadow>[ |
113 | BoxShadow(color: Colors.cyan, offset: Offset(3, 3), blurRadius: 24), |
114 | ], |
115 | ), |
116 | sliver: SliverList.builder( |
117 | itemCount: 5, |
118 | itemBuilder: |
119 | (_, int index) => Padding( |
120 | padding: const EdgeInsets.all(8.0), |
121 | child: Row( |
122 | children: <Widget>[ |
123 | const Icon(Icons.add_box, color: Color(0xFFA8A8A8)), |
124 | Flexible( |
125 | child: Text( |
126 | 'Item $index' , |
127 | style: const TextStyle(color: Color(0xFFA8A8A8)), |
128 | ), |
129 | ), |
130 | ], |
131 | ), |
132 | ), |
133 | ), |
134 | ), |
135 | ], |
136 | ); |
137 | } |
138 | } |
139 | |