Flutter中StreamBuilder的用法

先大概說說Stream的概念,這個Stream就是類似平常大家用的比較多的RxJava、RxSwift等框架的思路,它是一個異步數據的源,它可以接受任何數據,通過StreamController可以給這個Stream添加數據,如果這個Stream有監聽者就會接收到數據。 代碼如下:

import 'dart:async';

void main() {
  // 初始化一個Stream controller
  final StreamController ctrl = StreamController();
  // 添加一個監聽
  ctrl.stream.listen((data) => print('$data'));
  // 往Stream中添加數據
  ctrl.sink.add('這個是字符串'); //字符串類型
  ctrl.sink.add(1234);//int 類型
  ctrl.sink.add({'name': '姓名', 'content': 'json對象也行'});//對象類型
  ctrl.sink.add(123.45); //double類型
  // StreamController用完后需要釋放
  ctrl.close();
}

Read more ?

flutter數據監聽器

最近用Flutter做功能的時候,發現了這么一個控件ValueListenableBuilder,它也是一個Widget,從它的名字看應該是監聽數據,并且用新的數據生成Widget,它的參數就三個:

const ValueListenableBuilder({
    @required this.valueListenable,
    @required this.builder,
    this.child,
  }) 

參數說明

示例

從上面那些說明看來這個控件的作用就是作為局部刷新用的,可能我們整個頁面上只是一個小參數變化了,那有了這個Widget就不需要用setState(() {});來刷新整個頁面。

做個簡單的示例,這個示例是flutter默認生成的項目改寫的:

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  final ValueNotifier<int> _notifier = ValueNotifier<int>(0);

  void _incrementCounter() {
    _counter++;
    _notifier.value++;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ValueListenableBuilder(
                valueListenable: _notifier,
                builder: (BuildContext context, int value, Widget child) {
                  return Text(
                    'You have pushed the button this many times:$value',
                  );
                }),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), 
   );
  }
}

20190614-1.2019-06-14 15_36_31

Read more ?

flutter 白板工具

平常桌面上都放著一些草稿紙,因為經常要整理思路、畫畫草圖啥的。這不是電子時代嘛,就覺得在手機、pad上也可以這樣寫寫畫畫,我看了有很多這種類似的app,功能很簡單就一個白板,直接就可以畫,工具欄大概包括選畫筆顏色、選筆尖大小、選橡皮擦等。

于是我用Flutter簡單實現了一個,效果看下圖,可以選顏色和筆尖大小: 20190606-whiteboard.2019-06-06 09_48_24

主要思路

整體看這個功能實現不難,其實就是一個普通畫板,畫板我們可以用一個CustomPainter來做,關于CustomPainter我前面有文章有介紹過《Flutter 學習6:繪制動畫》

CustomPainter 根據拖動手勢,把手指滑動過的坐標畫出來,其實就是把點連成線,并且得知道當時的畫筆顏色和大小。

那拖動手勢當然用GestureDetector啦,拖動的時候用onPanUpdate事件來獲取坐標并且把坐標連成線,每次繪畫結束就用拖動結束事件來處理onPanEnd

Read more ?

android做一個類似釘釘的日歷時間選擇器

最近做一個日期選擇器,仿照釘釘上的,它有三種模式:日期選擇、日期間隔、日期+時間。日期是用一個月歷選擇的,時間是滾動的TimePicker。 大概的樣子是這樣的:

  1. 日期選擇

    1558069562450588.2019-05-17 13_12_38

  2. 日期間隔

1558069567543421.2019-05-17 13_13_27

  1. 日期+時間 1558069562438557.2019-05-17 13_11_08

Read more ?

IOS應用切換主題

應用切換主題,或者叫換皮膚,這在現在的應用中還是蠻常見,還有一些比如節日主題的需求也是一樣,都需要動態的切換顏色、背景、圖片等內容,這種情況其實應用開發開始的時候規劃蠻重要的,不然等到應用開發到一定程度再考慮往往工作量就會很大,修改的地方很多。

UIAppearance

開始考慮的時候發現官方有提供一個叫UIAppearance的代理類,說是處理全局統一管理IOS控件的樣式的。這個代理方式的思路蠻好的,把官方提供的所有IOS控件都進行處理,可以統一設置各種控件自身的樣式。而且代碼沒有侵入性。 比如:

// 設置主題色
UIApplication.shared.delegate?.window??.tintColor = theme.mainColor
// 設置NavigationBar的樣式
UINavigationBar.appearance().barStyle = .black
// 設置TabBar背景
UITabBar.appearance().backgroundImage = UIImage(named: "barBackground")
...

所以有這個代理類,我們只要定義好主題,然后切換的時候設置一下就都變過來了。 如下定義主題:

enum Theme: Int {
    case Red = 0
    case Blue = 1
    case Green = 2
    
    //主題色
    var mainColor: UIColor {
        switch self {
        case .Red:
            return UIColor.red
        case .Blue:
            return UIColor.blue
        case .Green:
            return UIColor.green
        }
    }
    ...
 }

切換主題:

static func applyTheme(theme: Theme) {
        // 保存當前主題
        UserDefaults.standard.set(theme.rawValue, forKey: SelectedThemeKey)
        UserDefaults.standard.synchronize()
        
        // 設置各個組件的主題色
        let sharedApplication = UIApplication.shared
        sharedApplication.delegate?.window??.tintColor = theme.mainColor
        UIApplication.shared.delegate?.window??.tintColor = theme.mainColor
  
        let navBar = UINavigationBar.appearance()
        navBar.barStyle = theme.barStyle
        navBar.tintColor = theme.barTextColor
        navBar.barTintColor = theme.mainColor
      
        let tabBar = UITabBar.appearance()
        tabBar.barStyle = theme.barStyle
        tabBar.barTintColor = theme.tabBarBackgroundColor
        
        UISwitch.appearance().tintColor = theme.mainColor


    }

