0

I am trying to make a bookmark app that you can input a title and URL on a dailog and list these on ListTile. I can see passed value (title and URL) on ListTile now but I cannot open URL that is passed from the dialog yet. How can I open URL that I add on ListTile?

Here is the whole code

main.dart

void main() {
  runApp(const BookmarkApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Bookmark App',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
        useMaterial3: true,
      ),
      home:  BookmarkListPage(text: '', url: '',),
    );
  }
}

class BookmarkListPage extends StatefulWidget {
  BookmarkListPage({super.key, title, required this.text, required this.url});

  String text;
  String url;

  final String title = 'Bookmark List';

  @override
  State<BookmarkListPage> createState() => _BookmarkListPageState();
}

class _BookmarkListPageState extends State<BookmarkListPage> {

  List<String> bookmarkList = [];
  List<String> bookmarkUrl = [];

   _launchUrl() async {
    var url = Uri.parse(bookmarkUrl as String);
    if(await canLaunchUrl(url)) {
      await launchUrl(url);
    } else {
      throw "Could not open $url";
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.white,
        title: Text(widget.title),
        bottom: PreferredSize(
          child: Container(
            height: 1,
            color: Colors.black,
          ),
          preferredSize: Size.fromHeight(1),
        ),
      ),
      body: ListView.builder(
        itemCount: bookmarkList.length,
        itemBuilder: (context, index) {
          return Card(
            child: ListTile(
              title: Text(bookmarkList[index]),
              subtitle: Text(bookmarkUrl[index]),
              // TODO if you tap the List, open the URL
              onTap: _launchUrl,
            ),
          );
        },
      ),

      // show dialog
      floatingActionButton: FloatingActionButton(
        shape: const CircleBorder(),
        backgroundColor: Colors.blue,
        onPressed: () async {
          final (newBookmarkTitle, newBookmarkUrl) = await showDialog(
              context: context,
              builder: (_) {
                return BookmarkDialog();
              });

          setState(() {
            bookmarkList.add(newBookmarkTitle);
            bookmarkUrl.add(newBookmarkUrl);
          });


        },
        child: const Icon(
          Icons.add,
          color: Colors.white,
        ),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

dialog.dart

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

class BookmarkDialog extends StatefulWidget {
  const BookmarkDialog({super.key});

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

class BookMarkDialogState extends State<BookmarkDialog> {
  String bookmarkTitle = "";
  String bookmarkUrl = "";

  @override
  Widget build(BuildContext context) {
    return AlertDialog(
      title: const Text('Add Bookmark'),
      content: Column(
        children: [
          Text('Title'),
          TextField(onChanged: (value) {
            setState(() {
              bookmarkTitle = value;
            });
          }),
          Text('URL'),
          TextField(
            onChanged: (value) {
              setState(() {
                bookmarkUrl = value;
              });
            },
          )
        ],
      ),
      actions: <Widget>[
        GestureDetector(
          child: const Text('Cancel'),
          onTap: () {
            Navigator.pop(context);
          },
        ),
        GestureDetector(
          child: const Text('Add'),
          onTap: () {
            Navigator.of(context).pop((bookmarkTitle, bookmarkUrl));
          },
        )
      ],
    );
  }
}

1 Answer 1

2

Update _launchUrl to accept the index of thne item from which you can get the bookmarkUrl from the list

 _launchUrl(int index) async {
    var url = Uri.parse(bookmarkUrl[index]);
    if(await canLaunchUrl(url)) {
      await launchUrl(url);
    } else {
      throw "Could not open $url";
    }
  }

Then update the list item as to pass the url to _launchUrl

     Card(
        child: ListTile(
          title: Text(bookmarkList[index]),
          subtitle: Text(bookmarkUrl[index]),
          onTap:()=> _launchUrl(index),
        ),
      );
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.