1
0
mirror of https://github.com/h7x4/Jisho-Study-Tool.git synced 2024-12-21 13:37:29 +01:00

Animate kanji search UI

This commit is contained in:
Oystein Kristoffer Tveit 2021-07-19 01:47:12 +02:00
parent 25e270ec1d
commit 99912333ac
6 changed files with 158 additions and 44 deletions

View File

@ -15,6 +15,7 @@ class KanjiGrid extends StatelessWidget {
horizontal: 40.0, horizontal: 40.0,
), ),
child: GridView.count( child: GridView.count(
shrinkWrap: true,
crossAxisCount: 3, crossAxisCount: 3,
mainAxisSpacing: 10.0, mainAxisSpacing: 10.0,
crossAxisSpacing: 10.0, crossAxisSpacing: 10.0,

View File

@ -4,6 +4,9 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:jisho_study_tool/bloc/kanji/kanji_bloc.dart'; import 'package:jisho_study_tool/bloc/kanji/kanji_bloc.dart';
class KanjiSearchBar extends StatefulWidget { class KanjiSearchBar extends StatefulWidget {
const KanjiSearchBar();
@override @override
_KanjiSearchBarState createState() => new _KanjiSearchBarState(); _KanjiSearchBarState createState() => new _KanjiSearchBarState();
} }
@ -18,7 +21,7 @@ class _KanjiSearchBarState extends State<KanjiSearchBar> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
focus.addListener(_onFocusChange); // focus.addListener(_onFocusChange);
} }
void _getKanjiSuggestions(String text) => void _getKanjiSuggestions(String text) =>
@ -26,19 +29,6 @@ class _KanjiSearchBarState extends State<KanjiSearchBar> {
void updateSuggestions() => _getKanjiSuggestions(textController.text); void updateSuggestions() => _getKanjiSuggestions(textController.text);
void _onFocusChange() {
debugPrint('TextField Focus Changed: ${focus.hasFocus.toString()}');
setState(() {
button = focus.hasFocus ? TextFieldButton.clear : TextFieldButton.paste;
});
if (focus.hasFocus)
updateSuggestions();
else
FocusScope.of(context).unfocus();
}
void _clearText() { void _clearText() {
textController.text = ''; textController.text = '';
updateSuggestions(); updateSuggestions();
@ -63,27 +53,23 @@ class _KanjiSearchBarState extends State<KanjiSearchBar> {
); );
return TextField( return TextField(
focusNode: focus,
controller: textController, controller: textController,
onChanged: (text) => _getKanjiSuggestions(text), onChanged: (text) => _getKanjiSuggestions(text),
onSubmitted: (text) => onSubmitted: (text) => {},
BlocProvider.of<KanjiBloc>(context).add(GetKanji(text)), // BlocProvider.of<KanjiBloc>(context).add(GetKanji(text)),
decoration: new InputDecoration( decoration: new InputDecoration(
prefixIcon: Icon(Icons.search), prefixIcon: Icon(Icons.search),
hintText: 'Search', hintText: 'Search',
fillColor: Colors.white, fillColor: Colors.white,
filled: true, filled: true,
border: OutlineInputBorder( border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0), borderRadius: BorderRadius.circular(10.0),
), ),
contentPadding: EdgeInsets.symmetric(vertical: 10.0),
isDense: false, isDense: false,
suffixIcon: (button == TextFieldButton.clear) ? clearButton : pasteButton, suffixIcon: (button == TextFieldButton.clear) ? clearButton : pasteButton,
), ),
style: TextStyle(
fontSize: 14.0,
),
); );
} }
} }

View File