UIAppearance.2019-04-22 13_15_49

可以看到直接設置window的tintColor是能馬上提現的,但是通過UIAppearance設置的就不行,它只能在view放到window之前設置才有效。比如上面我們設置好了主題,切換TabController內部的UIViewController,設置好的NavigationBar的背景顏色就體現出來了。

UIAppearance它其實有一個大統一的思路,它把所有同一類型的UI都進行了統一管理,但是實際業務比這個復雜的多,所以用它來做切換皮膚的功能難度還是很大的。

SwiftTheme

后來在GitHub上找到了一個國人寫的換膚框架,SwiftTheme。 先看效果: switch

Read more ?

Flutter Widget - PageView的使用

PageView 在Android中也是很常用的一個控件,可以配合TabBar、BottomBar做頁面切換。也有很多廣告Banner頁用PageView來實現。Flutter也有這個Widget,用法更靈活方便。

 PageView({
    Key key,
    this.scrollDirection = Axis.horizontal,
    this.reverse = false,
    PageController controller,
    this.physics,
    this.pageSnapping = true,
    this.onPageChanged,
    ...
  }) 

參數說明

默認構造

這個默認構造,一般用在多個頁面切換的場景下,只要放入固定的幾個頁面就行了。 例子代碼:

PageView(
      children: <Widget>[
        Container(
          color: Colors.red,
          child: Center(child: Text('第一頁', style: TextStyle(color: Colors.white),),),
        ),
        Container(
          color: Colors.blue,
          child: Center(child: Text('第二頁', style: TextStyle(color: Colors.white),),),
        ),
        Container(
          color: Colors.green,
          child: Center(child: Text('第三頁', style: TextStyle(color: Colors.white),),),
        ),
        Container(
          color: Colors.blueGrey,
          child: Center(child: Text('第四頁', style: TextStyle(color: Colors.white),),),
        )
      ],
    )

1554884412508646.2019-04-10 16_25_39

Read more ?

Flutter使用自定義的Icon

Flutter默認開啟了uses-material-designScreen Shot 2019-03-29 at 13.02.50 這使得我們在開發中可以輕松使用很多定義好的圖標,非常方便,也節約了很多設計或者找圖的時間。

但需求無止境嘛,雖然這個material design的Icons庫里面已經有很多圖標了,有些需求或者場景下想找到一個符合語境的圖標還是很難。不過最近發現了一個網站 Flutter Icon ,可以通過上傳svg文件生成自定義字體文件,然后就可以使用自定義的Icon了。

Read more ?

Android系統的指紋識別API使用

Android的指紋識別系統API是從Android M開始支持的。有專門的FingerprintManager類來提供指紋識別的能力,但是最新的Android P開始這個類被廢棄了,取而代之的是BiometricPrompt類,從名字上看是生物識別,說明提供了更多的識別的支持,比如人臉識別、虹膜識別?我隨便猜的??

所以你的應用要使用指紋識別來進行驗證的話,如果你的工程compileSdkVersion大于等于Android P就需要寫兩種調用方式,如果低于Android P,但是大于等于Android M就只需要寫一種調用方式就行了。

FingerprintManager

FingerprintManager是從API 23開始的所以使用的時候必須判斷系統版本:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    val fingerprintManager = context.getSystemService(FingerprintManager::class.java)
}

Read more ?

指紋識別驗證和人臉識別驗證-IOS

本文代碼是基于Swift4.2。

TouchID和FaceID的驗證,在IOS中調用本身比較簡單。因為現在要么是FaceID,要么是TouchID,再老一點的就是啥都沒有。這種機器應該沒人用了吧?不過還有是IOS系統版本的支持。TouchID是從IOS8.0開始的,FaceID是從IOS11.0開始的。

引入模塊,初始化環境

要使用驗證模塊先要引入:

import LocalAuthentication

然后初始化對象:

let context = LAContext.init()

Read more ?

自簽名SSL證書

現在大家對互聯網安全越來越重視了,Chrome、Safari等瀏覽器更是直接把http請求的網站標記為不安全網站,還有IOS應用直接就關閉了http的請求,只支持https。所以現在越來越多的網站、服務都開始使用https進行加密傳輸。

HTTPS

https其實就是http基礎上加了SSL協議,通過SSL數字證書來進行服務器身份認證和通信的加密。所以我們的服務或者網站要升級到https就需要有SSL數字證書。數字證書中的公鑰能夠和服務器上的私鑰配對使用,實現數據傳輸過程中的加密和解密。

CA

這個數字證書其實大家都可以自己生成的,既然這樣,我們訪問某個網站咋知道這個網站是別人偽造的還是真的?這時候“權威”機構就出來了,就是常說的CA(數字證書簽發機構)專門簽發證書的第三方機構,你作為網站主到這個第三方機構去申請證書,CA確認你的申請信息無誤后就會給你頒發證書,這個證書瀏覽器接收到后因為是“權威”結構頒發的所以會認為是安全的、可信任的。

自簽名證書

CA證書需要“權威”機構頒發,既然是“權威”的,價格就不菲,對很多人來說是筆很大的開銷。但是為了數據傳輸的安全性,我們內部使用的服務還是可以用自簽名證書來開啟https協議的。就是前面說的自己通過一些工具生成的數字證書,來進行數據傳輸的加密解密。

Read more ?
陕西省快乐十分走势图 双色球十大杀号汇总表