Flutter 진급 의 애니메이션 효과 구현(1)

10523 단어 flutter애니메이션
지난 글 에서 우 리 는 Flutter 의 애니메이션 기 초 를 알 게 되 었 고 이 글 은 도표 의 애니메이션 효 과 를 실현 했다.
우선,새로운 프로젝트 my app 을 만 든 다음 main.dart 의 내용 을 아래 코드 로 바 꿔 야 합 니 다.

import 'package:flutter/material.dart';
import 'dart:math';

void main() {
 runApp(new MyApp());
}

class MyApp extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
 return new MaterialApp(
 title: 'Flutter Demo',
 home: new MyHomePage(),
 );
 }
}

class MyHomePage extends StatefulWidget {
 @override
 _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
 // Random([int seed ]):          
 final random = new Random();
 int dataSet;

 void changeData() {
 setState(() {
 dataSet = random.nextInt(100);
 });
 }

 @override
 Widget build(BuildContext context) {
 return new Scaffold(
 body: new Center(
 child: new Text('   :$dataSet'),
 ),
 floatingActionButton: new FloatingActionButton(
 onPressed: changeData,
 child: new Icon(Icons.refresh),
 ),
 );
 }
}
프로젝트 를 시작 하면 프로그램 은 가운데 에 있 는 텍스트 탭 을 표시 하고'데이터 세트:null'과 유동 단 추 를 표시 하여 데 이 터 를 새로 고 칩 니 다.
우리 의 응용 프로그램 이 생 성 한 트 리 구 조 는 다음 그림 에서 보 듯 이 컨트롤 개념 이 상당히 광범 위 하지만 모든 구체 적 인 컨트롤 유형 은 매우 중요 한 책임 을 가지 고 있 습 니 다.

사용자 인터페이스의 변 하지 않 는 컨트롤 트 리 를 정의 함으로써 사용자 인터페이스 를 수정 하 는 유일한 방법 은 트 리 를 재 구축 하 는 것 입 니 다.현재 프레임 이 만 료 되 었 을 때 Flutter 키 트 리 가 의존 하 는 일부 상태 가 바 뀌 었 음 을 알려 줍 니 다.이 상태 에서 의존 하 는 하위 트 리 의 뿌리 는 Stateful Widget 이 어야 합 니 다.Stateful Widget 은 가 변 적 이지 않 지만 하위 트 리 는 State 대상 에 의 해 구 축 됩 니 다.Flutter 는 구축 기간 에 트 리 를 통 해 State 대상 을 보존 하고 새 트 리 에 추 가 된 각각의 컨트롤 을 재 구축 한 다음 이 컨트롤 의 하위 트 리 가 어떻게 구축 되 었 는 지 확인 합 니 다.우리 프로그램 에서 MyHomePage 는MyHomePageState 는 그 상태의 Stateful Widget 입 니 다.사용자 가 단 추 를 누 를 때마다 코드 를 실행 하여 변경 합 니 다MyHomePageState。Flutter 가 내부 관 리 를 하고 컨트롤 트 리 를 재 구축 할 수 있 도록 setState 로 이 변 화 를 나 누 었 습 니 다.이런 상황 이 발생 했 을 때,MyHomePageState 는 새로운 MyHomePage 인 스 턴 스 를 기반 으로 조금 다른 하위 트 리 를 구축 합 니 다.
가 변 적 이지 않 은 컨트롤 과 상태 의존 서브 트 리 는 Flutter 가 제공 하 는 주요 도구 로 비동기 이벤트(예 를 들 어 버튼,타이머 눈금 또는 입력 데이터)에 응답 하 는 복잡 한 사용자 인터페이스 에서 의 상태 관리의 복잡성 을 처리 합 니 다.
우리 의 응용 프로그램 은 간단 한 컨트롤 구 조 를 유지 할 것 입 니 다.그러나 우 리 는 애니메이션 맞 춤 형 도형 을 만 들 것 입 니 다.첫 번 째 단 계 는 모든 데이터 세트 의 텍스트 를 아주 간단 한 도표 로 바 꾸 는 것 입 니 다.데이터 세트 는 현재 0~100 사이 의 숫자 만 있 기 때문에 도 표 는 하나의 선형 을 가 진 막대 그래프 가 될 것 입 니 다.그 높이 는 이 숫자 에 의 해 확정 되 고 우 리 는 초기 값 50 을 사용 하여 높이 가 null 이 되 지 않도록 할 것 입 니 다.

