html content
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:webview_flutter/webview_flutter.dart';
|
||||
|
||||
class _ListDetailScreen extends StatefulWidget {
|
||||
final String title;
|
||||
final String? filepath;
|
||||
|
||||
const _ListDetailScreen({super.key, required this.title, this.filepath});
|
||||
|
||||
@override
|
||||
State<_ListDetailScreen> createState() => _ListDetailScreenState();
|
||||
}
|
||||
|
||||
class _ListDetailScreenState extends State<_ListDetailScreen> {
|
||||
List<bool> checklist = [];
|
||||
late WebViewController _controller;
|
||||
late String? fPath = widget.filepath;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_controller =
|
||||
WebViewController()..setJavaScriptMode(JavaScriptMode.unrestricted);
|
||||
checklist = List.generate(paragraphs.length, (index) => false);
|
||||
if (fPath != null && fPath!.isNotEmpty) {
|
||||
_loadContent(fPath!); // <- ini penting
|
||||
}
|
||||
}
|
||||
|
||||
final List<String> paragraphs = [
|
||||
"Paragraf pertama tentang ${"widget.title"}.",
|
||||
"Paragraf kedua dengan informasi tambahan.",
|
||||
"Paragraf ketiga yang menjelaskan detail lebih lanjut.",
|
||||
"Paragraf keempat yang melengkapi pembahasan.",
|
||||
];
|
||||
|
||||
void _loadContent(String path) async {
|
||||
try {
|
||||
if (path.startsWith('http')) {
|
||||
_controller.loadRequest(Uri.parse(path));
|
||||
} else {
|
||||
String fileHtml = await rootBundle.loadString(path);
|
||||
_controller.loadHtmlString(fileHtml);
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint("Error loading HTML: $e");
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
appBar: AppBar(title: Text(widget.title)),
|
||||
body:
|
||||
(fPath != null && fPath!.isNotEmpty)
|
||||
? WebViewWidget(controller: _controller)
|
||||
: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Image.asset(
|
||||
'assets/images/default.png',
|
||||
width: 100,
|
||||
height: 100,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Expanded(
|
||||
child: Text(
|
||||
"Ini adalah detail dari ${widget.title}.",
|
||||
style: const TextStyle(fontSize: 18),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
itemCount: paragraphs.length,
|
||||
itemBuilder: (context, index) {
|
||||
return ListTile(
|
||||
title: Text(paragraphs[index]),
|
||||
trailing: Checkbox(
|
||||
value: checklist[index],
|
||||
onChanged: (bool? value) {
|
||||
setState(() {
|
||||
checklist[index] = value!;
|
||||
});
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:webview_flutter/webview_flutter.dart';
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
import 'dart:convert';
|
||||
|
||||
class ListDetailScreen extends StatefulWidget {
|
||||
final String title;
|
||||
@@ -13,89 +14,118 @@ class ListDetailScreen extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _ListDetailScreenState extends State<ListDetailScreen> {
|
||||
List<bool> checklist = [];
|
||||
late WebViewController _controller;
|
||||
late String? fPath = widget.filepath;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
checklist = List.generate(paragraphs.length, (index) => false);
|
||||
}
|
||||
|
||||
final List<String> paragraphs = [
|
||||
"Paragraf pertama tentang ${"widget.title"}.",
|
||||
"Paragraf kedua dengan informasi tambahan.",
|
||||
"Paragraf ketiga yang menjelaskan detail lebih lanjut.",
|
||||
"Paragraf keempat yang melengkapi pembahasan.",
|
||||
];
|
||||
|
||||
void _loadContent(String path) async {
|
||||
if (path.startsWith('http')) {
|
||||
// Load dari Internet
|
||||
_controller.loadRequest(Uri.parse(path));
|
||||
} else {
|
||||
// Load dari assets lokal
|
||||
String fileHtml = await rootBundle.loadString(path);
|
||||
_controller.loadHtmlString(fileHtml);
|
||||
}
|
||||
}
|
||||
late InAppWebViewController _webViewController;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
String _getMimeType(String path) {
|
||||
if (path.endsWith('.png')) return 'image/png';
|
||||
if (path.endsWith('.jpg') || path.endsWith('.jpeg')) return 'image/jpeg';
|
||||
if (path.endsWith('.svg')) return 'image/svg+xml';
|
||||
if (path.endsWith('.html')) return 'text/html';
|
||||
if (path.endsWith('.css')) return 'text/css';
|
||||
if (path.endsWith('.js')) return 'application/javascript';
|
||||
return 'application/octet-stream';
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
appBar: AppBar(title: Text(widget.title)),
|
||||
body:
|
||||
(fPath != null && fPath!.isNotEmpty)
|
||||
? WebViewWidget(controller: _controller)
|
||||
: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
children: [
|
||||
// Gambar di kiri atas dengan teks di kanan
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Image.asset(
|
||||
'assets/images/default.png', // Ganti dengan gambar yang sesuai
|
||||
width: 100,
|
||||
height: 100,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Expanded(
|
||||
child: Text(
|
||||
"Ini adalah detail dari ${widget.title}.",
|
||||
style: const TextStyle(fontSize: 18),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
|
||||
// Paragraf dengan checklist
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
itemCount: paragraphs.length,
|
||||
itemBuilder: (context, index) {
|
||||
return ListTile(
|
||||
title: Text(paragraphs[index]),
|
||||
trailing: Checkbox(
|
||||
value: checklist[index],
|
||||
onChanged: (bool? value) {
|
||||
setState(() {
|
||||
checklist[index] = value!;
|
||||
});
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
widget.filepath != null
|
||||
? InAppWebView(
|
||||
initialUrlRequest: URLRequest(url: WebUri("about:blank")),
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
javaScriptEnabled: true,
|
||||
allowFileAccessFromFileURLs: true,
|
||||
allowUniversalAccessFromFileURLs: true,
|
||||
),
|
||||
),
|
||||
),
|
||||
onWebViewCreated: (controller) async {
|
||||
_webViewController = controller;
|
||||
|
||||
final html = await rootBundle.loadString(widget.filepath!);
|
||||
final base = widget.filepath!.substring(
|
||||
0,
|
||||
widget.filepath!.lastIndexOf('/') + 1,
|
||||
);
|
||||
await controller.loadData(
|
||||
data: html,
|
||||
baseUrl: WebUri(
|
||||
"http://localhost/$base",
|
||||
), // agar path relatif seperti img1/* jalan
|
||||
mimeType: 'text/html',
|
||||
encoding: 'utf-8',
|
||||
);
|
||||
},
|
||||
onLoadStop: (controller, url) async {
|
||||
debugPrint("🚀 onLoadStop called. URL: $url");
|
||||
|
||||
var result = await controller.evaluateJavascript(
|
||||
source: """
|
||||
(() => {
|
||||
const board = document.getElementById('game-board');
|
||||
const hasRender = typeof renderGrid === 'function';
|
||||
return { hasRender, boardExists: board !== null };
|
||||
})();
|
||||
""",
|
||||
);
|
||||
|
||||
debugPrint("📊 Evaluated JS result: $result");
|
||||
|
||||
final jsCheck = await controller.evaluateJavascript(
|
||||
source: """
|
||||
typeof renderGrid === 'function' &&
|
||||
document.querySelector('#game-board') !== null
|
||||
""",
|
||||
);
|
||||
|
||||
debugPrint(
|
||||
"Apakah renderGrid tersedia dan board muncul? => $jsCheck",
|
||||
);
|
||||
|
||||
final imageLoaded = await controller.evaluateJavascript(
|
||||
source: """
|
||||
Array.from(document.images).every(img => img.complete)
|
||||
""",
|
||||
);
|
||||
|
||||
debugPrint("Semua gambar berhasil dimuat? => $imageLoaded");
|
||||
},
|
||||
|
||||
// (Opsional) tangkap log dari JS
|
||||
onConsoleMessage: (controller, consoleMessage) {
|
||||
debugPrint("📢 JS Console: ${consoleMessage.message}");
|
||||
},
|
||||
shouldInterceptRequest: (controller, request) async {
|
||||
final url = request.url;
|
||||
if (url == null || url.host != 'localhost') return null;
|
||||
|
||||
try {
|
||||
// Strip "http://localhost/" from the path
|
||||
final path = url.path.replaceFirst('/', '');
|
||||
|
||||
final asset = await rootBundle.load(path);
|
||||
final mimeType = _getMimeType(path);
|
||||
|
||||
return WebResourceResponse(
|
||||
contentType: mimeType,
|
||||
data: asset.buffer.asUint8List(),
|
||||
statusCode: 200,
|
||||
reasonPhrase: 'OK',
|
||||
);
|
||||
} catch (e) {
|
||||
print("⚠️ Asset not found: ${url.path} -> $e");
|
||||
return WebResourceResponse(
|
||||
contentType: 'text/plain',
|
||||
data: Uint8List.fromList(utf8.encode('404 Not Found')),
|
||||
statusCode: 404,
|
||||
reasonPhrase: 'Not Found',
|
||||
);
|
||||
}
|
||||
},
|
||||
)
|
||||
: const Center(child: Text("Tidak ada file HTML")),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,12 +6,14 @@ import 'package:flutter/services.dart';
|
||||
import 'package:freekake/components/card_list.dart';
|
||||
import 'package:freekake/components/collection_container%20copy.dart';
|
||||
import 'package:freekake/helpers/color_helper.dart';
|
||||
import 'package:freekake/screen/pustaka/list_detail_screen.dart';
|
||||
import 'package:list_detail_extension/list_detail_extension.dart';
|
||||
import 'package:webview_flutter/webview_flutter.dart';
|
||||
import 'package:flutter/foundation.dart' show kIsWeb;
|
||||
|
||||
class ListEducation extends StatefulWidget {
|
||||
const ListEducation({super.key});
|
||||
final String? selectedCategory;
|
||||
const ListEducation({super.key, this.selectedCategory});
|
||||
|
||||
@override
|
||||
State<ListEducation> createState() => _ListEducationState();
|
||||
@@ -22,8 +24,7 @@ class _ListEducationState extends State<ListEducation> {
|
||||
late final WebViewController _controller;
|
||||
late String urlOrAssetPath;
|
||||
bool _shouldShowWebView = false;
|
||||
|
||||
// load extension
|
||||
String? selectedCategory;
|
||||
final listDetailExtension = ListDetailExtension();
|
||||
|
||||
Future<void> _initExtension() async {
|
||||
@@ -69,18 +70,55 @@ class _ListEducationState extends State<ListEducation> {
|
||||
""",
|
||||
"file": "assets/html/index.html",
|
||||
},
|
||||
{
|
||||
"title": "Memori Game",
|
||||
"image": "assets/html/freekake.png",
|
||||
"color": "#cef1da",
|
||||
"category": "Gizi",
|
||||
"type": "Materi",
|
||||
"point": "100",
|
||||
"coint": "20",
|
||||
"body":
|
||||
"""Game untuk melatih daya ingat siswa, sehingga bisa diharapkan bisa
|
||||
menemukan cara sendiri untuk mengingat sesuatu
|
||||
""",
|
||||
"file": "assets/html/memory/memory.html",
|
||||
},
|
||||
{
|
||||
"title": "Find Words",
|
||||
"image": "assets/html/freekake.png",
|
||||
"color": "#cef1da",
|
||||
"category": "Kesehatan",
|
||||
"type": "Materi",
|
||||
"point": "100",
|
||||
"coint": "20",
|
||||
"body": """
|
||||
No Descripptions
|
||||
""",
|
||||
"file": "assets/html/findwords/findwords.html",
|
||||
},
|
||||
];
|
||||
List<Map<String, dynamic>> filteredItems = [];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
filteredItems = List.from(_listContent);
|
||||
|
||||
selectedCategory = widget.selectedCategory;
|
||||
print(selectedCategory);
|
||||
if (selectedCategory != null && selectedCategory!.isNotEmpty) {
|
||||
filteredItems =
|
||||
_listContent
|
||||
.where((item) => item["category"] == selectedCategory)
|
||||
.toList();
|
||||
} else {
|
||||
filteredItems = List.from(_listContent);
|
||||
}
|
||||
if (!kIsWeb && (Platform.isAndroid || Platform.isIOS)) {
|
||||
_shouldShowWebView = true;
|
||||
_controller =
|
||||
WebViewController()..setJavaScriptMode(JavaScriptMode.unrestricted);
|
||||
urlOrAssetPath = "assets/makanan_bergizi/index.html";
|
||||
urlOrAssetPath = "assets/html/index.html";
|
||||
_loadContent(urlOrAssetPath);
|
||||
_initExtension();
|
||||
}
|
||||
@@ -92,18 +130,20 @@ class _ListEducationState extends State<ListEducation> {
|
||||
// Load dari Internet
|
||||
_controller.loadRequest(Uri.parse(path));
|
||||
} else {
|
||||
// Load dari assets lokal
|
||||
// String fileHtml = await rootBundle.loadString(path);
|
||||
String fileHtml = await DefaultAssetBundle.of(
|
||||
context,
|
||||
).loadString('assets/html/index.html');
|
||||
_controller.loadHtmlString(fileHtml);
|
||||
try {
|
||||
await rootBundle.load(path);
|
||||
await _controller.loadFlutterAsset(path);
|
||||
} catch (e) {
|
||||
print("Gagal memuat file HTML: $path\nError: $e");
|
||||
}
|
||||
_controller.loadFlutterAsset(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void filterSearch(String query) {
|
||||
setState(() {
|
||||
selectedCategory = null;
|
||||
if (query.isEmpty) {
|
||||
filteredItems = List.from(_listContent);
|
||||
} else {
|
||||
@@ -117,6 +157,7 @@ class _ListEducationState extends State<ListEducation> {
|
||||
|
||||
void filterByCategory(String category) {
|
||||
setState(() {
|
||||
selectedCategory = category;
|
||||
filteredItems =
|
||||
_listContent.where((item) {
|
||||
return item["category"].toLowerCase() == category.toLowerCase();
|
||||
@@ -126,7 +167,6 @@ class _ListEducationState extends State<ListEducation> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
String searchQuery = "";
|
||||
final List<Map<String, dynamic>> collections = [
|
||||
{
|
||||
"label": "Kesehatan",
|
||||
@@ -158,7 +198,8 @@ class _ListEducationState extends State<ListEducation> {
|
||||
collections
|
||||
.where(
|
||||
(item) => item["label"].toLowerCase().contains(
|
||||
searchQuery.toLowerCase(),
|
||||
// searchQuery.toLowerCase(),
|
||||
searchController.text.toLowerCase(),
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
@@ -176,7 +217,7 @@ class _ListEducationState extends State<ListEducation> {
|
||||
body: Column(
|
||||
children: [
|
||||
// Header Section
|
||||
headerContainer(context, filteredCollections),
|
||||
headerContainer(context, collections),
|
||||
// Collection Items dengan Filter
|
||||
SizedBox(height: 20),
|
||||
Expanded(child: contentContainer(context)),
|
||||
@@ -255,6 +296,7 @@ class _ListEducationState extends State<ListEducation> {
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children:
|
||||
filteredCollections.map((item) {
|
||||
final isSelected = selectedCategory == item["category"];
|
||||
return CollectionContainer(
|
||||
label: item["label"]!,
|
||||
imageSvg: item["image"]!,
|
||||
@@ -262,9 +304,16 @@ class _ListEducationState extends State<ListEducation> {
|
||||
iconh: 20,
|
||||
width: 70,
|
||||
height: 70,
|
||||
textColor: Colors.black,
|
||||
textColor:
|
||||
isSelected
|
||||
? const Color.fromARGB(255, 230, 48, 160)
|
||||
: Colors.black,
|
||||
lblSize: 10,
|
||||
colorContiner: ColorHelper.hexToColor(item["color"]),
|
||||
// colorContiner: ColorHelper.hexToColor(item["color"]),
|
||||
colorContiner:
|
||||
isSelected
|
||||
? const Color.fromARGB(255, 84, 3, 224)
|
||||
: ColorHelper.hexToColor(item["color"]),
|
||||
onTapAc:
|
||||
() => {
|
||||
searchController.clear(),
|
||||
@@ -347,36 +396,41 @@ class _ListEducationState extends State<ListEducation> {
|
||||
GridView _generateList() {
|
||||
return GridView.builder(
|
||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 1, // 2 Kolom
|
||||
crossAxisCount: 1,
|
||||
crossAxisSpacing: 10,
|
||||
mainAxisSpacing: 10,
|
||||
childAspectRatio: 2.5,
|
||||
),
|
||||
itemCount: _listContent.length,
|
||||
itemCount: filteredItems.length,
|
||||
itemBuilder: (context, index) {
|
||||
return GestureDetector(
|
||||
child: CardList(
|
||||
title: _listContent[index]["title"] ?? "",
|
||||
body: _listContent[index]["body"] ?? "",
|
||||
gambar: _listContent[index]['image'],
|
||||
point: _listContent[index]['coint'],
|
||||
coint: _listContent[index]['point'],
|
||||
tipe: _listContent[index]['tipe'],
|
||||
title: filteredItems[index]["title"] ?? "",
|
||||
body: filteredItems[index]["body"] ?? "",
|
||||
gambar: filteredItems[index]['image'],
|
||||
point: filteredItems[index]['point'],
|
||||
coint: filteredItems[index]['coint'],
|
||||
tipe: filteredItems[index]['type'],
|
||||
),
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder:
|
||||
(context) => listDetailExtension.buildPage({
|
||||
'title': filteredItems[index]['category'],
|
||||
'imagePath': filteredItems[index]['image'],
|
||||
'filepath': filteredItems[index]['file'],
|
||||
'paragraphs':
|
||||
"""
|
||||
"""
|
||||
"<h1> ${_listContent[index]["title"]} </h1> <p> ${_listContent[index]["body"]}",
|
||||
}),
|
||||
// (context) => listDetailExtension.buildPage({
|
||||
// 'title': filteredItems[index]['category'],
|
||||
// 'imagePath': filteredItems[index]['image'],
|
||||
// 'filepath': filteredItems[index]['file'],
|
||||
// 'paragraphs':
|
||||
// """
|
||||
// """
|
||||
// "<h1> ${filteredItems[index]["title"]} </h1> <p> ${filteredItems[index]["body"]}",
|
||||
// }),
|
||||
(context) => ListDetailScreen(
|
||||
title: filteredItems[index]['category'],
|
||||
// 'imagePath': filteredItems[index]['image'],
|
||||
filepath: filteredItems[index]['file'],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
|
||||
@@ -74,106 +74,11 @@ class _ListDetailScreenState extends State<ListPustakaDetailScreen> {
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// Padding(
|
||||
// padding: const EdgeInsets.all(20.0),
|
||||
// child: Row(
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// children: [
|
||||
// Image.asset(
|
||||
// widget.imagePath,
|
||||
// width: 100,
|
||||
// height: 100,
|
||||
// fit: BoxFit.cover,
|
||||
// ),
|
||||
// const SizedBox(width: 16),
|
||||
// Expanded(
|
||||
// child: Center(
|
||||
// child: Text(
|
||||
// widget.title,
|
||||
// style: const TextStyle(
|
||||
// fontSize: 22,
|
||||
// fontWeight: FontWeight.bold,
|
||||
// color: Colors.black,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
const SizedBox(height: 0),
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.only(left: 18.0, right: 18, bottom: 18),
|
||||
child:
|
||||
// ListView.builder(
|
||||
// itemCount: widget.paragraphs.length,
|
||||
// itemBuilder: (context, index) {
|
||||
// return
|
||||
// Padding(
|
||||
// padding: const EdgeInsets.only(bottom: 16.0),
|
||||
// child: Row(
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// children: [
|
||||
// Expanded(
|
||||
// child:
|
||||
// // Text(
|
||||
// // widget.paragraphs[index] +
|
||||
// // style: TextStyle(color: Colors.black),
|
||||
// Html(
|
||||
// // style: {
|
||||
// // "body": Style(
|
||||
// // color: const Color.fromRGBO(0, 0, 0, 1),
|
||||
// // ),
|
||||
// // },
|
||||
// data:
|
||||
// widget.paragraphs +
|
||||
// """
|
||||
// <html>
|
||||
// <!-- Text between angle brackets is an HTML tag and is not displayed.
|
||||
// Most tags, such as the HTML and /HTML tags that surround the contents of
|
||||
// a page, come in pairs; some tags, like HR, for a horizontal rule, stand
|
||||
// alone. Comments, such as the text you're reading, are not displayed when
|
||||
// the Web page is shown. The information between the HEAD and /HEAD tags is
|
||||
// not displayed. The information between the BODY and /BODY tags is displayed.-->
|
||||
// <head>
|
||||
// <title>Enter a title, displayed at the top of the window.</title>
|
||||
// </head>
|
||||
// <!-- The information between the BODY and /BODY tags is displayed.-->
|
||||
// <body>
|
||||
// <h1>Enter the main heading, usually the same as the title.</h1>
|
||||
// <p>Be <b>bold</b> in stating your key points. Put them in a list: </p>
|
||||
// <ul>
|
||||
// <li>The first item in your list</li>
|
||||
// <li>The second item; <i>italicize</i> key words</li>
|
||||
// </ul>
|
||||
// <p>Improve your image by including an image. </p>
|
||||
// <p><img src="http://www.mygifs.com/CoverImage.gif" alt="A Great HTML Resource"></p>
|
||||
// <p>Add a link to your favorite <a href="https://www.dummies.com/">Web site</a>.
|
||||
// Break up your page with a horizontal rule or two. </p>
|
||||
// <hr>
|
||||
// <p>Finally, link to <a href="page2.html">another page</a> in your own Web site.</p>
|
||||
// <!-- And add a copyright notice.-->
|
||||
// <p>© Wiley Publishing, 2011</p>
|
||||
// </body>
|
||||
// </html>
|
||||
// """,
|
||||
// ),
|
||||
// ),
|
||||
// // ),
|
||||
// // Checkbox(
|
||||
// // value: _readStatus[index],
|
||||
// // onChanged: (bool? value) {
|
||||
// // _toggleReadStatus(index);
|
||||
// // },
|
||||
// // ),
|
||||
// ],
|
||||
// ),
|
||||
// );
|
||||
// },
|
||||
// ),
|
||||
htmlBody(),
|
||||
child: htmlBody(),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user