1. 程式人生 > >WatchOS開發教程之三: 導航方式和控制元件詳解

WatchOS開發教程之三: 導航方式和控制元件詳解

導航方式

Watch App中導航樣式分為兩種:分頁樣式(Page based) 和分層樣式(Hierarchical), 這兩種樣式是互斥的,所以不能混合使用只能選擇其一。Hierarchical方式可以通過pushController或者presentController來顯示二級頁面; 而Page based方式只能通過presentController來模態出新的二級頁面。

Page based

分頁樣式導航(Page-based)是一種呈現平面資訊集合的方式, 其中所有頁面都是平級的。在分頁樣式導航中, 使用者水平滑動或者垂直滑動以在頁面之間導航, 並且白點表示它們在頁面集中的位置。由於瀏覽大量頁面可能非常耗時, 因此請限制介面中包含的頁數。

Hierarchical

分層導航非常適合分層資訊的應用程式。它還可以更輕鬆地擴充套件應用的新內容。當用戶點選層次結構中的專案時,會出現一個新螢幕,顯示有關該專案的詳細資訊。通過垂直基於頁面的導航,使用者還可以使用數字表冠或在詳細檢視上垂直滑動,在不同行的詳細檢視之間快速導航。但要儘量避免建立深度超過2-3級的層次結構。

控制元件詳解

iOS中的大部分控制元件在 WatchOS中也在有, 比如: WKInterfaceLabelWKInterfaceImageWKInterfaceButtonWKInterfacePickerWKInterfaceTable

WKInterfaceSwitchWKInterfaceSlider、等類。還有一些 WatchOS特有的類, 比如: WKInterfaceGroupWKInterfaceSeparatorWKInterfaceMenuWKInterfaceDateWKInterfaceTimer等類。下面我將對部分控制元件進行詳細的使用說明。

WKInterfaceImage

Image相關控制元件

WatchOS中很多控制元件都可以與WKInterfaceImage類結合使用:
1.WKInterfaceGroupWKInterfaceButtonWKInterfaceController

類允許您指定影象作為其背景。
2.WKInterfaceSlider類可以顯示增量和減量控制元件的自定義影象。
3.WKInterfaceMovie類顯示視訊或音訊內容的海報影象。
4.WKInterfacePicker類顯示可包含影象的專案。

Image效能

關於圖片的使用有一個坑需要注意, 當我們為WKInterfaceImage類新增圖片時, 可能會遇到圖片不顯示的問題。這是因為所使用的方法和圖片資源庫是有一定的關係的。
1.當使用setImageNamed:setBackgroundImageNamed:方法新增圖片時, 應該使用 Watch App包內Assets.xcassets中的已有的圖片資源。
2.當使用setImage:setImageData:setBackgroundImage:setBackgroundImageData:方法新增圖片時, 應該使用 WatchKit Extension包內Assets.xcassets中的圖片資源。

使用第2條的方式時, 會先在 WatchKit Extension中建立 Image, 然後在傳輸到 WatchKit App中進行顯示。而在第1條中按名稱指定影象更有效,因為只需要將名稱字串傳輸到您的Watch App中, 然後會在 Watch App包中搜索指定名稱的影象檔案, 並進行顯示。所以指定影象的最有效方法是將它們儲存在 Watch App包中,並使用setImageNamed:setBackgroundImageNamed:適當地配置相應的物件。

WKInterfaceGroup

WKInterfaceGroup在 WatchOS中的一個很特別的類, 它是一個容器性質的控制元件, 能為其他控制元件提供額外的佈局。Group可以指定其所包含控制元件的排列方向, 橫向或者縱向, 也可以設定間距和內嵌。它還能為自己新增背景圖片, 作為一個種控制元件疊加的效果這是一個不錯的選擇, 因為在 WatchOS中是不允許控制元件相互重疊的, 除了像Group這樣容器類的控制元件。

Group中還有一些屬性如下:

WKAlertControllerStyle

自 WatchOS 2.0開始, 就已經支援系統 Alert了, WKAlertControllerStyle列舉型別包含以下三種:

public enum WKAlertControllerStyle : Int {
    case alert
    case sideBySideButtonsAlert
    case actionSheet
}

它們對應的樣式是這樣的:

