Як створити гіперпосилання у віджеті Flutter?


97

Я хотів би створити гіперпосилання для відображення у моїй програмі Flutter.

Гіперпосилання має бути вбудовано в Textабо подібні текстові подання, наприклад:

The last book bought is <a href='#'>this</a>

Будь-яка підказка для цього?

Відповіді:


162

Просто оберніть InkWell навколо текстового віджета та поставте UrlLauncher (із бібліотеки послуг) до атрибута onTap. Встановіть UrlLauncher як пакет Flutter , перш ніж використовувати його нижче.

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:url_launcher/url_launcher.dart';


void main() {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text('UrlLauchner'),
        ),
        body: new Center(
          child: new InkWell(
              child: new Text('Open Browser'),
              onTap: () => launch('https://docs.flutter.io/flutter/services/UrlLauncher-class.html')
          ),
        ),
      ),
    );
  }
}

Ви можете надати стиль текстовому віджету, щоб він виглядав як посилання.

Оновлення

Трохи розглянувши проблему, я знайшов інше рішення для реалізації гіперпосилань, які ви просили. Ви можете використовувати віджет RichText із вкладеними TextSpans .

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:url_launcher/url_launcher.dart';

void main() {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text('UrlLauchner'),
        ),
        body: new Center(
          child: new RichText(
            text: new TextSpan(
              children: [
                new TextSpan(
                  text: 'This is no Link, ',
                  style: new TextStyle(color: Colors.black),
                ),
                new TextSpan(
                  text: 'but this is',
                  style: new TextStyle(color: Colors.blue),
                  recognizer: new TapGestureRecognizer()
                    ..onTap = () { launch('https://docs.flutter.io/flutter/services/UrlLauncher-class.html');
                  },
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

Таким чином ви можете насправді виділити одне слово та зробити з нього гіперпосилання;)


7
UrlLauncher більше не є частиною флаттера, його було переміщено до плагіна та змінено API .
Йозеф Адамчик

7
Також нам потрібно додати import: import 'package: flutter / gestures.dart'; імпортувати 'пакет: url_launcher / url_launcher.dart';
Алекс Плютау,

5
Ви не TapGestureRecognizerправильно обробляєте життєвий цикл свого . Ви повинні викликати dispose()метод, коли RichTextвін більше не використовується. Дивіться тут: api.flutter.dev/flutter/painting/TextSpan/recognizer.html
Олексій Семенюк

@AlexSemeniuk У вашому прикладі вони використовують StatefulWidget, у відповіді вище - StatelessWidget. Ви впевнені, що нам потрібно вирішити справу віджету без громадянства?
Кори Коул

2
@CoreyCole StatelessWidgetне буде магічно розпоряджатися вашими TapGestureRecognizerза вас. Насправді використання StatelessWidgetв цьому сценарії є неправильним, оскільки ви не можете розпоряджатися своїми джерелами ресурсів таким чином. І так, вам абсолютно потрібно викликати dispose()метод of TapGestureRecognizer, оскільки він запускає внутрішній таймер, який потрібно зупинити.
Олексій Семенюк

44

Flutter не має вбудованої підтримки гіперпосилань, але ви можете підробити це самостійно. Є приклад у Drawer.dart галереї . Вони використовують RichTextвіджет, що містить кольоровий TextSpan, який має recognizerатрибут для обробки кранів:

        RichText(
          text: TextSpan(
            children: [
              TextSpan(
                style: bodyTextStyle,
                text: seeSourceFirst,
              ),
              TextSpan(
                style: bodyTextStyle.copyWith(
                  color: colorScheme.primary,
                ),
                text: repoText,
                recognizer: TapGestureRecognizer()
                  ..onTap = () async {
                    final url = 'https://github.com/flutter/gallery/';
                    if (await canLaunch(url)) {
                      await launch(
                        url,
                        forceSafariVC: false,
                      );
                    }
                  },
              ),
              TextSpan(
                style: bodyTextStyle,
                text: seeSourceSecond,
              ),
            ],
          ),

гіперпосилання браузер


Дякую. Але це насправді не те, що я шукаю: я дивлюся за межі навігації в програмі.
TaylorR

Я не впевнений, що ви маєте на увазі під "поглядом за межі навігації в програмі". Ви хочете, щоб посилання відкрило браузер?
Коллін Джексон,

Так, посилання або подібне, яке можна натиснути, щоб відкрити в браузері.
TaylorR

1
Це те, що робить зразок, до якого я посилався. Я додав кілька відповідей до відповіді, щоб показати його.
Коллін Джексон,

Посилання на репо порушено
Мішель Файнштейн,

39

Ви можете обернути Textв систему GestureDetectorі натисніть ручку в onTap().

GestureDetector(
  child: Text("Click here", style: TextStyle(decoration: TextDecoration.underline, color: Colors.blue)),
  onTap: () {
    // do what you need to do when "Click here" gets clicked
  }
)

введіть тут опис зображення


Ви маєте рацію, у вашому рішенні менше рядків, ніж у інших, але Inkwell - це віджет для цієї конкретної роботи, тому, щонайменше семантично, я вважаю, що це найкраще рішення
dmarquina,

2
@dmarquina Так, ви можете використовувати InkWellзамість GestureDetector.
CopsOnRoad

7

Якщо ви хочете, щоб це виглядало ще більше як посилання, ви можете додати підкреслення:

new Text("Hello Flutter!", style: new TextStyle(color: Colors.blue, decoration: TextDecoration.underline),)

і результат:

введіть тут опис зображення


Це не можна натиснути!
atilkan

Потім оберніть його за допомогою віджета Button. :)
bartektartanus

7

Ви можете використовувати пакет flutter_linkify
https://pub.dev/packages/flutter_linkify
Просто хочу надати інший варіант.
Пакет розділить ваш текст і автоматично виділить http / https.
Об’єднайте плагін url_launcher, який ви можете запустити url.
Ви можете перевірити приклад нижче:

введіть тут опис зображення

повний код нижче

import 'package:flutter/material.dart';
import 'package:flutter_linkify/flutter_linkify.dart';
import 'dart:async';

import 'package:url_launcher/url_launcher.dart';

void main() => runApp(new LinkifyExample());

class LinkifyExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'flutter_linkify example',
      home: Scaffold(
        appBar: AppBar(
          title: Text('flutter_linkify example'),
        ),
        body: Center(
          child: Linkify(
            onOpen: _onOpen,
            text: "Made by https://cretezy.com \n\nMail: example@gmail.com \n\n  this is test http://pub.dev/ ",
          ),
        ),
      ),
    );
  }

  Future<void> _onOpen(LinkableElement link) async {
    if (await canLaunch(link.url)) {
      await launch(link.url);
    } else {
      throw 'Could not launch $link';
    }
  }
}

Як ви можете мати 2 посилання на одному віджеті? Наприклад, "наприклад," натиснувши тут, ви приймаєте умови використання та політику конфіденційності ", де нам потрібно їх зібрати
Дані

1

Альтернативний (чи ні) спосіб розміщення посилань, які можна натиснути, у своєму додатку (для мене це просто так працювало):

1 - Додайте пакет url_launcher у файл pubspec.yaml

(версія пакета 5.0 для мене не працювала, тому я використовую 4.2.0 + 3).

dependencies:
  flutter:
    sdk: flutter
  url_launcher: ^4.2.0+3

2 - Імпортуйте його та використовуйте, як показано нижче.

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

void main() {
  runApp(MaterialApp(
    title: 'Navigation Basics',
    home: MyUrl(),
  ));
}

class MyUrl extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Url Launcher'),
      ),
      body: Center(
        child: FlatButton(
          onPressed: _launchURL,
          child: Text('Launch Google!',
              style: TextStyle(fontSize: 17.0)),
        ),
      ),
    );
  }

  _launchURL() async {
    const url = 'https://google.com.br';
    if (await canLaunch(url)) {
      await launch(url);
    } else {
      throw 'Could not launch $url';
    }
  }
}

Якщо вам потрібне гіперпосилання між деяким текстом, ви можете використовувати такий FlatButtonже колір тла та тексту, як і решта ваших текстів, тому відформатуйте його за допомогою TextDecoration.underline, як показано вище
bartektartanus

0

Ви можете використовувати Текст посилання https://pub.dev/packages/link_text і використовувати його як

 final String _text = 'Lorem ipsum https://flutter.dev\nhttps://pub.dev'; 
 @override
 Widget build(BuildContext context) {
 return Scaffold(
     body: Center(
      child: LinkText(
        text: _text,
        textAlign: TextAlign.center,
      ),
    ),
  );
}

Під Linux flutter pub getце не вдаєтьсяUnable to find a plugin.vcxproj for plugin "url_launcher_windows"
Євген Гр. Філіппов
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.