Метод nextPage() и previousPage() в PageController иногда не работает

Вот мой код: я отвечаю на событие ключа в Android MainActivity и использую BasicMessageChannel для отправки ключевого сообщения:

public class MainActivity extends FlutterActivity {

private static final String CHANNEL = "scroll";
private static final String KEY_LEFT = "keyLeft";
private static final String KEY_RIGHT = "keyRight";
private BasicMessageChannel messageChannel;
private FlutterView flutterView;

private String[] getArgsFromIntent(Intent intent) {
    // Before adding more entries to this list, consider that arbitrary
    // Android applications can generate intents with extra data and that
    // there are many security-sensitive args in the binary.
    ArrayList<String> args = new ArrayList<String>();
    if (intent.getBooleanExtra("trace-startup", false)) {
        args.add("--trace-startup");
    }
    if (intent.getBooleanExtra("start-paused", false)) {
        args.add("--start-paused");
    }
    if (intent.getBooleanExtra("enable-dart-profiling", false)) {
        args.add("--enable-dart-profiling");
    }
    if (!args.isEmpty()) {
        String[] argsArray = new String[args.size()];
        return args.toArray(argsArray);
    }
    return null;
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    GeneratedPluginRegistrant.registerWith(this);
    flutterView = new FlutterView(this);
    String[] args = getArgsFromIntent(getIntent());
    FlutterMain.ensureInitializationComplete(getApplicationContext(), args);
    flutterView.runFromBundle(FlutterMain.findAppBundlePath(getApplicationContext()), null);
    messageChannel = new BasicMessageChannel<>(flutterView, CHANNEL, StringCodec.INSTANCE);
}

@Override
public boolean dispatchKeyEvent(KeyEvent event) {
    if (event.getAction() == KeyEvent.ACTION_DOWN) {
        Log.d(TAG, "dispatchKeyEvent: ACTION_DOWN keyCode = " + event.getKeyCode());
        switch (event.getKeyCode()) {
            case KeyEvent.KEYCODE_DPAD_LEFT:
                messageChannel.send(KEY_LEFT);
                return true;

            case KeyEvent.KEYCODE_DPAD_RIGHT:
                messageChannel.send(KEY_RIGHT);
                return true;

            default:
                break;
        }
    }
    return super.dispatchKeyEvent(event);
}

@Override
protected void onDestroy() {
    if (flutterView != null) {
        flutterView.destroy();
    }
    super.onDestroy();
}

@Override
protected void onPause() {
    super.onPause();
    flutterView.onPause();
}

@Override
protected void onPostResume() {
    super.onPostResume();
    flutterView.onPostResume();
}

}

Когда Flutter получает сообщение, я вызываю nextPage() и previousPage () для прокрутки PageView, это не работает. Но я нахожу, если я вызываю nextPage() и previousPage () в методе onTap() объекта GestureDetector, он работает:

class _Page {
  _Page({
    this.imagePath,
  });

  final String imagePath;
}

final List<_Page> _allPages = <_Page>[
  new _Page(imagePath: 'images/1.jpg'),
  new _Page(imagePath: 'images/2.jpg'),
  new _Page(imagePath: 'images/3.jpg'),
  new _Page(imagePath: 'images/4.jpg'),
  new _Page(imagePath: 'images/5.jpg'),
  new _Page(imagePath: 'images/6.jpg'),
];

class ScrollablePageDemo extends StatefulWidget {
  @override
  _ScrollablePageDemoState createState() => new _ScrollablePageDemoState();
}

class _ScrollablePageDemoState extends State<ScrollablePageDemo>
    with SingleTickerProviderStateMixin {
  PageController _controller;
  static const String _channel = 'scroll';
  static const String _emptyMessage = '';
  static const String KEY_LEFT = "keyLeft";
  static const String KEY_RIGHT = "keyRight";
  static const BasicMessageChannel<String> platform =
      const BasicMessageChannel<String>(_channel, const StringCodec());

  @override
  void initState() {
    super.initState();
    _controller = new PageController(
        initialPage: 0, keepPage: true, viewportFraction: 1.0);
    platform.setMessageHandler(changePage);
  }

  @override
  void dispose() {
    super.dispose();
    _controller.dispose();
  }

  Future<String> changePage(String message) async {
    setState(() {
      print(message);
      if (message == KEY_RIGHT) {
        //here doesn't work
        _controller.nextPage(duration: kTabScrollDuration, curve: Curves.ease);
        print("tab right: page = " + _controller.page.toString());
      } else if (message == KEY_LEFT) {
        //here doesn't work
        _controller.previousPage(duration: kTabScrollDuration, curve: Curves.ease);
        print("tab left: page = " + _controller.page.toString());
      }
    });
    return _emptyMessage;
  }

  PageView buildPageView() {
    return new PageView(
      controller: _controller,
      children: _allPages.map((_Page page) {
        return new Container(
            key: new ObjectKey(page.imagePath),
            padding: const EdgeInsets.all(12.0),
            child: new Card(
                child: new Image.asset(page.imagePath, fit: BoxFit.fill)));
      }).toList(),
    );
  }

  @override
  Widget build(BuildContext context) {
    return new GestureDetector(
        onTap: () {
          print('Listen PageView');
          //here works
          _controller.nextPage(duration: kTabScrollDuration, curve: Curves.ease);
        },
        child: new Scaffold(
            appBar: new AppBar(
              title: new Text('PageView'),
            ),
            body: buildPageView()));
  }
}

void main() {
  runApp(new MaterialApp(
    title: 'Flutter Study',
    home: new ScrollablePageDemo(),
  ));
}

1 ответ

Решение

Проблема с setState метод внутри changePage, setState Запускает build метод всякий раз, когда состояние установлено. Таким образом, страница создается снова всякий раз, когда setState называется. Вы можете просто удалить setState от changePage метод.

пример:

Future<String> changePage(String message) async {
  print(message);
  if (message == KEY_RIGHT) {
    _controller.nextPage(duration: kTabScrollDuration, curve: Curves.ease);
    print("tab right: page = " + _controller.page.toString());
  } else if (message == KEY_LEFT) {
    _controller.previousPage(duration: kTabScrollDuration, curve: Curves.ease);
    print("tab left: page = " + _controller.page.toString());
  }
  return _emptyMessage;
}

Надеюсь, что это помогло!

Другие вопросы по тегам