程式碼描述

在當前頁面建立三個按鈕, 點選事件別分展示不同型別的 Alert。

具體程式碼如下:

@IBAction func presentAlertStyleAction() {

    let confirmAction = WKAlertAction(title: "Ok", style: .default) {
        print("Ok")
    }
    let denyAction = WKAlertAction(title: "Deny", style: .destructive) {
        print("Deny")
    }
    let cancelAction = WKAlertAction(title: "Cancel", style: .cancel) {
        print("Cancel")
    }
    presentAlert(withTitle: "Tip", message: "Do you want to see it.", preferredStyle: .alert, actions: [confirmAction, denyAction, cancelAction])
}


@IBAction func presentSideBySideStyleAction() {

    let confirmAction = WKAlertAction(title: "Ok", style: .default) {
        print("Ok")
    }
    let denyAction = WKAlertAction(title: "Deny", style: .destructive) {
        print("Deny")
    }
    presentAlert(withTitle: "Tip", message: "Do you want to see it.", preferredStyle: .sideBySideButtonsAlert, actions: [confirmAction, denyAction])
}


@IBAction func presentSheetStyleAction() {

    let confirmAction = WKAlertAction(title: "Ok", style: .default) {
        print("Ok")
    }
    let denyAction = WKAlertAction(title: "Deny", style: .destructive) {
        print("Deny")
    }
    let cancelAction = WKAlertAction(title: "Custom Cancel", style: .cancel) {
        print("Cancel")
    }
    presentAlert(withTitle: "Tip", message: "Do you want to see it.", preferredStyle: .actionSheet, actions: [confirmAction, denyAction, cancelAction])
}

執行效果

WKInterfacePicker

WKInterfacePickerStyle屬性有三種, 分別是ListStackSequenceFocus Style屬性也有三種分別是NoneOutlineOutline with Caption

在 Storyboard中我們先新增3個Picker, 然後要對它們進行設定不同的Style屬性Focus Style屬性。目的是為了, 對比它們之前的區別。

程式碼描述

3個Picker關聯到程式碼檔案, 懶載入配置資料:

@IBOutlet var listPicker: WKInterfacePicker!
@IBOutlet var stackPicker: WKInterfacePicker!
@IBOutlet var sequencePicker: WKInterfacePicker!

lazy var itemArray: [WKPickerItem] = {
    var its = [WKPickerItem]()
    let titles = ["①", "②", "③", "④", "⑤"]
    let captions = ["① is one", "② is two", "③ is three", "④ is four", "⑤ is five"]

    for i in 0...4 {
        let item = WKPickerItem()
        item.title = titles[i]
        item.caption = captions[i]
        let string = "item_type_\(i + 1)"
        item.accessoryImage = WKImage(imageName: string)
        item.contentImage = WKImage(imageName: string)
        its.append(item)
    }
    return its
}() 

初始化的時候, 對3個Picker進行配置:

override func awake(withContext context: Any?) {
    super.awake(withContext: context)

    listPicker.setItems(itemArray)
    stackPicker.setItems(itemArray)
    sequencePicker.setItems(itemArray)

    listPicker.focus()
}

Picker新增的Action:

@IBAction func listPickerSelect(_ value: Int) {
    print(itemArray[value].title!)
}

@IBAction func stackPickerSelect(_ value: Int) {
    print(itemArray[value].title!)
}

@IBAction func sequencePickerSelect(_ value: Int) {
    print(itemArray[value].title!)
}

重寫在WKInterfaceController類中有關於Picker的方法, 當Picker獲得焦點、失去焦點、選擇保持穩定時會觸發的方法:

override func pickerDidFocus(_ picker: WKInterfacePicker) {
    if picker == listPicker {
        print("ListPicker Did Focus")
    } else if picker == stackPicker {
        print("StackPicker Did Focus")
    } else {
        print("SequencePicker Did Focus")
    }
}

override func pickerDidResignFocus(_ picker: WKInterfacePicker) {
    if picker == listPicker {
        print("ListPicker Did Resign Focus")
    } else if picker == stackPicker {
        print("StackPicker Did Resign Focus")
    } else {
        print("SequencePicker Did Resign Focus")
    }
}

