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ć?

TaylorR
źródło

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

Rainer Wittmann
źródło
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

Collin Jackson
źródło
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

CopsOnRoad
źródło
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

bartektartanus
źródło
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: [email protected] \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';
    }
  }
}
chunhunghan
źródło
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';
    }
  }
}
Fellipe Sanches
źródło
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,
      ),
    ),
  );
}
Syed Ahsan Ali
źródło
Pod Linuksem flutter pub getza to zawodziUnable to find a plugin.vcxproj for plugin "url_launcher_windows"
Eugene Gr. Philippov