flutter - 如何显示 sqflite 表中的项目
问题描述
我正在努力创建一个带有类别的笔记应用程序。但我被困了 3 天来解决这个问题。
我的问题是,如何将 SQLite 表中的“类别”显示到 DropdownButtonFormField。
这是我的 database_helper
class DatabaseHelper {
DatabaseHelper.privateConstructor();
static final DatabaseHelper instance = DatabaseHelper.privateConstructor();
static Database? _database;
Future<Database> get database async => _database ??= await _initDatabase();
Future<Database> _initDatabase() async {
Directory documentDirectory = await getApplicationDocumentsDirectory();
String path = join(documentDirectory.path, 'note.db');
return await openDatabase(
path,
version: 1,
onCreate: _onCreate,
);
}
Future _onCreate(Database db, int version) async {
await db.execute('''
CREATE TABLE categories(
id INTEGER PRIMARY KEY,
title TEXT)
''');
}
Future<List<Category>> getCategories() async {
Database db = await instance.database;
var categories = await db.query('categories');
List<Category> categoryList = categories.isNotEmpty? categories.map((c) => Category.fromMap(c)).toList() : [];
return categoryList;
}
Future<int> add(Category category) async {
Database db = await instance.database;
return await db.insert('categories', category.toMap());
}
Future<int> remove(int id) async {
Database db = await instance.database;
return await db.delete('categories', where: 'id = ?', whereArgs: [id]);
}
Future<int> update(Category category) async {
Database db = await instance.database;
return await db.update('categories', category.toMap(), where: 'id = ?', whereArgs: [category.id]);
}
}
这是 category_model
class Category {
final int? id;
final String title;
Category({this.id, required this.title});
factory Category.fromMap(Map<String, dynamic> json) => new Category(
id: json['id'],
title: json['title'],
);
Map<String, dynamic> toMap() {
return {
'id': id,
'title': title,
};
}
}
这是CategoryScreen,在这里用户可以进行分类。
class CategoryScreen extends StatefulWidget {
const CategoryScreen({Key? key}) : super(key: key);
@override
_CategoryScreenState createState() => _CategoryScreenState();
}
class _CategoryScreenState extends State<CategoryScreen> {
var _categoryNameController = TextEditingController();
int? selectedId;
_showFormDialog(BuildContext context) {
return showDialog(
context: context,
barrierDismissible: true,
builder: (param) {
return AlertDialog(
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
style: TextButton.styleFrom(
primary: Colors.white,
backgroundColor: Colors.blueGrey,
onSurface: Colors.grey,
),
child: Text(
'Cancel',
),
),
TextButton(
onPressed: () async {
print('category: ${_categoryNameController.text}');
await DatabaseHelper.instance.add(
Category(title: _categoryNameController.text),
);
setState(() {
_categoryNameController.clear();
});
Navigator.of(context).pop(CategoryScreen());
},
style: TextButton.styleFrom(
primary: Colors.white,
backgroundColor: Colors.redAccent,
onSurface: Colors.grey,
),
child: Text(
'Save',
),
),
],
title: Text('Categories Form'),
content: SingleChildScrollView(
child: Column(
children: [
TextField(
controller: _categoryNameController,
decoration: InputDecoration(
hintText: 'Write a category', labelText: 'Category'),
),
],
),
),
);
});
}
_showEditFormDialog(BuildContext context) {
return showDialog(
context: context,
barrierDismissible: true,
builder: (param) {
return AlertDialog(
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
style: TextButton.styleFrom(
primary: Colors.white,
backgroundColor: Colors.blueGrey,
onSurface: Colors.grey,
),
child: Text(
'Cancel',
),
),
TextButton(
onPressed: () async {
print('category: ${_categoryNameController.text}');
selectedId != null
? await DatabaseHelper.instance.update(
Category(
id: selectedId,
title: _categoryNameController.text),
)
: await DatabaseHelper.instance.add(
Category(title: _categoryNameController.text),
);
setState(() {
_categoryNameController.clear();
});
Navigator.of(context).pop(CategoryScreen());
},
style: TextButton.styleFrom(
primary: Colors.white,
backgroundColor: Colors.redAccent,
onSurface: Colors.grey,
),
child: Text(
'Save',
),
),
],
title: Text('Categories Form'),
content: SingleChildScrollView(
child: Column(
children: [
TextField(
controller: _categoryNameController,
decoration: InputDecoration(
hintText: 'Write a category', labelText: 'Category'),
),
],
),
),
);
});
}
final GlobalKey<ScaffoldState> _globalKey = GlobalKey<ScaffoldState>();
@override
Widget build(BuildContext context) {
return Scaffold(
key: _globalKey,
appBar: AppBar(
title: Text("Categories"),
),
body: Center(
child: FutureBuilder<List<Category>>(
future: DatabaseHelper.instance.getCategories(),
builder:
(BuildContext context, AsyncSnapshot<List<Category>> snapshot) {
if (!snapshot.hasData) {
return Center(
child: Text("Loading..."),
);
}
return snapshot.data!.isEmpty
? Center(
child: Text(
"No Categories!",
style:
TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
),
)
: ListView(
physics: BouncingScrollPhysics(),
children: snapshot.data!.map((category) {
return Padding(
padding: EdgeInsets.only(top: 10, right: 16, left: 16),
child: Card(
elevation: 8.0,
child: ListTile(
onTap: () {
setState(() {
_categoryNameController.text = category.title;
selectedId = category.id;
});
_showEditFormDialog(context);
},
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
category.title,
style: TextStyle(
fontSize: 23,
fontWeight: FontWeight.bold),
),
IconButton(
onPressed: () async {
Category result = await showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text(
'${category.id}: ${category.title}'),
content: Text(
'Delete ${category.title} ?'),
actions: [
TextButton(
onPressed: () async {
DatabaseHelper.instance
.remove(category.id!);
setState(() {
_categoryNameController.clear();
});
Navigator.of(context).pop(CategoryScreen());
},
style: TextButton.styleFrom(
primary: Colors.white,
backgroundColor: Colors.blueGrey,
onSurface: Colors.grey,
),
child: Text("Yes"),
),
TextButton(onPressed: (){
Navigator.of(context).pop();
},
child: Text("No"),
style: TextButton.styleFrom(
primary: Colors.white,
backgroundColor: Colors.blueGrey,
onSurface: Colors.grey,
),
),
],
);
});
},
icon: Icon(
Icons.delete,
color: Colors.blueGrey,
))
],
),
),
),
);
}).toList(),
);
},
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
_showFormDialog(context);
},
child: Icon(Icons.add),
),
);
}
}
这是我的noteScreen 页面。在此页面中,用户可以使用类别屏幕中的类别做笔记。
class NoteScreen extends StatefulWidget {
const NoteScreen({Key? key}) : super(key: key);
@override
_NoteScreenState createState() => _NoteScreenState();
}
class _NoteScreenState extends State<NoteScreen> {
@override
Widget build(BuildContext context) {
var noteTitleController = TextEditingController();
var noteContentController = TextEditingController();
return Scaffold(
appBar: AppBar(
title: Text("Create Note"),
),
body: Padding(
padding: const EdgeInsets.all(15.0),
child: Column(
children: [
TextField(
controller: noteTitleController = TextEditingController(),
decoration: InputDecoration(
labelText: "Title",
hintText: "Write title",
),
),
TextField(
controller: noteContentController = TextEditingController(),
decoration: InputDecoration(
labelText: "Contents",
hintText: "Write Contents",
),
),
DropdownButtonFormField(
value:,
items:,
hint: Text('Category'),
onChanged: (value) {
setState(() {
});
},
),
SizedBox(
height: 20,
),
TextButton(onPressed: () {},
child: Text("Save",
style: TextStyle(fontSize: 20),),
style: TextButton.styleFrom(
minimumSize: Size(120, 40),
primary: Colors.white,
backgroundColor: Colors.blueGrey,
onSurface: Colors.grey,
),
),
],
),
),
);
}
}
你们能帮帮我吗?这是我在这里的第一篇文章,所以如果我做错了什么,请告诉我。
解决方案
像这样试试
List<Map<String, dynamic>>? categoryList;
String? selectedCategory;
int? selectedCatId;
@override
void initState() {
// TODO: implement initState
categoryList = [
{"id": 0, "title": "ABC"},
{"id": 1, "title": "DEF"},
{"id": 2, "title": "JKL"},
{"id": 3, "title": "XYZ"}
];
super.initState();
}
DropdownButtonFormField(
value: selectedCategory,
items: categoryList!
.map((label) => DropdownMenuItem(
child: Text(label['title']),
value: label["title"],
))
.toList(),
hint: Text('Category'),
onChanged: (dynamic value) {
setState(() {
selectedCategory = value;
});
var data = categoryList
?.where((element) => element["title"] == selectedCategory)
.toList();
selectedCatId = data![0]['id'];
},
),
它看起来像这样