override func pickerDidSettle(_ picker: WKInterfacePicker) {
    if picker == listPicker {
        print("ListPicker Did Settle")
    } else if picker == stackPicker {
        print("StackPicker Did Settle")
    } else {
        print("SequencePicker settle")
    }
}

執行效果

List and None:

Stack and Outline:

Sequence and Outline with Caption:

WKInterfaceTable

WKInterfaceTable和 UITableView的區別

在 iOS中的 UITableView使用範圍是很廣的, 它可以實現列表性質的複雜功能。那麼在 WatchOS中對應的類是WKInterfaceTable, 但功能上來說相對簡單了許多。

1.Table只有行的概念, 沒有分割槽, 沒有頭尾檢視的概念。
2.Table通過Gruop進行自適應佈局, 所以沒有行高等設定。
3.Table沒有代理, 所有行的資料都是採用靜態配置的方式。
4.Table的點選事件也是依靠重寫WKInterfaceController的方法來實現的。
5.Table中是通過自定義的TableRowController來進行控制 TableRow上顯示的內容的。TableRowController是一個繼承於NSObject的類, 其實從根本上與 iOS中的UITableViewCell類似。

如何使用Table

1.在Storyboard中, 為頁面新增一個Table
2.新建一個TableRowController類繼承與 NSObject的 Cocoa Touch類。
3.在Storyboard中, 為新增的Table配置一個或多個TableRowController, 並設定ID。
3.在程式碼中, 為Table指定行數和TableRowController型別。
4.為TableRowController的每一行配置顯示的資料。

程式碼描述

Storyboard中的配置:


Table的配置及點選事件處理:

    @IBOutlet var table: WKInterfaceTable!
    let dataArray = {
        return [
            ["image": "item_type_0", "title": "Menu Action And Controller Life Cycle"],
            ["image": "item_type_1", "title": "Media Player"],
            ["image": "item_type_2", "title": "Picker Styles" ],
            ["image": "item_type_3", "title": "Interactive Between iPhone And Watch"],
            ["image": "item_type_3", "title": "Interactive Between iPhone And Watch"],
          ]
    }()


    override func awake(withContext context: Any?) {
        super.awake(withContext: context)

        // Set Row Number And Row Type
        table.setNumberOfRows(dataArray.count, withRowType: "ItemRowController")

        for (i, info) in dataArray.enumerated() {
            let cell = table.rowController(at: i) as! ItemRowController
            cell.titleLabel.setText(info["title"])
            cell.image.setImageNamed(info["image"])
        }
    }

    override func table(_ table: WKInterfaceTable, didSelectRowAt rowIndex: Int) {
        print(dataArray[rowIndex]["title"]!)
    }

執行效果

WKInterfaceMenu

Apple Watch的 Retina屏是支援 Force Touch功能的, 提供了一種新的互動方式。這是一個 WatchOS獨有的類, 當頁面中配置這 Menu時, 按壓螢幕將會啟用頁面中的Menu。並且顯示出Menu下的操作, 這些操作是另一個型別, WKInterfaceMenuItem

Menu最多可顯示四個MenuItem, 它們可以關聯各自的點選事件, 從而進行你想要的各自操作。

程式碼描述

在 Storyboard中為頁面新增WKInterfaceMenuWKInterfaceMenuItem, 併為MenuItem設定各自的Imagetitle

