Введение и краткое изложение имитирующего однократного чтения приложения Flutter

Flutter

Предисловие:

  • Flutter перешел от бета-версии к версии 1.0 в 2018 г. Хотя выяснилось, что в версии 1.0 по-прежнему много ошибок, несовершенная экология, мало библиотек и плохая реализация некоторых функций, люди, которые обращают на это внимание, по-прежнему полны энтузиазма.Каждый день появляются новые вещи о выводе Flutter, что указывает на то, что многие люди все еще очень оптимистичны в этом отношении.
  • В Китае Alibaba и Tencent также активно проповедуют и делают много качественного обмена. Для пожара может потребоваться время, а для коммерческого использования тоже требуется мужество, но учиться и разбираться нужно еще сейчас.

О проекте:

На этот раз я решил сымитировать очень легкий проект单读App, в основном через проект, чтобы практиковать обычно используемые组件,布局,网络请求,json解析Ждать.

Подготовка проекта:

Этот проект черезCharlesИнструмент захвата пакетов для получения предметовApi,пройти черезApple Configurator 2инструменты для имитацииAppДля ознакомления и использования двух инструментов, пожалуйста, обратитесь к предыдущим статьям.Charles, одно из гималайских приложений Swift с высоким уровнем имитации, перехватывает пакеты, получает ресурсы изображения и т. д.

Исходный код проекта:

Flutter имитирует полный исходный код приложения для однократного чтения

Изображение эффекта:

主要效果图

Представлены основные пункты проекта в целом:

Возьмите главную страницу, которую вы видите, когда приходит проект, в качестве примера, чтобы представить макет:

На главной странице проекта используетсяPageView, текущий экран может видеть в реальном времениPageViewОдна страница, макет страницы в основном используетсяColumnвchildren: <Widget>[]обернуть все видыWidget, верхнее изображение используетnew Image.network()Чтобы получить изображение сети дисплея, средняя часть обернутаContainer、Text, можно использовать расстояние между компонентамиPaddingилиExpandedПриходите к живому управлению, выберите использование внизуRowОберните, как кнопки комментариев о напитках и т. Д.

主页面

Пример основного кода для главной страницы:

Вернуться к просмотру страниц:

 return Center(
      child: PageView.builder(
        itemCount: dataList.length,
        scrollDirection: Axis.vertical,
        itemBuilder: (context, index) {
          return calendarList(dataList[index],index,context);
        },
      ),
    );

Сетевой запрос и парсинг данных:

требуется в машиностроенииpubspec.yamlв файлеdependencies:введен вdio: ^1.0.13Эта библиотека является библиотекой сетевых запросов.^x.x.xэто номер версии. существуетdependencies:введен вjson_annotation:: ^2.0.0,существуетdev_dependencies:введен вjson_serializable: ^2.0.1 build_runner: ^1.1.2, Эти три библиотеки для синтаксического анализа json, которые можно использовать вместе для выполнения сетевых запросов и назначения данных для синтаксического анализа json, запомните верхний правый угол после завершения введения.Packages getодин раз.

Примеры использования следующие:

Объяснять: Поскольку это интерфейс захвата пакетов, захваченные пакеты содержат зашифрованныеsignПоле не взломано, что приводит к очень короткому тайм-ауту интерфейса, поэтому многоjsonДанные локального интерфейса также означают, что подкачки нет, но интерфейс текстового модуля является полученным сетевым интерфейсом, включая пейджинговые и раскрывающиеся соединения, поэтому проект может видеть локальныйjsonДанные и сетевые данные обрабатываются двумя способами.

для местныхjsonВведение файла, вы можете напрямую перетащитьjsonПерейдите в папку, созданную самим проектом, а затем вpubspec.yamlв файлеflutter:написать нижеassets:Представляет введение файлов ресурсов, а затем записывает конкретный путь.Например- json/HomeData.jsonОднако нужно обращать внимание на орфографию и пробелы.Ресурсы изображений, необходимые в том же проекте, также перетаскиваются в новую папку, а затем импортируются в нее.Packages getДля получения дополнительной информации вы можете просмотреть исходный код этого проекта.