import 'package:flutter/material.dart';
import 'dart:math';

void main() {
 runApp(new MyApp());
}

class MyApp extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
 return new MaterialApp(
 title: 'Flutter Demo',
 home: new MyHomePage(),
 );
 }
}

class MyHomePage extends StatefulWidget {
 @override
 _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
 // Random([int seed ]):          
 final random = new Random();
 int dataSet = 50;

 void changeData() {
 setState(() {
 dataSet = random.nextInt(100);
 });
 }

 @override
 Widget build(BuildContext context) {
 return new Scaffold(
 body: new Center(
 child: new CustomPaint(
 size: new Size(200.0, 100.0),
 painter: new BarChartPainter(dataSet.toDouble())
 )
 ),
 floatingActionButton: new FloatingActionButton(
 onPressed: changeData,
 child: new Icon(Icons.refresh),
 ),
 );
 }
}

// CustomPaint:       CustomPainter     
class BarChartPainter extends CustomPainter {
 static const barWidth = 10.0;

 BarChartPainter(this.barHeight);
 final double barHeight;

 /*
 void paint(
 Canvas canvas,
 Size size
 )
           ,   Canvas     ,           ,
      size     
 */
 @override
 void paint(Canvas canvas, Size size) {
 final paint = new Paint()
 ..color = Colors.blue[400]
 ..style = PaintingStyle.fill;
 // drawRect:     Paint      ,       (   )  Paint.style  
 canvas.drawRect(
 // Rect.fromLTWH(double left, double top, double width, double height):
 //               ,         
 new Rect.fromLTWH(
 size.width-barWidth/2.0,
 size.height-barHeight,
 barWidth,
 barHeight
 ),
 paint
 );
 }

 /*
 bool shouldRepaint(
 CustomPainter,
 oldDelegate
 )
                 RenderCustomPaint   ,
                        CustomPaint  
 (        ,          )
 */
 @override
 bool shouldRepaint(BarChartPainter old) => barHeight != old.barHeight;
}
다음 단 계 는 애니메이션 을 추가 하 는 것 입 니 다.데이터 세트 가 변 할 때마다 이 표시 줄 이 갑자기 높이 를 바 꾸 는 것 이 아니 라 부 드 럽 기 를 바 랍 니 다.Flutter 는 애니메이션 을 편성 하 는 데 사용 되 는 Animation Controller 라 는 개념 이 있 습 니 다.모니터 를 등록 하면 애니메이션 값(0.0~1.0)이 바 뀌 었 을 때 알려 집 니 다.이런 상황 이 발생 할 때마다 우 리 는 예전 처럼 setState 를 호출 하여 업데이트 할 수 있 습 니 다MyHomePageState。

import 'package:flutter/material.dart';
import 'package:flutter/animation.dart';
import 'dart:math';
import 'dart:ui' show lerpDouble;

void main() {
 runApp(new MyApp());
}

class MyApp extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
 return new MaterialApp(
 title: 'Flutter Demo',
 home: new MyHomePage(),
 );
 }
}

class MyHomePage extends StatefulWidget {
 @override
 _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
 // Random([int seed ]):          
 final random = new Random();
 int dataSet = 50;
 AnimationController animation;
 double startHeight;
 double currentHeight;
 double endHeight;

