반응형
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- Raycasting
- jszip
- node
- Prism.js
- react
- babel
- identifierForVender
- Flutter
- KakaoMap
- Three js
- Excel
- web track
- Babel standalone
- Game js
- methodChannel
- typescript
- Redux
- REST API
- webrtc
- Image Resize typescript
- Three-fiber
- androidId
- swagger-typescript-api
- code editor
- uint16array
- RouteObserver
- uint8array
- userevent_tracker
- FirebaseAnalytics
- Completer
Archives
- Today
- Total
Never give up
Flutter - Map<key, List<data>> with Listview(simple chatting screen) 본문
Flutter
Flutter - Map<key, List<data>> with Listview(simple chatting screen)
대기만성 개발자 2020. 11. 2. 18:19반응형
데이터를 다루다보면 Map을 Listview로 표현해야될때가 있습니다
제가 사용한 데이터 타입은 Map<String, List<items>>입니다
(items은 String값의 reply와 user name입니다)
다양한 방법이 있지만 필자는 다음과 같은 방법을 사용했습니다
Main
class MapListViewExample extends StatefulWidget {
@override
_MapListViewExampleState createState() => _MapListViewExampleState();
}
class _MapListViewExampleState extends State<MapListViewExample> {
TextEditingController _tController = TextEditingController();
ScrollController _sController = ScrollController();
@override
void initState() {
super.initState();
Provider.of<MapExampleData>(context, listen: false).setName('하..');
WidgetsBinding.instance.addPostFrameCallback((_) {
_sController.jumpTo(_sController.position.maxScrollExtent);
});
}
void addListener() {
_sController.animateTo(_sController.position.maxScrollExtent,
duration: Duration(milliseconds: 300), curve: Curves.ease);
}
@override
void dispose() {
_tController?.dispose();
_sController?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Consumer<MapExampleData>(
builder: (context, items, child) {
return Scaffold(
backgroundColor: Colors.green,
body: SafeArea(
child: InkWell(
focusColor: Colors.green,
onTap: () => FocusScope.of(context).unfocus(),
child: Column(
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: ListView.builder(
controller: _sController,
itemCount: items.getLength,
itemBuilder: (context, index) {
var item = items.getList[index];
return MessageForm(
name: item.name,
message: item.message,
isOwner: (index % 2 == 1));
}),
),
),
Container(
padding: const EdgeInsets.only(left: 10),
color: Colors.white,
child: TextField(
controller: _tController,
style: TextStyle(color: Colors.black),
decoration: InputDecoration(
hintText: 'Reply...',
suffixIcon: Container(
color: Colors.yellow[600],
child: IconButton(
icon: Icon(Icons.search, color: Colors.white),
onPressed: () {
items.addData();
_tController.clear();
FocusScope.of(context).unfocus();
addListener();
}),
),
border: InputBorder.none,
),
onChanged: (value) => items.setMessage(value),
onSubmitted: (value) {
items.addData();
_tController.clear();
addListener();
},
),
)
],
),
),
),
);
},
);
}
}
MessageForm
class MessageForm extends StatelessWidget {
final String name, message;
final bool isOwner;
MessageForm({this.name, this.message, this.isOwner});
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment:
isOwner ? CrossAxisAlignment.end : CrossAxisAlignment.start,
children: <Widget>[
Align(
alignment: isOwner ? Alignment.topRight : Alignment.topLeft,
child: CircleAvatar(child: Text(name[0]))),
Padding(
padding: isOwner
? EdgeInsets.only(right: 40)
: EdgeInsets.only(left: 40),
child: Card(
shape: RoundedRectangleBorder(
borderRadius: isOwner
? BorderRadius.only(
topLeft: Radius.circular(30),
bottomLeft: Radius.circular(30),
bottomRight: Radius.circular(30))
: BorderRadius.only(
bottomLeft: Radius.circular(30),
bottomRight: Radius.circular(30),
topRight: Radius.circular(30))),
elevation: 5,
color: isOwner ? Colors.lightGreen : Colors.white,
child: Padding(
padding:
const EdgeInsets.symmetric(vertical: 10, horizontal: 20),
child: Text(
message,
style: TextStyle(
fontSize: 15,
color: isOwner ? Colors.white : Colors.lightGreen),
),
),
),
),
],
),
);
}
}
Item class
class MapExampleItem {
String name, message;
MapExampleItem({this.name, this.message});
}
Data class
class MapExampleData extends ChangeNotifier {
Map<String, List<MapExampleItem>> _data = {};
String _key = '';
String _name, _message;
UnmodifiableListView<MapExampleItem> get getList {
if (_data[_key] == null) {
_data[_key] = [];
}
return UnmodifiableListView(_data[_key]);
}
int get getLength => getList.length;
void addData() {
if (checkData) {
_data[_key].add(MapExampleItem(name: _name, message: _message));
notifyListeners();
}
}
bool get checkData {
return (_message != null && _name != null);
}
void setMessage(String value) {
_message = value;
}
void setName(String value) {
_name = value;
}
}
먼저 리스트를 불러올 때는 getList부분에서 Map[key]를 사용하면 해당 value(List)를 가져올 수 있고
(getList부분에서 null처리를 안해주면 init값이 null이라서 에러가 납니다)
Listview형태로 출력을 해주는 간단한 방법인데 key에 따라 여러 List를 사용할 때 유용할거 같습니다
번외로 Map<Key, Value>를 Listview로 표현하는 방법에 대해 알아보자면
data class에서 다음과 같이 정의해주고
UnmodifiableMapView<key, value> get getMap => UnmodifiableMapView(_map);
int get getMapLength => _map.length;
Listview의 itemBuilder부분에서
ListView.builder(
controller: _sController,
itemCount: items.getLength,
itemBuilder: (context, index) {
String key = items.getMap.keys.elementAt(index);
var item = items.getMap[key];
return //위젯부분은 생략)
element위치에 따른 key값을 가져온 후
map에서 key에 해당되는 value값을 추출해서 사용하시면 됩니다
아니면 values.toList()를 사용하는것도 괜찮습니다
상황에 맞게 사용하시면 될거 같습니다
반응형
'Flutter' 카테고리의 다른 글
Flutter - When to use Enum(feat. authentication) (2) | 2020.11.30 |
---|---|
Flutter - context, key example with snackbar, provider (0) | 2020.11.16 |
Flutter - Search item in List and how to keep TextField from keyboard (0) | 2020.10.05 |
Flutter - Json serialize (0) | 2020.10.01 |
Flutter - how to get item index in Listview (0) | 2020.09.30 |
Comments