@ -0,0 +1,52 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:jisho_study_tool/bloc/kanji/kanji_bloc.dart';
//TODO: Make buttons have an effect
class KanjiSearchOptionsBar extends StatelessWidget {
const KanjiSearchOptionsBar({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
_IconButton(
icon: Text(
"",
style: TextStyle(
fontWeight: FontWeight.w700,
fontSize: 18,
),
),
onPressed: () =>
BlocProvider.of<KanjiBloc>(context).add(ReturnToInitialState()),
),
_IconButton(
icon: Icon(Icons.category),
onPressed: () =>
BlocProvider.of<KanjiBloc>(context).add(ReturnToInitialState()),
),
_IconButton(
icon: Icon(Icons.mode),
onPressed: () =>
BlocProvider.of<KanjiBloc>(context).add(ReturnToInitialState()),
),
],
),
);
}
}
class _IconButton extends StatelessWidget {
final Widget icon;
final Function onPressed;
const _IconButton({this.icon, this.onPressed, Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return IconButton(onPressed: onPressed, icon: icon);
}
}

View File

@ -1,17 +0,0 @@
import 'package:flutter/material.dart';
import 'package:jisho_study_tool/view/components/kanji/kanji_search_bar.dart';
class InitScreen extends StatelessWidget {
const InitScreen({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
alignment: Alignment.center,
padding: EdgeInsets.symmetric(horizontal: 20),
child: KanjiSearchBar(),
);
}
}

View File

@ -0,0 +1,95 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:jisho_study_tool/bloc/kanji/kanji_bloc.dart';
import 'package:animated_size_and_fade/animated_size_and_fade.dart';
import 'package:jisho_study_tool/view/components/kanji/kanji_grid.dart';
import 'package:jisho_study_tool/view/components/kanji/kanji_search_bar.dart';
import 'package:jisho_study_tool/view/components/kanji/kanji_search_options_bar.dart';
class SearchScreen extends StatefulWidget {
SearchScreen({Key key}) : super(key: key);
@override
_SearchScreenState createState() => _SearchScreenState();
}
class _SearchScreenState extends State<SearchScreen>
with SingleTickerProviderStateMixin {
AnimationController _controller;
Animation _searchbarMovementAnimation;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: Duration(milliseconds: 200),
);
_searchbarMovementAnimation = AlignmentTween(
begin: Alignment.center,
end: Alignment.topCenter,
).animate(CurvedAnimation(
parent: _controller,
curve: Curves.easeInOut,
));
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: Container(
decoration: BoxDecoration(),
alignment: Alignment.center,
padding: EdgeInsets.symmetric(horizontal: 20),
child: AnimatedBuilder(
animation: _searchbarMovementAnimation,
builder: (BuildContext context, _) {
return Container(
alignment: _searchbarMovementAnimation.value,
padding: EdgeInsets.symmetric(vertical: 10.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Focus(
onFocusChange: (hasFocus) {
if (hasFocus)
_controller.forward();
else
_controller.reverse();
},
child: KanjiSearchBar(),
),
BlocBuilder<KanjiBloc, KanjiState>(
builder: (context, state) {
return AnimatedSizeAndFade(
vsync: this,
child: _controller.value == 1
? KanjiGrid((state is KanjiSearchKeyboard)
? state.kanjiSuggestions
: [])
// ? Container()
: KanjiSearchOptionsBar(),
fadeDuration: const Duration(milliseconds: 200),
sizeDuration: const Duration(milliseconds: 300),
);
},
)
],
),
);
},
),
),
);
}
}

View File

@ -4,12 +4,9 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:jisho_study_tool/bloc/kanji/kanji_bloc.dart'; import 'package:jisho_study_tool/bloc/kanji/kanji_bloc.dart';
import 'package:jisho_study_tool/view/screens/loading.dart'; import 'package:jisho_study_tool/view/screens/loading.dart';
import 'package:jisho_study_tool/view/components/kanji/kanji_grid.dart';
import 'package:jisho_study_tool/view/components/kanji/kanji_search_bar.dart';
import 'init.dart'; import 'search.dart';
import 'result.dart'; import 'result.dart';
import 'search/grid.dart';
class KanjiView extends StatelessWidget { class KanjiView extends StatelessWidget {
@override @override
@ -25,8 +22,8 @@ class KanjiView extends StatelessWidget {
child: BlocBuilder<KanjiBloc, KanjiState>( child: BlocBuilder<KanjiBloc, KanjiState>(
builder: (context, state) { builder: (context, state) {
if (state is KanjiSearch) { if (state is KanjiSearch) {
if (state.type == KanjiSearchType.Initial) return InitScreen(); if (state.type == KanjiSearchType.Initial) return SearchScreen();
else if (state is KanjiSearchKeyboard) return SearchGrid(state.kanjiSuggestions); else if (state is KanjiSearchKeyboard) return SearchScreen();
} }
else if (state is KanjiSearchLoading) return LoadingScreen(); else if (state is KanjiSearchLoading) return LoadingScreen();
else if (state is KanjiSearchFinished) else if (state is KanjiSearchFinished)