местныйjsonданныеloadи пример разбора:

 void loadData() async{
    String cssStr = await DefaultAssetBundle.of(context).loadString('json/HomeData.json');
    CommonModel model = CommonModel.fromJson(json.decode(cssStr));
    setState(() {
      List<dynamic>data = [];
      data.addAll(model.datas);
      dataList.addAll(data);//给数据源赋值
    });
  }

Пример запроса и разбора сетевого интерфейса: Объясните, что iOS необходимо добавить доверенную аутентификацию Http при запросе интерфейса http, в частности, добавив код в папку iOS --> Runner-->info.plist

  /// 这里是请求接口数据,当滑动到最底端的时候会判断是否加载更多更改二个参数,post_id,page+1,然后把新请求的数据追加到以前的数据中
  void loadData(String post_id, int curPage,bool isMore) async{
    Dio dio = new Dio();
    Response response = await dio.get("http://203.195.230.211/index.php?m=Home&c=Api2&a=getTagList&tag=$tag&p=$curPage&client=iOS&show_sdv=1&page_id=$post_id&create_time=0&sign=24a904d18a786327741ca5613180ceda&time=1547092560&device_id=A39632E7-F689-405B-A3A3-0319D6095B54&version=1.6.2&client=iOS");
    CommonModel result = CommonModel.fromJson(response.data);
    setState(() {
      if(!isMore) {
        List<dynamic>data = [];
        data.addAll(result.datas);
        new_page_id = result.datas[data.length-1].id;
        dataList.addAll(data);//给数据源赋值
      }else{
        List<dynamic>data = [];
        data.addAll(result.datas);
        new_page_id = result.datas[data.length-1].id;
        dataList.addAll(data);
      }
    });
  }
}

Для создания модели данных:

Вот инструмент для автоматического созданияmodel,json2dart, как показано на рисунке:

Конкретное использование заключается в том, чтобы сначала создать, например, в проектеHomeDataModel.dartфайл, а затем используйте инструмент для созданияjsonформат, скопируйте его в файл ниже, обратите внимание наentityследует изменить наHomeDataModel, в это время терминал перейдет в корневую директорию проекта, т.е.lsможно увидетьpubspec.yamlкаталог, запуститьflutter packages pub run build_runner build, который будет автоматически сгенерирован через некоторое времяHomeDataModel.g.dartдокумент.

Перейти в раздел Главная здесь布局,数据模型,接口请求,数据解析Все хорошо, можно поставить значение для просмотра страницы с реальными данными, вот низ главной страницыRow, то есть, как и в некоторых примерах кода присваивания, подробности см. в исходном коде.

class _LikeWidgetState extends State<LikeWidget> {
  bool _isLike = true;
  void _togoLike() {
    setState(() {
      /// 如果是喜欢置为未喜欢
      if (_isLike) {
        _isLike = false;
        /// 如果是未喜欢置为喜欢
      } else {
        _isLike = true;
      }
    });
  }
  @override
  Widget build(BuildContext context) {
    return Row(
      children: <Widget>[
        new Expanded(
            child:new Row(
              children: <Widget>[
                new IconButton(
                    icon: Image.asset('assets/comment@2x.png'),
                    onPressed: (){
                      Navigator.of(context).push(new MaterialPageRoute(builder: (ctx) {
                        return new CommentPageStateful(post_id: widget.data.id);
                      }));
                    }
                ),
                new Text(
                  widget.data.comment,
                  style: TextStyle(
                    color: Colors.black,
                    fontSize: 16,
                  ),
                ),
                new IconButton(
                    icon: (_isLike ? new Image.asset("assets/like@2x.png") : new Image.asset("assets/liked@2x.png")),
                    onPressed: (){
                      _togoLike();
                    }
                ),
                new Text(
                  /// 这里是先通过int.parse(widget.data.good) string转int ,然后toString()再转成string
                  _isLike ? int.parse(widget.data.good).toString() : (int.parse(widget.data.good)+1).toString(),
                  style: TextStyle(
                    color: Colors.black,
                    fontSize: 16,
                  ),
                ),
              ],
            )
        ),
        new Container(
          padding: EdgeInsets.only(right: 15),
          child: new Text(
            '阅读数 '+widget.data.view,
            style: TextStyle(
              color: Colors.black,
              fontSize: 16,
            ),
          ),
        )
      ],
    );
  }
}

