Недавно столкнулся с требованием загрузить html в веб-проекте Flutter. На мобильном мы можем использоватьwebview_plugin
Плагин загружен, но он недействителен в Интернете. Итак, во Flutter Web, как загрузить html? Flutter предоставляет нам элемент управления специально для Интернета:HtmlElementView
. (В качестве отступления здесь написано, что в документе комментариев HtmlElementView написано, что построение html — дорогостоящая операция. Если есть эквивалентная реализация Flutter, которую можно заменить, постарайтесь не делать этого.)
Основные правила использования HtmlElementView
Будьте осторожны при использовании этого элемента управления,Перед использованием обязательна регистрация! ! !
допустимыйinitState()
При регистрации, конечно, вы также можетеrunApp()
Когда пора регистрироваться глобально (лично не рекомендую):
import 'dart:ui' as ui;
ui.platformViewRegistry.registerViewFactory(
'hello-world-html',
(int viewId) => HtmlElement();
ui.platformViewRegistry
Он сообщит о статической ошибке, не беспокойтесь об этом, это никак не повлияет на ваш код. пожалуйста, объясниregisterViewFactory()
В метод передаются два параметра: первое личное понимание — дать имя id фрагменту html, который нужно вставить, а второй параметр — это соответствующий элемент, который фактически используется для загрузки html. здесьHtmlElement()
Это базовый класс, который следует передавать при написании.IFrameElement
,HtmlHtmlElement
,MediaElement
,BodyElement
и так далее для элементов, которые вам действительно нужны.
использоватьHtmlElementView
, вам нужно только передать идентификатор, соответствующий зарегистрированному элементу:
HtmlElementView(
viewType: 'hello-world-html',
)
Загрузить URL
Можно использовать URL загрузкиIFrameElement
(Пожалуйста, напишите весь адрес, не пропуститеhttps
):
ui.platformViewRegistry.registerViewFactory(
'hello-world-html',
(int viewId) => IFrameElement()
..style.border = 'none'
..src = 'https://www.baidu.com');
Загрузить локальный html-файл
ui.platformViewRegistry.registerViewFactory(
'hello-world-html',
(int viewId) => IFrameElement()
..style.border = 'none'
..src = '/assets/test2.html');
загрузить html-строку
- Загрузить более сложный смешанный HTML (короче)
Если это HTML, смешанный с различными тегами, вы можете использоватьHtmlHtmlElement
:
ui.platformViewRegistry.registerViewFactory(
'hello-world-html',
(int viewId) => HtmlHtmlElement()
..style.border = 'none'
..setInnerHtml(html));
Обратите внимание на ямки здесь, потому что html, используемый в реальном проекте, содержит<img>
,<a href>
Ярлык и тому подобное нормальные, но если загрузить картинку, то гиперссылка не отображается указанным выше образом, потому что по умолчаниюHtmlHtmlElement
Эти теги отключены (предположительно для производительности, в конце концов, как я сказал в начале, Flutter на самом деле не хочет, чтобы вы загружали html-теги напрямую), вам нужно вручную включить загрузку сложных тегов. Конкретный метод заключается в передачеvalidator
параметр:
final NodeValidator _validator = NodeValidatorBuilder.common()
..allowElement('img', attributes: ['src'], uriPolicy: _AllowUriPolicy())
..allowElement('a', attributes: ['href'], uriPolicy: _AllowUriPolicy());
ui.platformViewRegistry.registerViewFactory(
'hello-world-html',
(int viewId) => HtmlHtmlElement()
..style.border = 'none'
..setInnerHtml(html,validator: _validator));
class _AllowUriPolicy implements UriPolicy {
@override
bool allowsUri(String uri) {
return true;
}
}
- Загрузить более сложный смешанный HTML (длиннее)
Если это длинный html, если вы используетеHtmlHtmlElement
Загрузившись, вы обнаружите, что страницу невозможно прокрутить. нужно пройтиScrollView
Комбинированный дисплей, но будьте осторожны,HtmlElementView
Необходимо рассчитать высоту:
ui.platformViewRegistry.registerViewFactory(
'hello-world-html',
(int viewId) => HtmlElementView()
..style.border = 'none'
..innerHtml = content);
Про расчет: можно пройтиscrollOffset
Получить высоту, но будет проблема с этим получением высоты, высота точна при входе на страницу в первый раз, но если вы измените размер окна, высота станет неточной. Временным решением является принудительная повторная отправка страницы при прослушивании изменения размера окна (во Flutter Web изменение размера самого окна восстановит текущую страницу, включая виджеты и данные, но это похоже на повторную отправку). он другой, с какими-то кешированными данными?scrollOffset
приобретенныйHtmlElementView
высота увеличивается без проводов). Если у вас есть лучшее решение, пожалуйста, оставьте сообщение и дайте мне знать.
мощныйIFrameElement
Вы также можете загрузить смешанный HTML, используяsrcdoc
способ загрузки, но IFrameElement, если иScrollView
Совмещать будет хлопотнее, высоту этой штуки рассчитать не так-то просто (надеюсь, здоровяк, умеющий считать, меня научит):
ui.platformViewRegistry.registerViewFactory(
'hello-world-html',
(int viewId) => IFrameElement()
..style.border = 'none'
..srcdoc = content);
- Загрузите html одного тега
Рекомендуется использовать легкийMediaElement
,BodyElement
,FormElement
,MenuElement
и т.п.