Jak stworzyć hiperłącze w widżecie Flutter?


103

Chciałbym utworzyć hiperłącze, które będzie wyświetlane w mojej aplikacji Flutter.

Hiperłącze powinno być osadzone w Textlub podobnym widoku tekstowym, takim jak:

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

Masz jakąś wskazówkę, jak to zrobić?

Odpowiedzi:


169

Po prostu zawiń InkWell wokół widżetu Text i podaj UrlLauncher (z biblioteki usług) do atrybutu onTap. Zainstaluj UrlLauncher jako pakiet Flutter przed użyciem go poniżej.

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')
          ),
        ),
      ),
    );
  }
}

Możesz nadać styl widgetowi Tekst, aby wyglądał jak łącze.

Aktualizacja

Po dokładnym zbadaniu problemu znalazłem inne rozwiązanie, aby zaimplementować hiperłącza „w linii”, o które prosiłeś. Możesz użyć widgetu RichText z dołączonymi parametrami 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');
                  },
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

W ten sposób możesz faktycznie zaznaczyć jedno słowo i zrobić z niego hiperłącze;)


7
UrlLauncher nie jest już częścią flutter, został przeniesiony do wtyczki i zmieniono API .
Josef Adamcik

7
Musimy również dodać import: import 'package: flutter / gestures.dart'; import 'package: url_launcher / url_launcher.dart';
Alex Pliutau

5
Nie obsługujesz TapGestureRecognizerpoprawnie cyklu życia swojego . Musisz wywołać dispose()metodę, gdy RichTextnie jest już używana. Zobacz tutaj: api.flutter.dev/flutter/painting/TextSpan/recognizer.html
Alex Semeniuk

@AlexSemeniuk W twoim przykładzie używają StatefulWidget, w powyższej odpowiedzi jest to StatelessWidget. Czy na pewno musimy pozbyć się przypadku statelessWidget?
Corey Cole

2
@CoreyCole StatelessWidgetnie pozbędzie się TapGestureRecognizerCiebie w magiczny sposób . W rzeczywistości użycie StatelessWidgetw tym scenariuszu jest niepoprawne, ponieważ nie możesz w ten sposób pozbyć się swoich zasobów. I tak, absolutnie musisz wywołać dispose()metodę of TapGestureRecognizer, ponieważ uruchamia ona wewnętrzny zegar, który należy zatrzymać.
Alex Semeniuk

50

Flutter nie ma wbudowanej obsługi hiperłączy, ale możesz to zrobić samodzielnie. Przykład w galerii drawer.dart . Używają RichTextwidżetu zawierającego kolorowy TextSpan, który ma recognizeratrybut do obsługi dotknięć:

        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,
              ),
            ],
          ),

hiperłącze przeglądarka


Dzięki. Ale to nie jest to, czego szukam: wychodzę poza nawigację w aplikacji.
TaylorR

Nie jestem pewien, co masz na myśli, mówiąc „wykraczając poza nawigację w aplikacji”. Czy chcesz, aby link otwierał przeglądarkę?
Collin Jackson

Tak, łącze lub podobne, które można kliknąć, aby otworzyć w przeglądarce.
TaylorR

1
Tak właśnie działa próbka, z którą się łączyłem. Dodałem kilka zdjęć do odpowiedzi, aby to pokazać.
Collin Jackson

Link repo jest uszkodzony
Michel Feinstein

41

Można owinąć Textin GestureDetectori kliknij w uchwyt 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
  }
)

wprowadź opis obrazu tutaj


Masz rację, twoje rozwiązanie ma mniej linii niż inne, ale Inkwell jest widżetem do tego szczególnego zadania, więc przynajmniej semantycznie myślę, że to najlepsze rozwiązanie
dmarquina

2
@dmarquina Tak, możesz użyć InkWellzamiast GestureDetector.
CopsOnRoad

9

Jeśli chcesz, aby wyglądało jeszcze bardziej jak link, możesz dodać podkreślenie:

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

a wynik:

wprowadź opis obrazu tutaj


Nie można go kliknąć!
atilkan

Następnie zawiń go widżetem Button. :)
bartektartanus

8

Możesz użyć pakietu flutter_linkify
https://pub.dev/packages/flutter_linkify
Po prostu chcę zapewnić inną opcję.
Pakiet automatycznie podzieli Twój tekst i podświetli http / https
Połącz wtyczkę url_launcher możesz uruchomić url
Przykład poniżej:

wprowadź opis obrazu tutaj

pełny kod poniżej

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';
    }
  }
}

Jak możesz mieć 2 linki na tym samym widżecie? Na przykład „klikając to akceptujesz warunki użytkowania i politykę prywatności”, gdzie musimy mieć je razem
Dani,

1

Alternatywny (lub nie) sposób umieszczania klikalnych linków w Twojej aplikacji (dla mnie to po prostu działało):

1 - Dodaj pakiet url_launcher do pliku pubspec.yaml

(pakiet w wersji 5.0 nie działał dobrze dla mnie, więc używam 4.2.0 + 3).

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

2 - Zaimportuj go i użyj jak poniżej.

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';
    }
  }
}

Jeśli potrzebujesz hiperłącza między jakimś tekstem, możesz użyć tego FlatButtonsamego tła i koloru tekstu, co reszta twoich tekstów, więc sformatuj go za pomocą TextDecoration. podkreśl tak, jak pokazano powyżej
bartektartanus

1

Możesz użyć Link Text https://pub.dev/packages/link_text i używać go jak

 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,
      ),
    ),
  );
}

Pod Linuksem flutter pub getza to zawodziUnable to find a plugin.vcxproj for plugin "url_launcher_windows"
Eugene Gr. Philippov
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.