Пользовательский ящик:

Его видно через главную страницу, вверхуAppBarЛевая и правая кнопки могут всплывать влево и вправоDrawer, из-за системыDrawerНевозможно замаскировать весь экран, поэтому выберите здесьWidgetполноэкранная маскаDrawer.

Изображение эффекта:

左边导航页
右边导航页

настроитьDrawerОбразец кода:

/// 自定义的左边栏抽屉
class LeftDrawer extends StatefulWidget {
  final double elevation;
  final Widget child;
  final String semanticLabel;
  final double widthPercent;
  ///add start
  final DrawerCallback callback;
  ///add end
  const LeftDrawer({
    Key key,
    this.elevation = 16.0,
    this.child,
    this.semanticLabel,
    this.widthPercent,
    ///add start
    this.callback,
    ///add end
  })  : assert(widthPercent < 1.0 && widthPercent > 0.0),
        super(key: key);
  @override
  _LeftDrawerState createState() => _LeftDrawerState();
}

class _LeftDrawerState extends State<LeftDrawer> {

  @override
  Widget build(BuildContext context) {
    assert(debugCheckHasMaterialLocalizations(context));
    String label = widget.semanticLabel;
    final double _width = MediaQuery.of(context).size.width * widget.widthPercent;
    return Semantics(
      scopesRoute: true,
      namesRoute: true,
      explicitChildNodes: true,
      label: label,
      child: ConstrainedBox(
        constraints: BoxConstraints.expand(width: _width),
        child: Material(
          color: Colors.black87,
          elevation: widget.elevation,
          child: Container(
          ),
        ),
      ),
    );
  }

для левого и правогоDrawerТекстовая кнопка имеет анимацию увеличения, анимация шрифта используетanimated_text_kit: ^1.2.0, Есть несколько анимаций, вы можете обратиться к исходному коду для получения подробной информации, конкретное использование - импортimport 'package:animated_text_kit/animated_text_kit.dart';

  Widget _AnimatedText(String str){
    return SizedBox(
      child: ScaleAnimatedTextKit(
        duration: Duration(milliseconds: 4000),
        isRepeatingAnimation: false,
        text:[str],
        textStyle: TextStyle(
            fontSize: 35,
            color: Colors.white
        ),
      ),
    );
  }

О загрузке WebView:

Flutterиспользуется вWebView, вы можете использоватьflutter_webview_plugin: ^0.3.0+2Плагин, он также очень прост в использовании и импорте заголовочных файлов.import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';

Widget _WebView(String url) {
  return WebviewScaffold(url: url);
}

Используйте этот плагин для отображения общегоWebViewстраницу, но в моем проектеWebViewверх страницыAppBar, На нем все еще есть кнопка, как показано на рисунке ниже, нажмите кнопку, чтобы перейти к интерфейсу комментариев, но используйте этот плагин, потому что возвращаемыйWebviewScaffold, так когдаWebViewКогда страница переходит на другие страницы, эта страница всегда будет вверху других страниц, хотя вы можете использоватьwidget.flutterWebviewPlugin.close();чтобы закрыть страницу, но это означает, что вы не сможете увидеть ее, когда вернетесьWebViewСодержание страницы, и я хотел пойти авторуgithubИщу ответ, видел кого-то уже упомянутогоissueНо ярлык, данный автором, подлежит разрешению. Кто знает, как решить эту проблему, пожалуйста, просветите меня.

WebView页面
И если это просто простая нагрузкаWebViewстраницу, вы также можете использоватьurl_launcher: ^4.0.1Плагин, этот плагин является системным плагином, который может не только отображатьWebViewПожалуйста, обратитесь к информации для конкретного использования страницы Стиль страницы после использования фиксируется Для конкретного использования, пожалуйста, обратитесь к следующей цитате.入import 'package:url_launcher/url_launcher.dart';

