<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Flutter on Colinx Blog</title>
    
    
    
    <link>/tags/flutter/</link>
    <description>Recent content in Flutter on Colinx Blog</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Tue, 30 Mar 2021 00:00:00 +0000</lastBuildDate>
    
	<atom:link href="/tags/flutter/index.xml" rel="self" type="application/rss+xml" />
    
    
    <item>
      <title>Flutter 拖动排序列表与跨平台优化实践</title>
      <link>/posts/flutter-%E6%8B%96%E5%8A%A8%E6%8E%92%E5%BA%8F%E5%88%97%E8%A1%A8%E4%B8%8E%E8%B7%A8%E5%B9%B3%E5%8F%B0%E4%BC%98%E5%8C%96%E5%AE%9E%E8%B7%B5/</link>
      <pubDate>Tue, 30 Mar 2021 00:00:00 +0000</pubDate>
      
      <guid>/posts/flutter-%E6%8B%96%E5%8A%A8%E6%8E%92%E5%BA%8F%E5%88%97%E8%A1%A8%E4%B8%8E%E8%B7%A8%E5%B9%B3%E5%8F%B0%E4%BC%98%E5%8C%96%E5%AE%9E%E8%B7%B5/</guid>
      <description>
        
          
          
          
        
        
        &lt;!-- # Flutter 拖动排序列表与跨平台优化实践 --&gt;

