mirror of
https://github.com/flutter/samples.git
synced 2025-11-11 07:18:15 +00:00
Add flutter_web samples (#75)
This commit is contained in:
committed by
Andrew Brogdon
parent
42f2dce01b
commit
3fe927cb29
177
web/slide_puzzle/lib/src/puzzle_home_state.dart
Normal file
177
web/slide_puzzle/lib/src/puzzle_home_state.dart
Normal file
@@ -0,0 +1,177 @@
|
||||
// Copyright 2019 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'app_state.dart';
|
||||
import 'core/puzzle_animator.dart';
|
||||
import 'flutter.dart';
|
||||
import 'shared_theme.dart';
|
||||
import 'theme_plaster.dart';
|
||||
import 'theme_seattle.dart';
|
||||
import 'theme_simple.dart';
|
||||
|
||||
class PuzzleHomeState extends State
|
||||
with TickerProviderStateMixin
|
||||
implements AppState {
|
||||
TabController _tabController;
|
||||
AnimationController _controller;
|
||||
|
||||
@override
|
||||
final PuzzleAnimator puzzle;
|
||||
|
||||
@override
|
||||
final animationNotifier = _AnimationNotifier();
|
||||
|
||||
@override
|
||||
TabController get tabController => _tabController;
|
||||
|
||||
SharedTheme _currentTheme;
|
||||
|
||||
@override
|
||||
SharedTheme get currentTheme => _currentTheme;
|
||||
|
||||
@override
|
||||
set currentTheme(SharedTheme theme) {
|
||||
setState(() {
|
||||
_currentTheme = theme;
|
||||
});
|
||||
}
|
||||
|
||||
Duration _tickerTimeSinceLastEvent = Duration.zero;
|
||||
Ticker _ticker;
|
||||
Duration _lastElapsed;
|
||||
StreamSubscription sub;
|
||||
|
||||
@override
|
||||
bool autoPlay = false;
|
||||
|
||||
PuzzleHomeState(this.puzzle) {
|
||||
sub = puzzle.onEvent.listen(_onPuzzleEvent);
|
||||
|
||||
_themeDataCache = List.unmodifiable([
|
||||
ThemeSimple(this),
|
||||
ThemeSeattle(this),
|
||||
ThemePlaster(this),
|
||||
]);
|
||||
|
||||
_currentTheme = themeData.first;
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_ticker ??= createTicker(_onTick);
|
||||
_ensureTicking();
|
||||
|
||||
_controller = AnimationController(
|
||||
vsync: this,
|
||||
duration: const Duration(milliseconds: 200),
|
||||
);
|
||||
|
||||
_tabController = TabController(vsync: this, length: _themeDataCache.length);
|
||||
|
||||
_tabController.addListener(() {
|
||||
currentTheme = _themeDataCache[_tabController.index];
|
||||
});
|
||||
}
|
||||
|
||||
List<SharedTheme> _themeDataCache;
|
||||
|
||||
@override
|
||||
Iterable<SharedTheme> get themeData => _themeDataCache;
|
||||
|
||||
@override
|
||||
void setAutoPlay(bool newValue) {
|
||||
if (newValue != autoPlay) {
|
||||
setState(() {
|
||||
// Only allow enabling autoPlay if the puzzle is not solved
|
||||
autoPlay = newValue && !puzzle.solved;
|
||||
if (autoPlay) {
|
||||
_ensureTicking();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) =>
|
||||
LayoutBuilder(builder: _currentTheme.build);
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
animationNotifier.dispose();
|
||||
_tabController.dispose();
|
||||
_controller?.dispose();
|
||||
_ticker?.dispose();
|
||||
sub.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _onPuzzleEvent(PuzzleEvent e) {
|
||||
_tickerTimeSinceLastEvent = Duration.zero;
|
||||
_ensureTicking();
|
||||
if (e == PuzzleEvent.noop) {
|
||||
assert(e == PuzzleEvent.noop);
|
||||
_controller
|
||||
..reset()
|
||||
..forward();
|
||||
}
|
||||
setState(() {
|
||||
// noop
|
||||
});
|
||||
}
|
||||
|
||||
void _ensureTicking() {
|
||||
if (!_ticker.isTicking) {
|
||||
_ticker.start();
|
||||
}
|
||||
}
|
||||
|
||||
void _onTick(Duration elapsed) {
|
||||
if (elapsed == Duration.zero) {
|
||||
_lastElapsed = elapsed;
|
||||
}
|
||||
final delta = elapsed - _lastElapsed;
|
||||
_lastElapsed = elapsed;
|
||||
|
||||
if (delta.inMilliseconds <= 0) {
|
||||
// `_delta` may be negative or zero if `elapsed` is zero (first tick)
|
||||
// or during a restart. Just ignore this case.
|
||||
return;
|
||||
}
|
||||
|
||||
_tickerTimeSinceLastEvent += delta;
|
||||
puzzle.update(delta > _maxFrameDuration ? _maxFrameDuration : delta);
|
||||
|
||||
if (!puzzle.stable) {
|
||||
animationNotifier.animate();
|
||||
} else {
|
||||
if (!autoPlay) {
|
||||
_ticker.stop();
|
||||
_lastElapsed = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (autoPlay &&
|
||||
_tickerTimeSinceLastEvent > const Duration(milliseconds: 200)) {
|
||||
puzzle.playRandom();
|
||||
|
||||
if (puzzle.solved) {
|
||||
setAutoPlay(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class _AnimationNotifier extends ChangeNotifier implements AnimationNotifier {
|
||||
_AnimationNotifier();
|
||||
|
||||
@override
|
||||
void animate() {
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
const _maxFrameDuration = Duration(milliseconds: 34);
|
||||
Reference in New Issue
Block a user