2017-05-24 6 views
1

Flutter/Dartを使い始めたばかりなので、私のCardウィジェットが画面外にスクロールすると状態が失われているのだろうと思います。グリッドビューのウィジェットは、オフスクリーン時に状態を失います

_isSelectedは、Cardウィジェットの1つをタップするユーザーによって切り替えられます。彼らは画面から消えるまで、すべて正常です - いつ彼らは正常に戻ります。私は状態を保存するために追加の措置を取る必要があると仮定していますが、これについて最善を尽くす方法についてはあまりよく分かりません。

import 'dart:convert'; 

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

class CardHolder extends StatefulWidget { 
    CardHolder({Key key}) : super(key: key); 

    @override 
    _CardHolderState createState() => new _CardHolderState(); 
} 

class _CardHolderState extends State<CardHolder> { 
    List _cardData; 

    _getCards() async { 
    String endpoint = 'https://jsonplaceholder.typicode.com/posts'; 
    var httpClient = createHttpClient(); 
    var response = await httpClient.read(endpoint); 

    List data = JSON.decode(response); 

    if (!mounted) return; 

    setState(() { 
     _cardData = data; 
    }); 
    } 

    @override 
    void initState() { 
    super.initState(); 

    _getCards(); 
    } 

    @override 
    Widget build(BuildContext context) { 
    return new GridView.extent(
     maxCrossAxisExtent: 250.0, 
     mainAxisSpacing: 4.0, 
     crossAxisSpacing: 4.0, 
     children: _buildGridList(_cardData) 
    ); 
    } 
} 

List<Card> _buildGridList(data) { 
    if (data == null) return []; 
    List<Card> cards = []; 
    for (var card in data) { 
    cards.add(new Card(title: card['title'])); 
    } 
    return cards; 
} 

class Card extends StatefulWidget { 
    Card({Key key, this.title}) : super(key: key); 

    final String title; 

    @override 
    CardState createState() => new CardState(); 
} 

class CardState extends State<Card> { 

    String title; 
    bool _isSelected = false; 

    _toggleSelected() { 
    setState(() { 
     _isSelected = !_isSelected; 
     print('Toggled to ' + _isSelected.toString()); 
    }); 
    } 

    CardState({this.title = "No Title!"}); 

    @override 
    Widget build(BuildContext context) { 
    print('Rendering card: ' + widget.title); 
    return new GestureDetector(
     onTap: _toggleSelected, 
     child: new Container(
      constraints: new BoxConstraints(minHeight: 120.0, minWidth: 100.0, maxWidth: 100.0), 
      decoration: new BoxDecoration(
       color: _isSelected ? Colors.red : Colors.white, 
       borderRadius: new BorderRadius.all(new Radius.circular(2.5)), 
       boxShadow: [new BoxShadow(color: Colors.black45, blurRadius: 5.0, spreadRadius: 0.0, offset: new Offset(0.0, 3.0))] 
      ), 
      margin: new EdgeInsets.all(5.0), 
      padding: new EdgeInsets.all(10.0), 
      child: new Text(widget.title, style: new TextStyle(color: Colors.black)) 
     ) 
    ); 
    } 
} 

答えて

1

この動作は、フラッターがあなたのオフスクリーンStateをクリーンアップするために設計された意味で意図したとおりに機能しています。 isSelectedブール値をツリーの上位レベルに維持することで、必要な動作を得ることができます。 CardHolderまたはモデルクラス。簡単な場合は、ValueNotifierで十分です。ここにその例があります。

import 'dart:collection'; 
import 'package:flutter/scheduler.dart'; 
import 'package:flutter/material.dart'; 
import 'dart:convert'; 

import 'package:flutter/material.dart'; 
import 'package:flutter/services.dart'; 
import 'package:flutter/foundation.dart'; 

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

class MyApp extends StatelessWidget { 
    @override 
    Widget build(BuildContext context) { 
    return new MaterialApp(
     title: 'Flutter Demo', 
     theme: new ThemeData(
     primarySwatch: Colors.blue, 
     primaryColorBrightness: Brightness.light, 
    ), 
     home: new CardHolder(), 
    ); 
    } 
} 

class CardHolder extends StatefulWidget { 
    CardHolder({Key key}) : super(key: key); 

    @override 
    _CardHolderState createState() => new _CardHolderState(); 
} 

class _CardHolderState extends State<CardHolder> { 
    List _cardData; 

    _getCards() async { 
    String endpoint = 'https://jsonplaceholder.typicode.com/posts'; 
    var httpClient = createHttpClient(); 
    var response = await httpClient.read(endpoint); 

    List data = JSON.decode(response); 

    if (!mounted) return; 

    setState(() { 
     _cardData = data; 
    }); 
    } 

    @override 
    void initState() { 
    super.initState(); 

    _getCards(); 
    } 

    @override 
    Widget build(BuildContext context) { 
    return new GridView.extent(
     maxCrossAxisExtent: 250.0, 
     mainAxisSpacing: 4.0, 
     crossAxisSpacing: 4.0, 
     children: _buildGridList(_cardData) 
    ); 
    } 
} 

List<Card> _buildGridList(data) { 
    if (data == null) return []; 
    List<Card> cards = []; 
    for (var card in data) { 
    cards.add(new Card(
     title: card['title'], 
     isSelected: new ValueNotifier<bool>(false), 
    )); 
    } 
    return cards; 
} 

class Card extends AnimatedWidget { 
    Card({Key key, this.title, this.isSelected }) : super(key: key, listenable: isSelected); 

    final String title; 
    final ValueNotifier<bool> isSelected; 

    @override 
    Widget build(BuildContext context) { 
    print('Rendering card: ' + title); 
    return new GestureDetector(
     onTap:() { 
     isSelected.value = !isSelected.value; 
     }, 
     child: new Container(
     constraints: new BoxConstraints(minHeight: 120.0, minWidth: 100.0, maxWidth: 100.0), 
     decoration: new BoxDecoration(
      color: isSelected.value ? Colors.red : Colors.white, 
      borderRadius: new BorderRadius.all(new Radius.circular(2.5)), 
      boxShadow: [new BoxShadow(color: Colors.black45, blurRadius: 5.0, spreadRadius: 0.0, offset: new Offset(0.0, 3.0))] 
     ), 
     margin: new EdgeInsets.all(5.0), 
     padding: new EdgeInsets.all(10.0), 
     child: new Text(title, style: new TextStyle(color: Colors.black)) 
    ) 
    ); 
    } 
} 
+0

私はそれに関係があると考えました。速いフォローアップ:なぜあなたは 'StatefulWidget'ではなく' AnimatedWidget'にカードウィジェットを変更しましたか? – opticon

+0

'ValueNotifier'の変更をリッスンして再構築する必要があるためです。 'AnimatedWidget'はそれを自動的に行います。 –

+0

良いもの。 'setState'を呼び出すのではなく?上記の単純なユースケースを超えてこれを拡張したいと仮定した場合、そのパターンはどのように見えますか? – opticon

関連する問題