&lt;p&gt;Flutter 中实现拖动排序的列表非常简单，使用官方的&lt;code&gt;ReorderableListView&lt;/code&gt;替代原本的&lt;code&gt;ListView&lt;/code&gt;即可，&lt;code&gt;ListView.builder&lt;/code&gt;同理。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-dart&#34;&gt;  return ReorderableListView(
    // padding: const EdgeInsets.symmetric(horizontal: 40),
    children: &amp;lt;Widget&amp;gt;[
      for (int index = 0; index &amp;lt; _items.length; index++)
        ListTile(
          key: Key(&#39;$index&#39;),
          tileColor: _items[index].isOdd ? oddItemColor : evenItemColor,
          title: Text(&#39;Item ${_items[index]}&#39;),
        ),
    ],
    onReorder: (int oldIndex, int newIndex) {
      setState(() {
        if (oldIndex &amp;lt; newIndex) {
          newIndex -= 1;
        }
        final int item = _items.removeAt(oldIndex);
        _items.insert(newIndex, item);
      });
    },
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;上面是官方给的 demo，简洁明了。&lt;a href=&#34;https://www.youtube.com/watch?v=yll3SNXvQCw&#34;&gt;官方介绍视频&lt;/a&gt;下面的评论里，人家直呼比原生 Android 写的过瘾的多。阅读文档后我给我的 App 的界面也加上了可拖动排序的功能。效果如下图&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://blog-1301127393.file.myqcloud.com/BlogImgs/20210330234001.png&#34; alt=&#34;截屏 2021-03-30 23.04.59&#34; /&gt;&lt;/p&gt;

&lt;p&gt;虽然可以实现拖动了，但是右边有一个按钮很碍眼。不过这个是用来控制拖动的，鼠标移上去才能触发拖动。&lt;/p&gt;

&lt;p&gt;翻了翻文档发现，这个地方&lt;code&gt;ReorderableListView&lt;/code&gt;在移动端和桌面端的处理是不一样的，上图（桌面 macos）右边会出现一个 dragHandler，而移动端则是靠长按列表项触发拖动。&lt;/p&gt;

&lt;p&gt;要把这个碍眼的图标去掉，有两个方案：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;找到定义这个图标的地方，更换一个合适的图标，并在外面包裹一层，仅在鼠标 hover 时将图标显示以进行拖动，其他情况下隐藏&lt;/li&gt;
&lt;li&gt;将拖动的实现定义为和移动端相同，即都通过长按列表项触发拖动&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;针对方案一，以&lt;code&gt;ReorderableListView&lt;/code&gt; 和&lt;code&gt;Icon&lt;/code&gt;为关键词搜索，很遗憾的是并没有这方面的资料，又翻了翻源码，并没有找到可以自定义右边这个拖拽按钮的实现。&lt;/p&gt;

&lt;p&gt;在 Flutter 官方的 Github 仓库的 issue 中，&lt;a href=&#34;https://github.com/flutter/flutter/issues/66080#issuecomment-771123430&#34;&gt;https://github.com/flutter/flutter/issues/66080#issuecomment-771123430&lt;/a&gt;   对相关问题做了阐述，并有提案对&lt;code&gt;ReorderableListView&lt;/code&gt;进行了改进。该 issue 对应的 pr 已经被合并到 stable channel，查阅相关 API 后了解到可以使用&lt;code&gt;buildDefaultDragHandles: false&lt;/code&gt;，关闭默认的拖拽触发实现，再使用&lt;code&gt;ReorderableDelayedDragStartListener&lt;/code&gt;包裹原先的&lt;code&gt;ListTile&lt;/code&gt;即可实现桌面端和移动端都通过长按列表项触发拖拽排序。&lt;/p&gt;

&lt;p&gt;不过相应的，ListTile 的&lt;code&gt;onLongPress&lt;/code&gt;就不能再有响应了。刚好今天完成了滑动删除的实现，现在列表也的删除、排序已经高度可用且多平台统一了。&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://blog-1301127393.file.myqcloud.com/BlogImgs/20210330233350.png&#34; alt=&#34;截屏 2021-03-30 23.21.32&#34; /&gt;&lt;/p&gt;

&lt;p&gt;附相关代码实现：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-dart&#34;&gt;body: ReorderableListView.builder(
  buildDefaultDragHandles: false,
  onReorder: (int oldIndex, int newIndex) {
    setState(() {
      if (oldIndex &amp;lt; newIndex) newIndex -= 1;
      var temp = l.removeAt(oldIndex);
      l.insert(newIndex, temp);
    });
  },
  itemCount: l.length,
  itemBuilder: (context, index) {
    final item = l[index];
    return Dismissible(
        key: item.key,
        background: listTileBackground(),
        onDismissed: (direction) {
          setState(() {
            lastDeleted = item;
            l.removeAt(index);
          });
          ScaffoldMessenger.of(context).showSnackBar(msgDeleted);
        },
        child: ReorderableDelayedDragStartListener(
            key: item.key,
            index: index,
            child: ListTile(
              title: Text(item.title),
              subtitle: Text(item.content),
              contentPadding: EdgeInsets.fromLTRB(16, 8, 16, 8),
              onTap: () {
                //your function here
              },
              // onLongPress: () {
              //   lastDeleted = item;
              //   l.removeAt(index);
              //   setState(() {});
              //   ScaffoldMessenger.of(context)
              //       .showSnackBar(msgDeleted);
              // },
            )));
  })));
&lt;/code&gt;&lt;/pre&gt;

        
        </description>
    </item>
    
    <item>
      <title>Colin&#39;s 实验室 - 2021 春</title>
      <link>/posts/colins-%E5%AE%9E%E9%AA%8C%E5%AE%A4-2021%E6%98%A5/</link>
      <pubDate>Thu, 25 Feb 2021 00:00:00 +0000</pubDate>
      
      <guid>/posts/colins-%E5%AE%9E%E9%AA%8C%E5%AE%A4-2021%E6%98%A5/</guid>
      <description>
        
          
          
          
        
        
        

&lt;!-- # Colin&#39;s 实验室  - 2021 春 --&gt;

&lt;blockquote&gt;
&lt;p&gt;小玩具及他们的 demo&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;英语文本智能查词-project-sweeper&#34;&gt;英语文本智能查词（Project Sweeper）&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;自动分割给定的英文文本，提取词元后在数据库中搜索，根据给定的词汇量和难度等级进行筛选，只能提取阅读障碍词汇并高亮当前备考项目（如四级）的重点单词&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&#34;https://blog-1301127393.file.myqcloud.com/BlogImgs/20210330233722.jpg&#34; alt=&#34;360 截图 20210206210445677&#34; /&gt;&lt;/p&gt;

