Làm cách nào để tạo siêu liên kết trong tiện ích Flutter?


98

Tôi muốn tạo một siêu liên kết để hiển thị trong ứng dụng Flutter của mình.

Siêu liên kết phải được nhúng trong một Texthoặc các dạng xem văn bản tương tự như:

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

Bất kỳ gợi ý để làm điều này?

Câu trả lời:


162

Chỉ cần quấn InkWell xung quanh tiện ích Văn bản và cung cấp UrlLauncher (từ thư viện dịch vụ) cho thuộc tính onTap. Cài đặt UrlLauncher dưới dạng gói Flutter trước khi sử dụng bên dưới.

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

Bạn có thể cung cấp một kiểu cho tiện ích Văn bản để làm cho nó giống như một liên kết.

Cập nhật

Sau khi xem xét vấn đề một chút, tôi đã tìm thấy một giải pháp khác để triển khai các siêu liên kết 'trong dòng' mà bạn yêu cầu. Bạn có thể sử dụng Widget RichText với TextSpans kèm theo .

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

Bằng cách này, bạn thực sự có thể đánh dấu một từ và tạo siêu liên kết từ nó;)


7
UrlLauncher không còn là một phần của sự bùng nổ nữa, nó đã được chuyển sang một plugin và API đã thay đổi .
Josef Adamcik

7
Ngoài ra, chúng ta cần thêm nhập khẩu: nhập khẩu 'package: Flagship / domains.dart'; nhập 'gói: url_launcher / url_launcher.dart';
Alex Pliutau

5
Bạn không xử lý đúng vòng đời của mình TapGestureRecognizer. Bạn phải gọi dispose()phương thức khi RichTextkhông còn được sử dụng. Xem tại đây: api.flutter.dev/flutter/painting/TextSpan/recognizer.html
Alex Semeniuk

@AlexSemeniuk Trong ví dụ của bạn, họ đang sử dụng StatefulWidget, trong câu trả lời ở trên, nó là StatelessWidget. Bạn có chắc chắn chúng ta cần xử lý trường hợp của StatelessWidget không?
Corey Cole

2
@CoreyCole StatelessWidgetsẽ không loại bỏ của bạn một cách kỳ diệu TapGestureRecognizer. Trên thực tế, sử dụng StatelessWidgettrong trường hợp này là không chính xác, vì bạn không thể loại bỏ rsources của mình theo cách này. Và có, bạn hoàn toàn cần gọi dispose()phương thức của TapGestureRecognizer, vì nó chạy bộ đếm thời gian bên trong cần được dừng lại.
Alex Semeniuk

44

Flutter không có hỗ trợ siêu liên kết tích hợp nhưng bạn có thể tự giả mạo nó. Có một ví dụ trong ngăn kéo của Thư viện . Họ sử dụng RichTexttiện ích con có chứa màu TextSpan, có recognizerthuộc tính để xử lý các lần nhấn:

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

siêu liên kết trình duyệt


Cảm ơn. Nhưng đây không thực sự là thứ tôi đang tìm kiếm: tôi đang tìm kiếm xa hơn điều hướng trong ứng dụng.
TaylorR

Tôi không chắc ý của bạn khi "nhìn xa hơn điều hướng trong ứng dụng". Bạn có muốn liên kết để mở trình duyệt không?
Collin Jackson

Có, một liên kết hoặc tương tự có thể được nhấp để mở trong trình duyệt.
TaylorR

1
Đó là những gì mẫu tôi liên kết với. Tôi đã thêm một số hình ảnh vào câu trả lời để hiển thị nó.
Collin Jackson

Liên kết repo bị hỏng
Michel Feinstein

39

Bạn có thể bọc của bạn Texttrong GestureDetectorvà xử lý nhấp chuột vào 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
  }
)

nhập mô tả hình ảnh ở đây


Bạn là đúng, giải pháp của bạn có dòng ít hơn những người khác, nhưng Inkwell là phụ tùng cho công việc especific này, vì vậy al nhất ngữ nghĩa tôi nghĩ Đó là giải pháp tốt nhất
dmarquina

2
@dmarquina Có, bạn có thể sử dụng InkWellthay thế GestureDetector.
CopsOnRoad

8

Bạn có thể sử dụng gói Flutter_linkify
https://pub.dev/packages/flutter_linkify
Chỉ muốn cung cấp một tùy chọn khác.
Gói sẽ phân chia văn bản của bạn và đánh dấu http / https tự động
Kết hợp plugin url_launcher bạn có thể khởi chạy url
Bạn có thể kiểm tra ví dụ bên dưới:

nhập mô tả hình ảnh ở đây

mã đầy đủ bên dưới

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

Làm thế nào bạn có thể có 2 liên kết trên cùng một widget? Ví dụ như "bằng cách nhấp vào đây, bạn chấp nhận các điều khoản sử dụng và chính sách bảo mật" nơi chúng ta cần phải có chúng cùng nhau
Dani

7

Nếu bạn muốn làm cho nó trông giống như một liên kết hơn, bạn có thể thêm gạch dưới:

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

và kết quả:

nhập mô tả hình ảnh ở đây


Nó không thể nhấp được!
atilkan

Sau đó, quấn nó xung quanh với tiện ích Nút. :)
bartektartanus

1

Một cách thay thế (hoặc không) để đặt các liên kết có thể nhấp vào ứng dụng của bạn (đối với tôi, nó chỉ hoạt động theo cách đó):

1 - Thêm gói url_launcher vào tệp pubspec.yaml của bạn

(phiên bản gói 5.0 không hoạt động tốt đối với tôi, vì vậy tôi đang sử dụng 4.2.0 + 3).

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

2 - Nhập nó và sử dụng như bên dưới.

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

Nếu cần một siêu liên kết giữa một số văn bản, bạn có thể sử dụng một FlatButtonvới cùng nền và màu văn bản như phần còn lại của văn bản của bạn, vì vậy định dạng nó whith TextDecoration.underline như bartektartanus trình bày ở trên ...
Fellipe Sanches

0

Bạn có thể sử dụng Văn bản liên kết https://pub.dev/packages/link_text và sử dụng nó như

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

Theo Linux, flutter pub getnó không thành công vớiUnable to find a plugin.vcxproj for plugin "url_launcher_windows"
Eugene Gr. Philippov
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.