  void _launchURL(String url, BuildContext context) async {
    if (await canLaunch(url)) {
      await launch(url);
    } else {
      throw 'Could not launch $url';
    }
  }
  
  onTap: (){
    _launchURL(data.html5, context);
  },

url_launcherпоказыватьWebViewСтиль страницы:

url_launcher显示的WebView页面样式

Объяснять:

В этом проекте есть два вида загрузкиWebViewИспользуются методы страницы и используется вторая страница текстового модуля.DetailСтраница используетflutter_webview_plugin, остальные страницы сведений используютurl_launcherпоказыватьWebViewстраница.

***Дополнительные примечания:

Нашел лучший после того, как группа друзей подсказалаwebviewметод загрузки, используйтеwebview_flutter: ^0.2.0плагин, сейчас в проектеWebViewВсе страницы были заменены этим методом, который можно настроить с помощью этого плагина.AppBar, и нет проблем с перескакиванием страниц, два вышеприведенныхwebviewСпособ загрузки можно выбрать самостоятельно.
Специально используется вpubspec.yamlвведен вwebview_flutter: ^0.2.0а такжеPackages getТеперь на странице нужно использоватьimport 'package:webview_flutter/webview_flutter.dart'; import 'dart:async';

Важно отметить, что на стороне iOS необходимо добавить настройки в info.plist.

plist设置
Пример использования исходного кода:

class WebViewExample extends StatelessWidget {
  final Completer<WebViewController> _controller =
  Completer<WebViewController>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView example'),
      ),
      body: WebView(
        initialUrl: 'https://www.baidu.com',
        javascriptMode: JavascriptMode.unrestricted,
        onWebViewCreated: (WebViewController webViewController) {
          _controller.complete(webViewController);
        },
      ),
    );
  }
}

Страница комментариев:

Просто для использованияflutter_webview_pluginизWebViewНажмите кнопку комментариев в правом верхнем углу страницы, чтобы перейти на страницу комментариев, потому что страница комментариев должна отображаться.HeaderView, так что выбирайsticky_headers: ^0.1.7Библиотека очень эффективна и удобна в использовании, внешний вид и подробный код смотрите в исходном коде.sticky_headersПример основного кода выглядит следующим образом:

       child: ListView.builder(
          itemCount: newsList.length+hotsList.length+1,
          itemBuilder: (context, index) {
            if (index == 0) {
              return StickyHeader(header: CommentHeader('喜欢', diggList.length, index),
              content: DiggList(diggList, diggList.length, context),
              );
            }else if (hotsList.length >0 && index < hotsList.length+1) {
              return StickyHeader(header: CommentHeader('最热评论', hotsList.length, index-1),
                content: HotsList(hotsList[index-1], index, context),
              );
            }else {
              return StickyHeader(header: CommentHeader('最新评论', newsList.length, index-hotsList.length-1),
                content: NewsList(newsList[index-hotsList.length-1], index, context),
              );
            }
          },
        ),

Рендеринг страницы комментариев:

评论页面

Разговор о странице:

В верхней части страницы обсуждения есть панель вкладок, и, проводя пальцем влево и вправо, можно переключаться между страницей вопроса для одного чтения и страницей читателя.

Пример кода выглядит следующим образом:

class TalkStateful  extends StatefulWidget {
  @override
  _TalkPageState createState() => new _TalkPageState();
}

