떨림 응답 쌍기둥 구조
31059 단어 flutterresponsivetutorial
전체 코드는 github에서 찾을 수 있습니다.
비헤이비어
응답 진동 레이아웃 항목 목록 프레젠테이션
인코딩을 시작하기 전에, 우리가 실현하고자 하는 목표를 정확하게 정의하고, 각 부분을 점차적으로 해결합시다.이것은 우리가 이 임무에 전념하고 전진 중에 우리의 진전을 추적하는 데 도움이 될 것이다.
간단하게 말하면, 창의 화면 크기에 따라 하위 창의 표시 방식을 업데이트하는 작은 위젯이 필요합니다.큰 화면에서 두 개의 창으로 나누어야 한다.작은 화면에는 하나의 창만 표시되고 필요에 따라 두 번째 창의 팝업 창을 열어야 합니다.
1. 유연한 배치
응답 전진기둥 배치도
첫 번째 부분은
Flex
작은 위젯을 Flatter에서 쉽게 사용할 수 있습니다. 다시 사용하기 쉽도록 작은 위젯을 만들 것입니다. 이 위젯은 창의 행동을 수용하고 책임질 수 있습니다.class TwoPane extends StatelessWidget {
final double breakpoint = 800;
final int paneProportion = 70;
@override
Widget build(BuildContext context) {
if (breakpoint < MediaQuery.of(context).size.width) {
return Flex(
direction: Axis.horizontal,
children: [
Flexible(
flex: paneProportion,
child: Pane1(),
),
Flexible(
flex: 100 - paneProportion,
child: Pane2(),
),
],
);
}
return Flex(
direction: Axis.horizontal,
children: [
Flexible(
flex: 100,
child: Pane1(),
),
],
);
}
}
Pane1
과 Pane2
은 간단한 용기로 텍스트의 하위 등급과 배경을 가지고 있어 구분하기 편리하다.class Pane1 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
color: Colors.green[200],
child: Center(
child: Text('Pane 1'),
),
);
}
}
우리의 규범에 따르면 그것들은 Flexible
소부품에 봉인되어 있다.Pane1의 신축성은 paneProportion
, pane2의 신축성은 100 - paneProportion
으로 이 예에서 남은 공간은 각각 70%와 30%이다.이런 것들이 있어서 우리는 우리의 첫 번째 목표를 실현했다.장치 화면 너비에 따라 패널 크기를 조절하는 유연한 소부품.일단 폭이 단점보다 작으면, 우리는 첫 번째 창으로만 돌아갑니다.이제 작은 화면의 행동을 추가합니다.
작은 화면 팝업 페이지
응답 바이브레이션 2열 레이아웃, 작은 화면에서 단일 열로 접기
이것은 가장 긴 부분입니다. 주의해야 할 경고가 있기 때문에 인내심을 가지고 제 말을 들어 주십시오.
다음은 내가 아래에서 분해할 마지막 코드이다.
class TwoPane extends StatefulWidget {
final Widget pane1;
final Widget pane2;
/// keeps track of the pane2 open state
final bool showPane2;
/// Called called when pane2Popup
final void Function() onClosePane2Popup;
/// the breakpoint for small devices
final double breakpoint;
/// pane1 has a flex of `paneProportion`. Default = 70
///
/// pane2 `100 - paneProportion`. Default = 30.
final int paneProportion;
const TwoPane({
Key? key,
this.showPane2 = false,
required this.pane1,
required this.pane2,
required this.onClosePane2Popup,
this.breakpoint = 800,
this.paneProportion = 70,
}) : super(key: key);
@override
_TwoPaneState createState() => _TwoPaneState();
}
class _TwoPaneState extends State<TwoPane> {
bool _popupNotOpen = true;
bool get canSplitPanes =>
widget.breakpoint < MediaQuery.of(context).size.width;
/// Loads and removes the popup page for pane2 on small screens
void loadPane2Page(BuildContext context) async {
if (widget.showPane2 && _popupNotOpen) {
_popupNotOpen = false;
SchedulerBinding.instance!.addPostFrameCallback((_) async {
// sets _popupNotOpen to true after popup is closed
Navigator.of(context)
.push<Null>(
new MaterialPageRoute<Null>(
builder: (BuildContext context) {
return new Scaffold(
appBar: AppBar(title: Text('hello')),
body: widget.pane2,
);
},
fullscreenDialog: true,
),
)
.then((_) {
// less code than wapping in a WillPopScope
_popupNotOpen = true;
// preserves value if screen canSplitPanes
if (!canSplitPanes) widget.onClosePane2Popup();
});
});
}
}
/// closes popup wind
void _closePopup() {
if (!_popupNotOpen) {
SchedulerBinding.instance!
.addPostFrameCallback((_) => Navigator.pop(context));
}
}
@override
Widget build(BuildContext context) {
if (canSplitPanes && widget.showPane2) {
_closePopup();
return Flex(
direction: Axis.horizontal,
children: [
Flexible(
flex: widget.paneProportion,
child: widget.pane1,
),
Flexible(
flex: 100 - widget.paneProportion,
child: widget.pane2,
),
],
);
} else {
loadPane2Page(context);
return Flex(
direction: Axis.horizontal,
children: [
Flexible(
flex: 100,
child: widget.pane1,
),
],
);
}
}
}
우선, 구성 요소를 더욱 중용성 있게 하기 위해pane1,pane2와 행위 속성을 매개 변수로 전달합니다. final Widget pane1;
final Widget pane2;
final bool showPane2;
final void Function() onClosePane2Popup;
final double breakpoint;
final int paneProportion;
onClosePane2Popup
메타데이터를 주의하십시오.작은 화면의 팝업 창을 닫을 때 업데이트 값이 유용합니다.그런 다음 팝업 창을 열고 닫는 방법을 추가했습니다.
canSplitPanes
: 윈도우 크기 및 브레이크 추적 loadPane2Page
: 작은 화면에pane2 팝업 페이지 불러오기 _closePopup
: 팝업 창 닫기 _popupNotOpen
을 추가했습니다. 화면의 크기를 조정할 때마다 팝업 창이 다시 열리지 않도록 합니다. popupNotOpen은 비최종 필드이기 때문에 애니메이션을 추가할 때 필요한 어셈블리 상태를 설정합니다. bool _popupNotOpen = true;
bool get canSplitPanes =>
widget.breakpoint < MediaQuery.of(context).size.width;
/// Loads the popup page for pane2 on small screens
void loadPane2Page(BuildContext context) async {
if (widget.showPane2 && _popupNotOpen) {
_popupNotOpen = false;
SchedulerBinding.instance!.addPostFrameCallback((_) async {
...
)
.then((_) {
// less code than wapping in a WillPopScope
_popupNotOpen = true;
// preserves value if screen canSplitPanes
if (!canSplitPanes) widget.onClosePane2Popup();
});
});
}
}
/// closes popup wind
void _closePopup() {
if (!_popupNotOpen) {
SchedulerBinding.instance!
.addPostFrameCallback((_) => Navigator.pop(context));
}
}
팝업 창 뒤의 loadPane2Page
에서 _popupNotOpen
을 true
10if (!canSplitPanes) widget.onClosePane2Popup();
으로 설정하면 사용자가 팝업 창을 닫을 때만 리셋을 실행할 수 있으며, 큰 시간에 리셋을 실행할 수 있도록 조정할 수 없습니다.loadPane2Page
과 _closePopup
은 SchedulerBinding.instance!.addPostFrameCallback()
에 포장되어 있으며, 이것은 다른 렌더링 작업을 호출하기 전에 작은 부품을 정확하게 렌더링한 것을 확보하기 위해서입니다.증강 구성 요소를 테스트하기 위해서, 간단한 상태 관리를 위한 홈 위젯을 만들었습니다.
StatefullWidget
과 ValueNotifier
을 사용하여 상태를 업데이트하고 필요에 따라 구성 요소를 재구성하고 있습니다. 단, 선택한 상태 관리를 마음대로 사용하십시오.나는 또한
Pane1
과 Pane2
을 홈페이지 파일로 옮겼다. 왜냐하면 그들은 사실상 우리의 TwoPane
구성 요소의 일부분이 아니라 하위 구성 요소로만 전달되기 때문이다.컨테이너 페이지 코드는 다음과 같습니다.
// home_page.dart component
import 'package:flutter/material.dart';
import 'package:two_columns/steps/two_columns1.dart';
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
ValueNotifier<int?> _selected = ValueNotifier(null);
void _selectValue(int? val) => _selected.value = val;
void _clearSelected() => _selected.value = null;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Home page')),
body: ValueListenableBuilder(
builder: (context, _, child) {
return TwoColumns(
showPane2: (_selected.value != null) ? true : false,
onClosePane2Popup: _clearSelected,
pane1: Pane1(selectValue: _selectValue),
pane2: Pane2(value: _selected.value),
);
},
valueListenable: _selected,
),
);
}
}
class Pane1 extends StatelessWidget {
final void Function(int?) selectValue;
const Pane1({required this.selectValue});
@override
Widget build(BuildContext context) {
return Container(
color: Colors.green[200],
child: Center(
child: ElevatedButton(
child: Text('set value'),
onPressed: () => selectValue(3),
),
),
);
}
}
class Pane2 extends StatelessWidget {
final int? value;
const Pane2({Key? key, this.value}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
color: Colors.blue[200],
child: Center(
child: Text('Pane2 value is $value'),
),
);
}
}
더욱 실제적인 예
비록 우리가 세운 일은 정상적이지만, 그것은 매우 현실적인 용례가 아니다.더 현실적인 예는 아래의 예다.기본적으로 유일한 변화는 프로젝트 목록을
pane1
에 전달하고 세부 정보 카드를 pane2
에 전달하는 것이다응답 진동 레이아웃 항목 목록 프레젠테이션
상기 예시된 코드와 모든 절차를 github에서 찾을 수 있습니다.
한층 더 개선하다.
나는 그것으로 가방을 만들 것을 고려하고 있기 때문에 가능한 한 코드를 최적화하고 싶다.수직 레이아웃, 더블 스크린 지원, 과도 애니메이션 등 추가 혜택도 추가할 것입니다. 필요에 따라 이 글을 업데이트하겠습니다.
모티프
Flatter에서 서랍을 만들 수 있는 작은 위젯이 많지만, 두 창의 화면을 쉽게 확장하고 접을 수 있는 작은 위젯을 찾을 수 없습니다. 그 중 하나는 디테일을 표시하는 데 사용되고, 다른 하나는 주요 내용을 표시하는 데 사용됩니다.그래서 저는 하나를 만들기로 결정했습니다. 저는 여기서 여러분과 공유할 것입니다. 왜냐하면 이것은 매우 유용한 것 같아서 저는 개선하고 여러분에게 배우고 싶습니다.
그러나 그 전에 개선 방법에 대한 당신들의 의견을 듣고 싶습니다.
방주
이것은 제가 프로그래밍에 관한 첫 번째 문장입니다. 여러분께 유용하길 바랍니다.그 밖에 코드뿐만 아니라 쓰기도 포함하는 모든 비판과 건의에 감사 드립니다.
Reference
이 문제에 관하여(떨림 응답 쌍기둥 구조), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/trindade7/responsive-two-columns-layout-in-flutter-4omd텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)