Текст не отображается в виджете с отслеживанием состояния при Flutter

#flutter #dart

#флаттер #dart

Вопрос:

Я пытаюсь создать очень простое приложение, в котором элемент из списка отображается при нажатии на центральный виджет.

Это мой код:

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

void main() => runApp(
      MaterialApp(home: MyApp()),
    );

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Welcome to Flutter',
      home: Scaffold(
        backgroundColor: Colors.white,
        appBar: AppBar(
          title: Text('Welcome to Flutter'),
        ),
        body: Center(),
      ),
    );
  }
}

class picker extends StatefulWidget {
  @override
  _pickerState createState() => _pickerState();
}

class _pickerState extends State<picker> {
  List yourList = ["Yes", "No", "Maybe"];
  int randomIndex;

  _pickerState() {
    int randomIndex = Random().nextInt(yourList.length);
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: TextButton(
        onPressed: () {
          setState(() {
            print(yourList[randomIndex]);
          });
        },
        child: Text('$randomIndex'),
      ),
    );
  }
}
  

Ошибок не отображается, но в то же время моя цель не достигнута, поскольку текст не отображается, и в терминале ничего не печатается, даже если я добавил этот код print(yourList[randomIndex]);. Как мне отобразить текст и отобразить печать?

введите описание изображения здесь

Комментарии:

1. я не вижу, куда вы переходите от класса MyApp к средству выбора классов? Если вы просто поместите Center() в тело класса MyApp, он никогда не изменится, поскольку он никуда не перемещается

Ответ №1:

Другим решением является установка

 randomIndex = Random().nextInt(yourList.length);
  

в setState(() { как показано ниже.

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

void main() => runApp(
      MaterialApp(home: MyApp()),
    );

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Welcome to Flutter',
      home: Scaffold(
        backgroundColor: Colors.white,
        appBar: AppBar(
          title: Text('Welcome to Flutter'),
        ),
        body: picker(),
      ),
    );
  }
}

class picker extends StatefulWidget {
  @override
  _pickerState createState() => _pickerState();
}

class _pickerState extends State<picker> {
  List yourList = ["Yes", "No", "Maybe"];
  int randomIndex = 0;

  @override
  Widget build(BuildContext context) {
    return Center(
      child: TextButton(
        onPressed: () {
          setState(() {
            randomIndex = Random().nextInt(yourList.length);
          });
        },
        child: Text(yourList[randomIndex]),
      ),
    );
  }
}
  

Чтобы иметь начальный текст, setState необходимо вывести в отдельной функции, например:

 class _pickerState extends State<picker> {
 List yourList = ["Yes", "No", "Maybe"];
 String buttonText = "Initial Text";
 int randomIndex = 0;
 
 void _newRandomIndex() {
   setState(() {
     randomIndex = Random().nextInt(yourList.length);
     buttonText = yourList[randomIndex];
   });
 }

 @override
 Widget build(BuildContext context) {
   return Center(
     child: TextButton(
       onPressed: _newRandomIndex,
       child: Text(buttonText),
     ),
   );
 }
}
  

Комментарии:

1. Спасибо! Лучший ответ когда-либо. Кстати, вы знаете, как запускать рандомизацию только при нажатии? Можно ли инициализировать центральный текст моим собственным пользовательским текстом, например, «Спросить что-нибудь», и при нажатии на него будут отображаться только да, нет или, возможно, появляются.

Ответ №2:

Две ошибки:

  1. Вы не присваивали значение тому variable , которое вы на самом деле хотели использовать здесь:
   int randomIndex;

  _pickerState() {
    // you declared a local variable here and you were using value of variable you declared on top
    int randomIndex = Random().nextInt(yourList.length);
  }
  
  1. Метод _pickerState() не был вызван, и именно поэтому null в TextButton .

Вот рабочий код, вы можете просто скопировать и вставить его:

 class _PickerState extends State<Picker> {
  List yourList = ["Yes", "No", "Maybe"];
  int randomIndex;

  _pickerState() {
    randomIndex = Random().nextInt(yourList.length);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: TextButton(
          onPressed: () {
            _pickerState();
            setState(() {
              print(yourList[randomIndex]);
            });
          },
          child: Text('$randomIndex'),
        ),
      ),
    );
  }
}
  

Быстрый совет: попробуйте использовать UpperCase для именования class или любой CustomWidget его более удобный способ

Ответ №3:

Попробуйте использовать this.randomIndex = Random().nextInt(yourList.length); вместо этого при инициализации переменной в теле конструктора.

В противном случае вы объявляете другую локальную переменную при инициализации класса.

В следующий раз попробуйте отладить эту ошибку, установив значение по умолчанию вне инициализации, чтобы проверить, есть ли аналогичная проблема, например, ваша инициализация не проходит в ваше состояние.

Я бы также посоветовал вам изменить имена ваших классов на camelCase, чтобы избежать путаницы и чтобы люди могли видеть, что это код для инициализации класса. Вот статья dart о стилизации кода.