class _TalkPageState extends State<TalkStateful> with SingleTickerProviderStateMixin {
  TabController _tabController;
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    _tabController = new TabController(vsync: this, initialIndex: 0, length: 2);
  }

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.black87,
        title: new Text('谈论', style: TextStyle(color: Colors.white,fontSize: 24),),
        bottom: new TabBar(
            isScrollable: false,//是否可滑动
            unselectedLabelColor: Colors.white,//未选中按钮颜色
            labelColor: Colors.white,//选中按钮颜色
            labelStyle: TextStyle(fontSize: 16),//文字样式
            indicatorSize: TabBarIndicatorSize.label,//滑动的宽度是根据内容来适应,还是与整块那么大(label表示根据内容来适应)
            indicatorWeight: 2.0,//滑块高度
            indicatorColor: Colors.black87,//滑动颜色
            indicatorPadding: EdgeInsets.only(bottom: 1),//与底部距离为1
            controller: _tabController,
            tabs: <Widget> [
              new Tab(
                text: '单读问',
              ),
              new Tab(
                text: '读者论',
              )
            ]
        ),
      ),
      body: new TabBarView(
          controller: _tabController,
          children: <Widget> [
            new DanDuWenPage(),
            new DuZheLunPage(),
          ]
      ),
    );
  }
}

Говоря о рендеринге страниц, можно сказать следующее:

单读问页面

读者论页面

Об этом проекте давайте представим его здесь.Если вы хотите узнать больше, пожалуйста, посмотрите часть исходного кода.Если вы ничего не понимаете или у вас есть вопросы, вы можете общаться друг с другом.

Примените настройки Icon и LaunchPage LaunchImage:

Пример основной папки проекта настройки iOS: flutter_dandu--> ios--> Runner--> Assets.xcassets--> AppIcon And LaunchImage

ios启动页和icon设置

Пример основной папки проекта Android: flutter_dandu-->android-->app-->src--main-->res

Android启动页和icon设置

Суммировать:

новичок вFlutterиспользоватьDartЯзык, это точно будет неудобно, слишком много вложенности трудно читать, но после понимания это нормально, в общем, давайте сейчас поговорим об этомFlutterБудущее еще немного впереди, но перспективы все еще очень хорошие.Если у вас есть время или клиентские специалисты по внешнему интерфейсу, вы можете подумать о том, чтобы начать работу и учиться. После того, как вы овладеете навыками, писать что-то очень быстро, кроссплатформенность — это общая тенденция, даже если нет.FlutterПоявятся другие. самое главное этоFlutterдаGoogleНовая система для мобильного оборудованияFuchsiaизUIСтруктура и переходные продукты все еще должны быть весьма оптимистичными.

Образовательные ресурсы:

Для больших парней это должны быть исходный код и официальные документы, а для новичков давайте поищем переводы и другие туториалы для больших парней. Вот несколько хороших ссылок на учебные ресурсы:
Серия базовых руководств:
1. Китайский сайт флаттера: https://flutterchina.club
2. Технический жир: бесплатное руководство по базовому видео Flutter
Технические статьи о больших парнях:
1.Талант /user/149189…
2.nuggets.capable/post/684490…
3.Талант /user/407224…
4.nuggets.capable/post/684490…
5.у-у-у. Краткое описание.com/U/5 от 5872 Цао Цао 9…
Флаттер круги и теги и знайте:
Трепетный круг: https://www.jianshu.com/c/ebc9d2e84214
Тег флаттера: https://juejin.cn/tag/Flutter
Флаттер знает: https://zhuanlan.zhihu.com/flutter
Флаттер-проповедник:
Техническая команда Сяньюй
Пример с открытым исходным кодом Flutter:
1.GitHub.com/2-Inc/Привет, тело…
2.flutterawesome.com
3.GitHub.com/solid O/awes…
Отличные проекты Flutter с открытым исходным кодом:
1. Клиентское приложение Github
2. Разработчики Flutter из аукционной команды Alibaba помогают приложению
3. Китайское приложение с открытым исходным кодом
4. Имитация приложения NetEase Cloud Music
5. Приложение Fake Book Flag Novel
6. Ежедневное приложение «Имитация любопытства»
7. Приложение для имитации одиночного чтения