 /*
 @protected
 @mustCallSuper
 void initState()
            
            State            
 */
 @override
 void initState() {
 super.initState();
 /*
 AnimationController({
 double value,
 Duration duration,
 String debugLabel,
 double lowerBound: 0.0,
 double upperBound: 1.0,
 TickerProvider vsync
 })
        
 */
 animation = new AnimationController(
 //              
 duration: const Duration(milliseconds: 300),
 vsync: this
 )
 /*
 void addListener(
 VoidCallback listener
 )
              
     removeListener     
 */
 ..addListener((){
 setState((){
 /*
 double lerpDouble(
 num a,
 num b,
 double t
 )
              
 return a + (b - a) * t;
 */
 currentHeight = lerpDouble(
 startHeight,
 endHeight,
 animation.value
 );
 });
 });
 startHeight = 0.0;
 currentHeight = 0.0;
 endHeight = dataSet.toDouble();
 //           (    )
 animation.forward();
 }

 /*
 @override
 void dispose()
               
   State           ,        
     dispose , State        ,  mounted   false,    setState     
             :        dispose State  
 */
 @override
 void dispose() {
 animation.dispose();
 super.dispose();
 }

 void changeData() {
 setState(() {
 startHeight = currentHeight;
 dataSet = random.nextInt(100);
 endHeight = dataSet.toDouble();
 animation.forward(from: 0.0);
 });
 }

 @override
 Widget build(BuildContext context) {
 return new Scaffold(
 body: new Center(
 child: new CustomPaint(
 size: new Size(200.0, 100.0),
 painter: new BarChartPainter(currentHeight)
 )
 ),
 floatingActionButton: new FloatingActionButton(
 onPressed: changeData,
 child: new Icon(Icons.refresh),
 ),
 );
 }
}

// CustomPaint:       CustomPainter     
class BarChartPainter extends CustomPainter {
 static const barWidth = 10.0;

 BarChartPainter(this.barHeight);
 final double barHeight;

 /*
 void paint(
 Canvas canvas,
 Size size
 )
           ,   Canvas     ,           ,
      size     
 */
 @override
 void paint(Canvas canvas, Size size) {
 final paint = new Paint()
 ..color = Colors.blue[400]
 ..style = PaintingStyle.fill;
 // drawRect:     Paint      ,       (   )  Paint.style  
 canvas.drawRect(
 // Rect.fromLTWH(double left, double top, double width, double height):
 //               ,         
 new Rect.fromLTWH(
 size.width-barWidth/2.0,
 size.height-barHeight,
 barWidth,
 barHeight
 ),
 paint
 );
 }

 /*
 bool shouldRepaint(
 CustomPainter,
 oldDelegate
 )
                 RenderCustomPaint   ,
                        CustomPaint  
 (        ,          )
 */
 @override
 bool shouldRepaint(BarChartPainter old) => barHeight != old.barHeight;
}
위의 코드 중의 lerp Double 함 수 는 이해 하기 어렵 습 니 다.매개 변 수 를 대 입 한 후에 계산 결 과 는 다음 과 같 습 니 다.

데이터 가 처음 0.0 에서 50.0 에 도 달 했 을 때 10 시간 이 걸 렸 다.52 시 에 도착 하 는 데 16 시간 이 걸 렸 다.따라서 대략 얻 은 결론 은 우리 응용 프로그램 에서 데이터 변화 가 적 을 수록 시간 이 많이 걸린다.

현재 프로그램 은 복잡성 이 변 했 습 니 다.우리 의 데이터 세트 는 여전히 하나의 숫자 일 뿐 입 니 다.애니메이션 제어 에 필요 한 코드 를 설정 하 는 것 은 작은 문제 입 니 다.왜냐하면 우리 가 더 많은 도표 데 이 터 를 얻 을 때 분해 되 지 않 기 때 문 입 니 다.진정한 문 제 는 변수 startHeight,currentHeight 와 endHeight 로 데이터 세트 와 애니메이션 값 에 대한 변경 사항 을 반영 하고 세 가지 다른 곳 에서 업데이트 하 는 것 이다.
우 리 는 이 혼 란 스 러 운 상황 을 처리 할 개념 이 필요 하 다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기