程式碼關聯:

    @IBAction func menuActionInvest() {
        print(#function)
    }

    @IBAction func menuActionNotification() {
        print(#function)
    }

    @IBAction func menuActionQuestion() {
        print(#function)
    }

    @IBAction func menuActionShare() {
        print(#function)
    }

執行效果

WKInterfaceController中的Present方法

在 WatchOS中WKInterfaceController就相當於 iOS中的 UIVIewController, 同樣具有類似生命週期和方法。 這裡就不再贅述了, 想了解請檢視第一篇文章:Watch App架構及生命週期

在這裡要說的是, 在WKInterfaceController中, 有許多重要的Present方法, 這些功能我們可以直接使用, 更加方便了我們的開發。
像平時使用的presentController, 還有上面Alert中涉及到一個, 另外, 還有一些關於文字錄入的, 音視訊播放的, 音訊錄製的。

open func presentController(withName name: String, context: Any?) // modal presentation

@available(watchOS 2.0, *)
open func presentAlert(withTitle title: String?, message: String?, preferredStyle: WKAlertControllerStyle, actions: [WKAlertAction])

文字錄入

presentTextInputController(withSuggestions: ["Hello!", "When are you free?", "Yes."], allowedInputMode: .plain) { (inputText) in
    if let stringArr = inputText {
        print(stringArr)
    }
}

音視訊播放

@IBAction func mp4PlayAction() {
    playMedia(name: "music", ex: ".mp4")
}

func playMedia(name: String, ex: String) {
    // MediaPlayer
    let URL = Bundle.main.url(forResource: name, withExtension: ex)
    let option = [WKMediaPlayerControllerOptionsAutoplayKey: true]

    presentMediaPlayerController(with: URL!, options: option) { (isEnd, endTime, error) in
        if error == nil {
            print("endTime=\(endTime)");
        } else {
            print("error=\(error!)")
        }
    }
}

音訊錄製

func textVoiceInput() {
    let option2: [String: Any] = [WKAudioRecorderControllerOptionsActionTitleKey: "傳送",
WKAudioRecorderControllerOptionsAutorecordKey: true,
WKAudioRecorderControllerOptionsMaximumDurationKey: 30]

    // Use App Group URL
    let uurl = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.watchAppSampler.record")
    let uuurl = uurl!.appendingPathComponent("record.wav")

    presentAudioRecorderController(withOutputURL:uuurl , preset: .narrowBandSpeech, options: option2) { (didSave, error) in
        if error == nil {
            print("didSave=\(didSave)");
        } else {
            print("error=\(error!)")
        }
    }
}

WatchOS中的其它控制元件和類

WatchKit框架中, 還有其它許多的控制元件和類, 這裡就不在介紹了。附一張WatchOS 4.3版本下的所有類的全家福:

相關推薦

WatchOS開發教程: 導航方式控制元件

導航方式 Watch App中導航樣式分為兩種:分頁樣式(Page based) 和分層樣式(Hierarchical), 這兩種樣式是互斥的,所以不能混合使用只能選擇其一。Hierarchical方式可以通過pushController或者prese

【Oracle 叢集】ORACLE DATABASE 11G RAC 知識圖文詳細教程RAC 工作原理相關元件

概述:寫下本文件的初衷和動力,來源於上篇的《oracle基本操作手冊》。oracle基本操作手冊是作者研一假期對oracle基礎知識學習的彙總。然後形成體系的總結,一則進行回顧複習,另則便於查詢使用。本圖文文件亦源於此。閱讀Oracle RAC安裝與使用教程前,筆者先對這篇文章整體構思和形成進行梳理。

基於 Linux MiniGUI 的嵌入式系統軟體開發指南——對話方塊控制元件程式設計

簡介: 本文講述 MiniGUI 中的對話方塊和控制元件程式設計。首先講解 MiniGUI 中的控制元件類和控制元件例項的關係,並舉例說明控制元件子類化的概念及應用;其次講解 MiniGUI 對話方塊的程式設計技術,包括對話方塊模板的定義和對話方塊回撥函式的程式設計;最後解

微信小程序開發教程(八)視圖層——.wxml

span hid 處理 路徑 strong 一般來說 emp 條件 頁面數據   框架的視圖層由WXMKL(WeiXin Markup language)與WXSS(WeiXin Style Sheet)編寫,由組件進行展示。   對於微信小程序而言,視圖層就是所有.wxm

微信小程序開發教程(九)視圖層——.wxss

hone mnt 而且 padding 移動 圖層 組成 特性 -1   WXSS是一套樣式語言,用於描述WXML的組件樣式。   官方文檔表示,WXSS的選擇器目前支持(“.class”、“#id”、“elemnt”、“element,element”、“::after”

)GETPOST協議

str 打印 http 類別 多個 表現 pro 版本 prot 一、GET請求報文分析: 1、 請求行:   a) GET(描述該請求采用了什麽請求方法),HTTP協議中包含8種請求方法: GET 請求獲取Request-URI 所標識的資源 POST

MFC程式設計學習改變對話方塊控制元件及文字顏色

//程式訊息流:首先對話方塊繪製時,會發送WM_CTLCOLOR訊息,那麼OnCtlColor()函式 //將響應該訊息,程式將用該函式返回的畫刷對控制元件進行繪製。 HBRUSH CSettingDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtl

前端學習筆記js中apply()call()方法

經過網上的大量搜尋,漸漸明白了apply()和call方法的使用,為此寫一篇文章記錄一下。 定義 apply()方法: Function.apply(obj,args)

Android開發——View動畫、幀動畫屬性動畫

0. 前言Android動畫是面試的時候經常被問到的話題。我們都知道Android動畫分為三類:View動畫、幀動畫和屬性動畫。先對這三種動畫做一個概述:View動畫是一種漸進式動畫,定義動畫開始和結束

MongoDB常用命令彙總插入、更新刪除操作

Insurt操作 insurt操作是MongoDB插入資料的基本方法,對目標集合使用Insert操作,會將該文件新增到MongoDB並自動生成相應的ID鍵。文件結果採用類似JSON的BSON格式。常見的插入操作主要有單挑插入和批量插入兩種形式。插入時只是簡單地將文件存入資

form表單提交方式,demo例項

第一種:使用type=submit 可以直接提交<html> <head> <title>submit直接提交</title> </head> <body> <!-- 表單的提交方

Android進階——效能優化佈局渲染原理底層機制(四)

引言 UI 全稱User Interaction,我第一次聽到這個名詞是在大學的時候,當時候上人機互動課,我們教授說他認為iPhone的i 就是代表Interaction的意思,暫且不必爭辯是非。回到我們軟體開發中來,UI是使用者感知與互動的第一且唯一的途徑,

Bitmap點陣圖取樣記憶體計算

原文首發於微信公眾號:躬行之(jzman-blog) Android 開發中經常考慮的一個問題就是 OOM(Out Of Memory),也就是記憶體溢位,一方面大量載入圖片時有可能出現 OOM, 通過取樣壓縮圖片可避免 OOM,另一方面,如一張 1024 x 768 畫素的影象被縮略顯示在 128 x

《Android群英傳》學習筆記Android控制元件架構與自定義控制元件

一、Android控制元件架構: 控制元件大致分為兩類:ViewGroup控制元件與View控制元件。View是繪製在螢幕上的使用者能與之互動的一個物件。而ViewGroup則是一個用於存放其他Vi

PyQt5基本控制元件QPixmap(十九)

QPixmap 前言 QPixmap類用於繪圖裝置的影象顯示,它可以作為一個QPainterDevice物件,也可以載入到一個控制元件中,通常是標籤或者按鈕,用於在標籤或按鈕上顯示影象

PyQt5基本控制元件QDialog(十二)

QDialog 前言 為了更好的實現人機互動,比如window和linux等系統均會提供一系列的標準對話方塊來完成特定場景下的功能,比如選擇字號大小。字型顏色等,在PyQt5中定義了一系列的標準對話方塊類,讓使用者能夠方便快捷地通過各個類完成字號大

React NativeScrollView控制元件

概述 ScrollView在Android和ios原生開發中都比較常見,是一個 滾動檢視控制元件。在RN開發中,系統也給我們提供了這麼一個控制元件。不過在RN開發中 ,使用ScrollView必須有一個確定的高度才能正常工作,因為它實際上所做的就是將一系列不確

PyQt5基本控制元件QCheckBox(八)

QCheckBox QCheckBox類中常用方法如表 方法 描述 setChecked() 設定複選框的狀態,設定為True表示選中,False表示取消選中的複選框 setText() 設定複選框的顯示文字

PyQt5基本控制元件QLineEdit(四)

QLineEdit QLineEdit類中常用的方法如下表 方法 描述 setAlignment() 按固定值方式對齊文字 Qt.AlignLeft:水平方向靠左對齊 Qt.AlignRight:水平方

EOS開發基礎:使用cleos命令行客戶端操作EOS——關於錢包wallet賬戶account

技術 account perm ons vnc HR and limit may 好了,上一節我們已經講了關於wallet的一些基礎操作,基本了解了怎麽去創建一個錢包,怎麽去查看錢包、上鎖和解鎖錢包等,這一節咱們就來開始操作賬戶account吧。 上一節講到了每一個