¿Cómo crear un hipervínculo en el widget Flutter?

97

Me gustaría crear un hipervínculo para mostrar en mi aplicación Flutter.

El hipervínculo debe estar incrustado en una Textvista de texto o similar como:

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

¿Alguna pista para hacer esto?

TaylorR
fuente

Respuestas:

161

Simplemente envuelva un InkWell alrededor de un widget de texto y proporcione un UrlLauncher (de la biblioteca de servicios) al atributo onTap. Instale UrlLauncher como un paquete de Flutter antes de usarlo a continuación.

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

Puede proporcionar un estilo al widget Texto para que parezca un enlace.

Actualizar

Después de investigar un poco el problema, encontré una solución diferente para implementar los hipervínculos 'en línea' que solicitó. Puede utilizar el widget RichText con TextSpans adjuntos .

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

De esta manera, puede resaltar una palabra y hacer un hipervínculo con ella;)

Rainer Wittmann
fuente
7
UrlLauncher ya no es parte de flutter, se movió a un complemento y se cambió la API .
Josef Adamcik
7
También necesitamos agregar importaciones: import 'package: flutter / gestures.dart'; importar 'paquete: url_launcher / url_launcher.dart';
Alex Pliutau
4
No está manejando TapGestureRecognizercorrectamente el ciclo de vida de su . Tienes que llamar al dispose()método cuando RichTextya no se usa. Ver aquí: api.flutter.dev/flutter/painting/TextSpan/recognizer.html
Alex Semeniuk
@AlexSemeniuk En su ejemplo, están usando un StatefulWidget, en la respuesta anterior es un StatelessWidget. ¿Estás seguro de que necesitamos deshacernos de la carcasa de un StatelessWidget?
Corey Cole
2
@CoreyCole StatelessWidgetno lo desechará mágicamente TapGestureRecognizerpor usted. De hecho, usar StatelessWidgeten este escenario es incorrecto, ya que no puede deshacerse de sus recursos de esta manera. Y sí, es absolutamente necesario llamar al dispose()método de TapGestureRecognizer, ya que ejecuta el temporizador interno que debe detenerse.
Alex Semeniuk
44

Flutter no tiene soporte de hipervínculo incorporado, pero puedes fingirlo tú mismo. Hay un ejemplo en drawer.dart de la Galería . Usan un RichTextwidget que contiene un color TextSpan, que tiene un recognizeratributo para manejar toques:

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

Hipervínculo navegador

Collin Jackson
fuente
Gracias. Pero esto no es realmente lo que estoy buscando: estoy mirando más allá de la navegación dentro de la aplicación.
TaylorR
No estoy seguro de lo que quiere decir con "mirar más allá de la navegación en la aplicación". ¿Quieres que el enlace abra un navegador?
Collin Jackson
Sí, un enlace o similar en el que se puede hacer clic para abrir en una exploración.
TaylorR
1
Eso es lo que hace la muestra a la que he vinculado. Agregué algunas imágenes a la respuesta para mostrarla.
Collin Jackson
El enlace de repositorio está roto
Michel Feinstein
39

Usted puede envolver su Texten GestureDetectory mango clic en 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
  }
)

ingrese la descripción de la imagen aquí

CopsOnRoad
fuente
Tienes razón, tu solución tiene menos líneas que la de otras, pero Inkwell es el widget para este trabajo específico, así que al menos semánticamente creo que es la mejor solución
dmarquina
2
@dmarquina Sí, puedes usar en InkWelllugar de GestureDetector.
CopsOnRoad
7

Si desea que se parezca aún más a un enlace, puede agregar un subrayado:

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

y el resultado:

ingrese la descripción de la imagen aquí

bartektartanus
fuente
¡No se puede hacer clic!
Atilkan
Luego envuélvalo con el widget de botón. :)
bartektartanus
7

Puede usar el paquete flutter_linkify
https://pub.dev/packages/flutter_linkify
Solo quiero proporcionar otra opción.
El paquete dividirá su texto y resaltará http / https automáticamente.Combine el
plugin url_launcher, puede iniciar la url
.

ingrese la descripción de la imagen aquí

código completo a continuación

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
fuente
¿Cómo puedes tener 2 enlaces en el mismo widget? Como, por ejemplo, "al hacer clic aquí, acepta los términos de uso y la política de privacidad" donde debemos tenerlos juntos
Dani hace
1

Una forma alternativa (o no) de colocar enlaces en los que se puede hacer clic en su aplicación (para mí simplemente funcionó de esa manera):

1 - Agregue el paquete url_launcher en su archivo pubspec.yaml

(La versión del paquete 5.0 no funcionó bien para mí, así que estoy usando 4.2.0 + 3).

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

2 - Importarlo y usarlo como se muestra a continuación.

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
fuente
Si necesita un hipervínculo entre algún texto, puede usar uno FlatButtoncon el mismo fondo y colores de texto que el resto de sus textos, así que formatee con TextDecoration.underline como el bartektartanus mostrado arriba ...
Fellipe Sanches
0

Puede usar Link Text https://pub.dev/packages/link_text y usarlo como

 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
fuente
Bajo Linux flutter pub getporque falla conUnable to find a plugin.vcxproj for plugin "url_launcher_windows"
Eugene Gr. Philippov