&lt;h2 id=&#34;知乎爬虫及-js-逆向&#34;&gt;知乎爬虫及 JS 逆向&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;日常用 RSS 订阅知乎的一些高质量专栏。但由于知乎本事并不支持 RSS，内容大多通过 RSShub 来的，其本质是个爬虫，经常会受到前端页面结构变更的影响。为了应对这个变化，RSShub 中对于知乎相关页面的爬取规则必须得重写。&lt;/p&gt;

&lt;p&gt;分析了一通知乎的页面，发现有个接口可以直接请求，但是会检验 header。header 里面有几项特殊的自定义参数，&lt;code&gt;x-zse-83&lt;/code&gt;  和 &lt;code&gt;x-zse-86&lt;/code&gt;等。为了搞清楚这里面的数值怎么来的，就必须对知乎前端页面资源中的一个 js 文件进行逆向分析。&lt;/p&gt;

&lt;p&gt;逆向折腾了大半天，就快要成功提取核心加密函数的时候，发现知乎的前端页面为了 SEO 有加入一页的文章列表数据，可以直接用上。考虑到逆向的工作量和潜在的法律问题，遂放弃原本的方案。&lt;/p&gt;

&lt;p&gt;新的方案完成后，已向 RSShub 提交 PR 并已被合并。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;mc-服务器搭建与极限优化&#34;&gt;MC 服务器搭建与极限优化&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;1 核 2G 学生机，从 2 人联机频频崩溃到 8 人挖矿毫无压力，学习了 JVM GC 种种，对服务端程序的一些参数也渐渐熟悉。优化效果喜人，总有还能压榨的性能，就像资本家看手下的骡子一样 hhh&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&#34;https://blog-1301127393.file.myqcloud.com/BlogImgs20210207205949.png&#34; alt=&#34;屏幕截图 (12)&#34; /&gt;&lt;/p&gt;

&lt;h2 id=&#34;洞洞板-冰箱贴-cvpro-没想好名字&#34;&gt;洞洞板/冰箱贴/CVPRO/（&amp;hellip;没想好名字）&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;一款跨平台的灵感素材收集与简易管理 App，基于 Flutter 构建，跨平台，颜值在线。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&#34;https://blog-1301127393.file.myqcloud.com/BlogImgs/20210330233350.png&#34; alt=&#34;截屏 2021-03-30 23.21.32&#34; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;持续开发中，附 roadmap&lt;/p&gt;

&lt;p&gt;version 1.0&lt;/p&gt;

&lt;p&gt;[x] Text support&lt;br /&gt;
[x] Key shortcut support&lt;br /&gt;
[x] About Page&lt;br /&gt;
[ ] Content editing&lt;br /&gt;
[x] List item dismiss
[x] List Sorting&lt;/p&gt;

&lt;p&gt;Future - Key functions&lt;/p&gt;

&lt;p&gt;[ ] Data Storage&lt;br /&gt;
[ ] Pic support&lt;br /&gt;
[ ] Trashbin&lt;br /&gt;
[ ] File support&lt;br /&gt;
[ ] Multiple List&lt;/p&gt;

&lt;p&gt;Future - Key features&lt;/p&gt;

&lt;p&gt;[ ] Grid view&lt;br /&gt;
[ ] Drag and Drop support&lt;br /&gt;
[ ] Card resize&lt;/p&gt;

&lt;p&gt;Future - Extra&lt;/p&gt;

&lt;p&gt;[ ] Text reformat, delete useless spaces etc.&lt;br /&gt;
[ ] Pic OCR support&lt;br /&gt;
[ ] WebDav support and automatically upload files&amp;lt;10M&lt;/p&gt;
&lt;/blockquote&gt;

        
        </description>
    </item>
    
  </channel>
</rss>