본문 바로가기

개발하자

자동으로 이동하여 플러터에서 단일 하위 스크롤 뷰 내 행 위치로 이동하는 방법

반응형

자동으로 이동하여 플러터에서 단일 하위 스크롤 뷰 내 행 위치로 이동하는 방법

SingleChildScrollView를 사용하고 있습니다. 스크롤 방향은 행 위젯 내에 20개 이상의 하위 위젯이 배치된 상태에서 수평으로 설정됩니다. 행에서 위치 위젯(즉, 5번째 또는 6번째 위치)으로 프로그래밍 방식으로 스크롤합니다. 프로그래밍 방식으로 할 수 있는 방법이 있나요?

SingleChildScrollView(
    scrollDirection: Axis.horizontal,
    child: Row(
      children: buttons,
    ),
  )



다음을 정의할 수 있습니다:

ScrollController _controller = new ScrollController();

에 전달합니다:

SingleChildScrollView(
    controller: _scrollController,
    scrollDirection: Axis.horizontal,
    child: Row(
      children: buttons,
    ),
  ),

다음과 같이 프로그래밍 방식으로 스크롤합니다:

void scroll(double position) {
 _scrollController.jumpTo(position);
}

또는 스크롤 애니메이션이 필요한 경우:

void scrollAnimated(double position) {
 _scrollController.animateTo(position, Duration(seconds: 1), Curves.ease);
}

레이아웃이 작성된 직후에 자동으로 스크롤하려면 다음 방법을 재정의하여 이동할 수 있습니다:

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance
        .addPostFrameCallback((_) => scroll(500)); // scroll automatically  500px (as an example)
  }



이 작업을 수행하는 가장 쉬운 방법은 를 사용하는 것입니다.

가시적인 방법을 보장합니다

지정된 컨텍스트를 둘러싸는 스크롤 가능 파일을 스크롤하여 지정된 컨텍스트를 표시합니다.

아래 코드를 참조하십시오:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

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

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _value = 0;
  static final List<GlobalKey> _key = List.generate(20, (index) => GlobalKey());
  final List<Widget> buttons = List.generate(
    20,
    (index) => RaisedButton(
      onPressed: () {},
      color: index % 2 == 0 ? Colors.grey : Colors.white,
      child: Text("Button No # ${index + 1}", key: _key[index]),
    ),
  );

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Column(
        children: [
          SingleChildScrollView(
            scrollDirection: Axis.horizontal,
            child: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: buttons,
            ),
          ),
          DropdownButton(
            value: _value,
            items: List.generate(
              20,
              (index) => DropdownMenuItem(
                  child: Text("Goto Button # ${index + 1}"), value: index),
            ),
            onChanged: (value) {
              setState(() {
                _value = value;
                print("calling");
                Scrollable.ensureVisible(_key[value].currentContext);
              });
            },
          )
        ],
      ),
    );
  }
}



SingleChildScrollView를 추가하고 원하는 특정 위치로 스크롤할 수 있습니다

_scrollController.animateTo(
           //here specifing position= 100 mean 100px
                      100,
                      curve: Curves.ease,
                      duration: Duration(seconds: 1),



상태 비저장 위젯에서도 빌드 메서드에서 트리거하여 이 작업을 수행할 수도 있습니다. 렌더링이 완료된 후 스크롤이 완료되었는지 확인하는 데 사용됩니다. 선택할 수 있도록 상태 관리를 다시 추가해야 합니다. 그러나 GetX, StatefulWidget 또는 기타 옵션을 사용할 수 있습니다.

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatelessWidget {
  MyHomePage({Key? key, this.title}) : super(key: key);

  final String? title;

  static final List<GlobalKey> _key = List.generate(20, (index) => GlobalKey());
  final List<Widget> buttons = List.generate(
    20,
    (index) => ElevatedButton(
      onPressed: () {},
      style: ButtonStyle(backgroundColor: MaterialStateProperty.resolveWith((_)=> index % 2 == 0 ? Colors.lightGreen : Colors.orange)),
      child: Text("Button No # ${index + 1}", key: _key[index]),
    ),
  );

  @override
  Widget build(BuildContext context) {
    final thisWidget = Scaffold(
      appBar: AppBar(
        title: Text(title!),
      ),
      body: Column(
        children: [
          SingleChildScrollView(
            scrollDirection: Axis.horizontal,
            child: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: buttons,
            ),
          ),
          DropdownButton(
            value: 0,
            items: List.generate(
              20,
              (index) => DropdownMenuItem(
                  value: index,
                  child: Text("Goto Button # ${index + 1}")),
            ),
            onChanged: (value) {
              if (value != null) {
                WidgetsBinding.instance
                  .addPostFrameCallback((_) => Scrollable.ensureVisible(_key[value].currentContext!));
              }
            },
          )
        ],
      ),
    );
    WidgetsBinding.instance
      .addPostFrameCallback((_) => Scrollable.ensureVisible(_key[15].currentContext!));
    return thisWidget;
  }
}

반응형