Anonymous
Suchtextfeld Animation in Flutter
Post
by Anonymous » 14 Sep 2025, 07:50
Ich möchte diese Animation und genaue Schatten für die Taste erreichen: -
. Lineare Gradientenfarbe, aber sie sieht nicht aus wie das GIF.
Code: Select all
import 'package:device_preview/device_preview.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
statusBarIconBrightness: Brightness.dark,
statusBarBrightness: Brightness.light,
));
runApp(DevicePreview(
enabled: true,
builder: (context) {
return const MyApp();
}));
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return ScreenUtilInit(
designSize: const Size(375, 812),
minTextAdapt: false,
splitScreenMode: false,
builder: (context, child) {
return MaterialApp(
themeMode: ThemeMode.light,
debugShowCheckedModeBanner: false,
builder: (context, child) {
return MediaQuery(
data: MediaQuery.of(context).copyWith(
textScaler: TextScaler.noScaling,
),
child: child!,
);
},
home: MyHomePage(),
);
});
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State createState() => _MyHomePageState();
}
class _MyHomePageState extends State {
@override
Widget build(BuildContext context) {
return RollingSearchBar();
}
}
class RollingSearchBar extends StatefulWidget {
const RollingSearchBar({super.key});
@override
State createState() => _RollingSearchBarState();
}
class _RollingSearchBarState extends State
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation _widthAnim;
late Animation _rotationAnim;
late Animation _iconShiftAnim;
final TextEditingController _textController = TextEditingController();
bool _isExpanded = false;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 600),
);
_widthAnim = Tween(begin: 56, end: 300).animate(
CurvedAnimation(parent: _controller, curve: Curves.easeInOut),
);
_rotationAnim = Tween(begin: 0, end: 2.0).animate(
CurvedAnimation(parent: _controller, curve: Curves.easeInOut),
); // 2.0 = 360° roll
_iconShiftAnim = Tween(begin: 0, end: -100).animate(
CurvedAnimation(parent: _controller, curve: Curves.easeInOut),
);
}
void _toggle() {
if (_isExpanded) {
_controller.reverse();
} else {
_controller.forward();
}
setState(() => _isExpanded = !_isExpanded);
}
@override
void dispose() {
_controller.dispose();
_textController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[200],
body: Center(
child: AnimatedBuilder(
animation: _controller,
builder: (context, child) {
return Container(
width: _widthAnim.value,
height: 56,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(28),
boxShadow: const [
BoxShadow(
color: Colors.black26,
offset: Offset(0, 4),
blurRadius: 8,
),
],
),
child: Stack(
alignment: Alignment.centerLeft,
children: [
// Rolling search icon
Transform.translate(
offset: Offset(_iconShiftAnim.value, 0),
child: Transform.rotate(
angle: _rotationAnim.value * 3.14159,
child: IconButton(
icon: const Icon(Icons.search, color: Colors.black54),
onPressed: _toggle,
),
),
),
// TextField (fades in)
Opacity(
opacity: _isExpanded ? 1 : 0,
child: Padding(
padding: const EdgeInsets.only(left: 56, right: 48),
child: TextField(
controller: _textController,
autofocus: _isExpanded,
style: const TextStyle(fontSize: 16),
decoration: const InputDecoration(
hintText: "Search...",
border: InputBorder.none,
isCollapsed: true,
),
),
),
),
// Close button
Align(
alignment: Alignment.centerRight,
child: AnimatedOpacity(
opacity: _isExpanded ? 1 : 0,
duration: const Duration(milliseconds: 300),
child: IconButton(
icon: const Icon(Icons.close, color: Colors.black54),
onPressed: _toggle,
),
),
),
],
),
);
},
),
),
);
}
}
1757829014
Anonymous
[url=viewtopic.php?t=14917]Ich möchte[/url] diese Animation und genaue Schatten für die Taste erreichen: - . Lineare Gradientenfarbe, aber sie sieht nicht aus wie das GIF.[code]import 'package:device_preview/device_preview.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; void main() { WidgetsFlutterBinding.ensureInitialized(); SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle( statusBarColor: Colors.transparent, statusBarIconBrightness: Brightness.dark, statusBarBrightness: Brightness.light, )); runApp(DevicePreview( enabled: true, builder: (context) { return const MyApp(); })); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return ScreenUtilInit( designSize: const Size(375, 812), minTextAdapt: false, splitScreenMode: false, builder: (context, child) { return MaterialApp( themeMode: ThemeMode.light, debugShowCheckedModeBanner: false, builder: (context, child) { return MediaQuery( data: MediaQuery.of(context).copyWith( textScaler: TextScaler.noScaling, ), child: child!, ); }, home: MyHomePage(), ); }); } } class MyHomePage extends StatefulWidget { const MyHomePage({super.key}); @override State createState() => _MyHomePageState(); } class _MyHomePageState extends State { @override Widget build(BuildContext context) { return RollingSearchBar(); } } class RollingSearchBar extends StatefulWidget { const RollingSearchBar({super.key}); @override State createState() => _RollingSearchBarState(); } class _RollingSearchBarState extends State with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation _widthAnim; late Animation _rotationAnim; late Animation _iconShiftAnim; final TextEditingController _textController = TextEditingController(); bool _isExpanded = false; @override void initState() { super.initState(); _controller = AnimationController( vsync: this, duration: const Duration(milliseconds: 600), ); _widthAnim = Tween(begin: 56, end: 300).animate( CurvedAnimation(parent: _controller, curve: Curves.easeInOut), ); _rotationAnim = Tween(begin: 0, end: 2.0).animate( CurvedAnimation(parent: _controller, curve: Curves.easeInOut), ); // 2.0 = 360° roll _iconShiftAnim = Tween(begin: 0, end: -100).animate( CurvedAnimation(parent: _controller, curve: Curves.easeInOut), ); } void _toggle() { if (_isExpanded) { _controller.reverse(); } else { _controller.forward(); } setState(() => _isExpanded = !_isExpanded); } @override void dispose() { _controller.dispose(); _textController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.grey[200], body: Center( child: AnimatedBuilder( animation: _controller, builder: (context, child) { return Container( width: _widthAnim.value, height: 56, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(28), boxShadow: const [ BoxShadow( color: Colors.black26, offset: Offset(0, 4), blurRadius: 8, ), ], ), child: Stack( alignment: Alignment.centerLeft, children: [ // Rolling search icon Transform.translate( offset: Offset(_iconShiftAnim.value, 0), child: Transform.rotate( angle: _rotationAnim.value * 3.14159, child: IconButton( icon: const Icon(Icons.search, color: Colors.black54), onPressed: _toggle, ), ), ), // TextField (fades in) Opacity( opacity: _isExpanded ? 1 : 0, child: Padding( padding: const EdgeInsets.only(left: 56, right: 48), child: TextField( controller: _textController, autofocus: _isExpanded, style: const TextStyle(fontSize: 16), decoration: const InputDecoration( hintText: "Search...", border: InputBorder.none, isCollapsed: true, ), ), ), ), // Close button Align( alignment: Alignment.centerRight, child: AnimatedOpacity( opacity: _isExpanded ? 1 : 0, duration: const Duration(milliseconds: 300), child: IconButton( icon: const Icon(Icons.close, color: Colors.black54), onPressed: _toggle, ), ), ), ], ), ); }, ), ), ); } } [/code]