發佈日期:

Flat Design 座談會筆記

講師介紹

Amy Megumi Kuo
http://happyux.hpx.tw/conf/ch/ux-usa-tibco-amy-kuo/
從政大畢業之後就到美國工作。原本是在做汽車面版設計,後來轉到手機和軟體的介面設計。
因為開發裝置的不同,在開發限制上會有所不同。
例如汽車的裝置在設計上,由於許多的按鍵仍然會是實體按鍵,但是手機與軟體則是完全要設計在畫面上。
會造成在設計方針上很大的不同

Flat design 的基本原則

首先要先介紹Flat這個詞
flat (N) 平面
skeuomorphism 擬真,在過去而言,對user來說還不熟悉,所以會用擬真的設計,希望讓使用者第一次接觸就知道如何使用。

flat design較有名的是microsoft和apple還有google。

在這邊比較了一下google的設計與ios的設計上的差異

google的原則

  1. icon盡量簡單
  2. 每個icon都需面向前面,不可有角度
  3. 陰影簡單且同光源方向(左上)
  4. 推薦使用的顏色
  5. 不可用太多效果

apple的iOS human interface guide line

  1. 所有的事情都要以content為主
  2. 所有以清楚展現text為主
  3. 深度的意思是透過不同的層級讓使用者了解要表達的內容

從ios6到7要注意的設計要點,最大差別是『把所有的東西都以展現內容為主

  1. content要全螢幕,東西要做成透明的,讓user可以看的到背景內容
  2. 要redesign使用者的介面,用深度去表達不同的內容種類
  3. 所有的button要沒有border
  4. 在ios7裡,font size可以調大小(大中小)、也可調字距。因此在設計app時要有一個基準大小,然後要考慮到使用者把字變大變小時該如何去條適整體的大小,因此不可以給定一個固定的背景大小,因為有時若是文字變大時字體會超過<重要>
  5. 如果在舊的設計裡面icon有發光、陰影、漸層,apple要求我們將這些design的元素拿掉

因此,在做flat design時,主要是要考量要做出來的感覺。apple和google在flat design上的考量是不一樣的。這是在說明,Flat Design其實並沒有一定的規範或是準則,而是以使用者經驗、或是產品想要給使用者的主要速求為考量做為出發點,維持一定的設計模式,而不需要一味的去盲從。

Flat design 對ux的影響

因為手機現在已更為普及,當操作方式更多元,過場的視窗縮放效果、畫面堆疊等等效果多了,在很多畫面切換中,icon的辨識就變得重要了。好不好辨識不再是”逼真”與否的問題,而是眼睛是否可以快速地辨識icon的輪廓與資訊。於是去掉細節,突顯關鍵形狀與顏色,就成了解決之道

「flat design的好與壞」
好:潮流 、簡單(讓人一看就能明瞭、對設計師程式師都簡單,但要能夠更能表現出精神的)
壞:較難突出(大家的設計都很像,要怎樣去吸引使用者會成為更難的議題)

flat design的三大要素為:顏色、字體、icon

因為設計平面化,使用者對操作的理解來自於操作習慣以及介面呈現,因此在使用者設計上,會有一些不同的注意要點

  1. flat design大部份是用顏色,顏色這件事是很能夠展現出概念或想法,是要專業、開心或是…。在icon設計上的顏色亦十分重要,不能有發光陰影
  2. <<<字體>>>很重要!在挑選字體上面要多花一點心力,要依app內容來挑選適合的字型。沒有最好的字型,只有最適合。每個字型都有他的個性,能與app本身的性質做搭配,就是好的字型選擇。
    若是中英文並用的app也是會在融合上比較困難,需要花心思去調整
  3. 假設今天裡面沒有很多文字時,會看起來太簡單,所以若是在ios7時文字若小,可以多用圖片,更可以讓人印象深刻,不論讀起來或使用起來都會較突顯
  4. 按鈕設計:當按鈕不再仿真,設計者要怎麼讓使用者知道那是按鈕?符合視覺動線的擺放位置和大小、形狀、圖樣、顏色等等都是關鍵。
  5. 當畫面變簡單,UX就更顯重要了。操作手勢(滑動、長按、點、下拉等等)、每個動作得到的回饋(微微顫動、變暗、噗啾一聲…)種種細節都能讓app更豐富。當然,得在使用者熟悉的操作模式下,設法讓app的UX發揮到淋漓盡致。
  6. flat design不鼓勵太無聊的裝飾

Flat design 的挑戰與突破

在Flat design的時代裡,設計者的角色會更加重要。

visual designer要更常去討論這個設計是否能表達出產品的感覺,了解產品特性及想表達給使用者的感受,並且要能夠更精準的使用顏色、字體等元件去表達想表達的。這時後,是否可以做出簡單而能表達出產品特性的icon,便挑戰著設計者的功力。
要如何評斷好的設計呢?在設計時,還是得回歸a b test,訴諸實際數據,然後找出最能讓使用者接受的介面。

當產品要使用Flat Design,在做的工上會能夠減少,因為不需要一直去仿真、繪製很多效果。但是設計者會需要更高強的功力,精準的去以手勢、顏色、字體等元素,來強調出產品的特色。

發佈日期:

IOS6與IOS7的不同處整理

1. View會和狀態列重疊(壓在其之下)

2. 按鈕沒有邊框

3. tab bar變為半透明

螢幕快照 2013-10-06 下午7.18.46

4. 狀態列的顏色不會與導覽列分開

5. tintColor的影響顏色範圍改變,導覽列與tab bar的顏色不會受到tint Color的影響
ps:經測試,在ios7對於Segmented Control的tintColor,如果使用Global tint,一開始時的框線顏色不會變,但點過後顏色會改變。此時必須去各別設定該元件的tint color才會完整變更顏色

6. tab bar的圖示有按下狀態及非按下狀態螢幕快照 2013-10-06 下午7.24.37

7. 文字樣式明顯不同(即使是相同的設定)

8. 預設會是全螢幕畫面

9. 狀態列的高度不再會影響到整體畫面高度(整體畫面會在狀態列之下)

10. NSBundle Class改變Chia-Hsin分享
ios7的pathForResource (NSBundle Class)方法有調整過,
例,Local/iphone/page/01/01.jpg,
ios7之前用:
folder = Local
fileName = iphone/page/01/01.jpg

參數帶入function裡面是OK的~

但現在ios7要改成:
folder = Local/iphone/page/01
fileName = 01.jpg

11. iOS 7 的UITextField會預先給值,iOS 6 不會
if(![username.text isKindOfClass:[NSString Class]]){
NSLog(@”你沒有輸入帳號”);
}
因此這邊在ios7,若使用者沒有輸入任何文字,還是會成立。

12. viewdidload執行順序改變(建議:直接用@property帶值過去,然後在viewWillAppear裡去執行動作)
IOS6的code
ViewController *view1;
[[self navigationController] pushViewController:view1animated:TRUE];
[view1 method];

iOS7以前, 順序為view1被push出來以後會先執行viewdidload候才會執行[view1 method]
而iOS7後變成會先執行[view1 method]才執行viewdidload
目前在push前加viewController.view.hidden = NO;可以解決我現在的問題

Micheal老師建議:本來就是在 View Controller 裡面,去判斷的,不是在你寫的 pushViewController 那段程式碼。你寫的這段的地方,view controller 的 view還沒呈現,所以 view 也沒有值。之前會有值,只是剛好。我們不能決定什麼時候 ViewController 產生 view 的值,我們只知道,在 viewDidLoad 會有 view 的物件,在 viewDidAppear,view 的 frame 會被決定(如果是 storyboard 上的 view 的話)。 再來收到 delegate 回傳值要反應的 view 是 ViewController 的 view 為什不把接收者,設定為 ViewController。

附註:狀態列改變的相關議題

(一)讓上方留狀態列的位置

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if ([[[UIDevice currentDevice] systemVersion] floatValue] &gt;= 7) {
[application setStatusBarStyle:UIStatusBarStyleLightContent];
self.window.clipsToBounds =YES;
self.window.frame =  CGRectMake(0,20,self.window.frame.size.width,self.window.frame.size.height-20);</code></strong>
<strong><code>
self.window.bounds = CGRectMake(0, 20, self.window.frame.size.width, self.window.frame.size.height);
}
return YES;
}

(二)座標計算不將狀態列的地方算入

if([[[UIDevice currentDevice] systemVersion] floatValue] &gt;= 7.0)
{
self.edgesForExtendedLayout = UIRectEdgeNone;
self.extendedLayoutIncludesOpaqueBars = NO;
self.modalPresentationCapturesStatusBarAppearance = NO;

self.navigationController.navigationBar.translucent = NO;
self.tabBarController.tabBar.translucent = NO;

self.navigationController.navigationBar.barTintColor =[UIColor grayColor];
self.tabBarController.tabBar.barTintColor =[UIColor grayColor];
}

(三)不顯示狀態列

  1. 至project setting=>General=>Deployment Info的地方勾選Hide during application launch
  2. 在ViewController加上
    -(BOOL) prefersStatusBarHidden{
    return YES;
    }

(四)改變狀態列顯示樣子(將字體顯示為白色)
-(UIStatusBarStyle)preferredStatusBarStyle{
return UIStatusBarStyleLightContent;
}

相關資料來源:

發佈日期:

UIWebView練習作業

作業目標:http://www.youtube.com/watch?v=azplcMbuoQ4&feature=youtu.be
練習檔案:homework0831

先介紹一下UIWebView

UIWebView的資料來源主要有三者:

  1. 本機上的HTML字串
  2. 本機上的資料 + MIME type
  3. 遠端的URL

這邊有中文的介紹:http://www.inside.com.tw/2010/03/14/cs193p-lecture-12

作業練習開始

首先我先拉出storyboard
螢幕快照 2013-09-04 下午11.30.34

然後我練習使用程式去產生UINavigationController,這是在AppDelegate.m裡

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

UINavigationController * navi = [UINavigationController new];
UIStoryboard * storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
UIViewController * controller = [storyboard instantiateViewControllerWithIdentifier:@"pink"];
[navi pushViewController:controller animated:YES];
self.window.rootViewController = navi;
return YES;
}

然後ViewController.h裡在viewDidLoad時初始化一些頁面數值

- (void)viewDidLoad
{
[super viewDidLoad];
[self.inputURL setAdjustsFontSizeToFitWidth:YES];//設定下方網址列的大小會自動resize
self.title = @"填入網址";
self.inputURL.text = @"http://www.apple.com";
}

實作按鈕按下時的動作

- (IBAction)goWeb:(id)sender {
//取出webview的view
UIStoryboard * storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
WebViewController * webView = [storyboard instantiateViewControllerWithIdentifier:@"webView"];
webView.urlString = self.inputURL.text;
webView.delegate = self;
[self.inputURL resignFirstResponder];//收起鍵盤
[self.navigationController pushViewController:webView animated:YES];
}

接下來做WebViewController.m裡的內容,
在這邊我弄了一個下載進度的物件叫作UIActivityIndicatorView
這部份首先要先在- (void)viewDidLoad裡初始化載入效果

//加入載入特效
aciv = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; colorView=[[UIView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];

[colorView setBackgroundColor:[UIColor colorWithRed:0.2 green:0.2 blue:0.2 alpha:0.4]];

然後加上下面兩段程式碼

//載入特效
- (void)addLoading{
aciv.activityIndicatorViewStyle=UIActivityIndicatorViewStyleWhite; aciv.center=CGPointMake(self.view.frame.size.width/2,self.view.frame.size.height/2-10);
[self.view addSubview:colorView];
[aciv startAnimating];
[self.view addSubview:aciv];
}

- (void)removeLoading{
[colorView removeFromSuperview];
[aciv stopAnimating];
[aciv removeFromSuperview];
}

然後在實做UIWebView的Delegate去設定載入畫面
[UIApplication sharedApplication].networkActivityIndicatorVisible這個是在上方指示列的圈圈圖示

- (void)webViewDidStartLoad:(UIWebView *)webView
{
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
[self addLoading];
}

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
[self removeLoading];
}

遇到問題(高手幫忙看3Q)

然後其實接下來這一點問題我弄了非常久~ 就是,在從上一頁傳來網址時,
也會執行到
-(BOOL) webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
所以會必須去判斷現在是使用者點擊的link,或是是從上頁傳來的指令

為了這個需求,我用了幾個方式,但都有問題,包括現在的其實也有,但因為實在搞太久~
所以就先這樣@@等老師公布他的作法後再來補修正

我總用試了這些方式

  1. 使用一個BOOL去判別,只有第一次loading頁面時不做跳頁呼叫,然後當webViewDidFinishLoad時將BOOL改為NO
    問題點:有某些頁面會有js檔案,當頁面全部載入完成後,執行js後,就又會再第二次讀取網路資料,此時頁面就會莫名的突然回到第一頁然後顯示網址。(例如:我的部落格http://claire-chang.com)
  2. 使用NSConnection(http://stackoverflow.com/questions/9475768/loading-nsdata-into-a-uiwebview)
    這是一個異想天開(?)的想法,我想說,第一次loading時用NSConnection去讀html,然後用loadHTMLString:baseURL:來顯示在畫面上。結果html成功的載下來了,但是不知為何WebView呈現一片空白。
    在網路上查了一下,似乎是因為<scripe>標籤的關係(不確定)
  3. 現在版本的方式:偵測使用者點擊事件,當使用者點擊時,判斷現在是使用者點擊事件,下一次的網頁讀取便會跳頁。
    不過這種方式也有問題,同第一點,不過狀況會變成若頁面尚未載入完,使用者就點擊非link的地方時,js呼叫讀取網頁時,就會跳回第一頁,然後網址顯示為js呼叫的頁面網址= =

也是因為這樣子,我才會去製作下載畫面,想說在未loading完前不讓使用者按下WebView,
結果因為畫面會先loading完成、然後才自動因js而去呼叫另一個網址。
中間還是會有使用者可以點擊畫面的時間點。

我總覺得UIWebView應該有個東西是可以直接判別是否是使用者呼叫的,
觀察過dataDetectorTypes的值,卻似乎不是~orz
有知道的人麻煩幫解惑吧~3Q!
ps:若想試有js會在loading完成後再次loading的狀況,請把網址設為我的部落格http://claire-chang.com

因為我是用第三種方式,所以我對WebView增加了碰觸事件的偵聽
首先在- (void)viewDidLoad設定碰觸事件監聽

//設定碰觸事件
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(handleTapFrom:)];
longPress.minimumPressDuration = .001;
longPress.delegate = self;
[self.web addGestureRecognizer:longPress];
[self.web addGestureRecognizer:test];

然後要實作UIGestureRecognizerDelegate

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    return YES;
}

上面這個一定要加,這樣子handleTapFrom:才會被呼叫到
然後當按到時將bool值改成YES

-(void)handleTapFrom :(UITapGestureRecognizer *)sender{
    NSLog(@"handleTapFrom:%d",sender.state);
    isClick = YES;
}

當讀取網頁且isClick是YES時就跳回第一頁

-(BOOL) webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
    if(isClick){
        [self.delegate userClickWebLink:request.URL.absoluteString];
        return NO;
    }
    return YES;
}

這時再回去ViewController.m增加接收的方法

-(void) userClickWebLink: (NSString *) url{
    [self.navigationController popViewControllerAnimated:YES];
    self.title = @"點選網址";
    self.webUrl.text = url;
}
發佈日期:

hasEventListener()與willTrigger()區別

承上一篇介紹Event事件流的基本概念
AS3的事件傳遞機制(Event、dispatchEvent及addEventListener)
再來介紹相關的檢查函數。

hasEventListener()方法:
檢查 EventDispatcher 對象是否為有註冊這個事件的監聽器。
willTrigger()方法:
檢查是否用此 EventDispatcher 對象或其父容器是否有註冊這個事件的監聽器

hasEventListener() 與 willTrigger()的區別是:hasEventListener() 只檢查它所屬的對象
而 willTrigger() 檢查對象以及對象的父容器是否有註冊這個事件(不管capture的值)。

假如像下面這樣的物件階層來說

efAzj

今天我們對stage註冊事件

stage.addEventListener(MouseEvent.CLICK, stageClick);

則檢查box的willTrigger及hasEventListener

trace(box.willTrigger(MouseEvent.CLICK));
trace(box.hasEventListener(MouseEvent.CLICK));

的結果為
true
false

而若我們對box註冊事件

box.addEventListener(MouseEvent.CLICK, stageClick);

則檢查box的willTrigger及hasEventListener

trace(box.willTrigger(MouseEvent.CLICK));
trace(box.hasEventListener(MouseEvent.CLICK));

的結果為
true
true

而若我們對box註冊事件

box.addEventListener(MouseEvent.CLICK, stageClick);

則檢查stage的willTrigger及hasEventListener

trace(stage.willTrigger(MouseEvent.CLICK));
trace(stage.hasEventListener(MouseEvent.CLICK));

的結果為
false
false
代表box不在stage完整可能有的事件流的動線裡。

發佈日期: 1 則留言

Flex記憶體監控程式-Profile

Flash Builder裡面大家最廣泛用來監控記憶體使用狀況的工具應該就是Profile了
Profile位於執行鈕的右邊,如下圖:
2013-08-27_160230

這邊提供幾個可能你按下Profile結果卻無法正常執行的一些討論串
Flex Builder – Profiler – Can’t run profiler

這個討論串有給一些嘗試的除錯方法

  1. 更改port號碼
  2. 是否SWF本身有錯誤?PreloadSwf 應位於本地端
  3. 換一個瀏覽器! (Preferences/General/Web Browser)也許 Firefox無法支援(我有遇過開不了的問題,我自己是換一個瀏覽器就解決了PS: 原本是firefox換成IE)
  4. 指定的瀏覽器是否有安裝debug版本Player?
  5. 設定mm.cfg檔案的值 (請看這邊 http://jpauclair.net/2010/02/10/mmcfg-treasure/)

設定開啟瀏覽器的地方在Window>Preference>General>Web Brower
2013-08-27_161918

Profile的設定則在這邊(兩個enable的選項要記得勾選),port之類的更改也在此區更改
2013-08-27_162200

接下來,請選擇工作區

2013-08-27_162621

切到Profile模式之後,如果我們想觀看外部SWF的記憶體使用狀況,
可以按Profile>Profile External Application,一樣可以進入觀查模式
2013-08-27_162737

2013-08-27_163808

在執行Profile時,左上的欄位可選擇要觀察的物件,
在profile視窗裡,可以設定中斷點,然後用右上的去控制繼續執行、暫停等等
2013-08-27_164013

在Memory Usage可以顯示現在所耗的記憶體的狀況
2013-08-27_163936

Live Objects裡觀察現在在記憶體內的物件以及它的值
2013-08-27_163948

如果還想開其他的頁籤,也可以由Window=>Show View>Other>Flash Prifile去叫出其他觀察視窗。
2013-08-27_164904

發佈日期:

我的第一款APP企劃

畫面繪製工具: Balsamiq Mockups
參考規範: iPhone-HIG(人機界面指南)
企劃圖片下載: APP開發

名稱:94愛吃
類別:生產力應用程式
分類:美食
簡介:
想揪三五好友去吃某間超好吃的餐廳時,卻總是忘了餐廳的詳細資訊嗎?
想找一間適合談公事的餐廳,卻又一時想不起究竟那裡適合嗎?

這一款APP可以幫助你記錄曾吃過的餐廳,以及想吃卻還未去吃的餐廳。
也可以以地圖的方式,去告訴你這附近有那些你吃過的餐廳可以去吃。更能提供你最新、最酷的焦點餐廳情報。

如果你是美食愛好者,那不能錯過這一款APP唷!

畫面截圖

PLAN
第一頁: 可用月曆模式瀏覽紀錄
PLAN_2
第二頁: 以列表方式顯式資料
PLAN_3
按進階搜尋後畫面,按搜尋之後會反回第二頁只是資料不同
PLAN_4
點選列表或日曆的單項說明後進入詳細資訊頁
PLAN_5
點第一、第二頁右上的新增後進入的新增畫面
PLAN_6
第三頁:以地圖去尋找附近的餐廳(未來可能會想改成可以找網友分享的紀錄)
PLAN_7
第四頁: 純粹顯示一個網頁,如果未連網則顯示沒有連網頁,這邊應該會用網頁去更新,提供好吃餐廳資訊
PLAN_8
第五頁: 介紹作者

因為是第一款APP,不知道這樣會不會觸犯到APP的上架條款

  1. 應用程式涉及了裸體、暴力、中傷他人
  2. 違反商標法
  3. 功能過於簡單或與iOS內建功能動覆
  4. 使用未開放的API
  5. 應用程式Bug、當機且無任何警告訊息
  6. 違反HIG(Human Interface Guide)使用者介面
  7. 軟體功能與描述不符,或是描述提到第三方的名詞,如:Android/BlackBerry
  8. 簽證檔需設定為Distribution(iOS Dev Center中設定)

希望有經驗的人可以給我一些建議,謝謝大家!

 

發佈日期:

IPhone元件介紹

表格視圖,文字視圖和Web視圖

  1. 狀態欄:狀態欄顯示與使用者裝置相關的重要資訊,包括電話信號強度,當前網路連接和電量資訊。
    螢幕快照 2013-08-26 上午1.14.48
  2. 導覽欄:導覽欄位於應用程式螢幕的上邊緣,在狀態欄之下。導覽欄通常會顯示當前視圖的標題,包含導覽控制元件,並在適當的情況下也可以包含作用於視圖內容的控制元件。
    螢幕快照 2013-08-26 上午1.15.53
  3. 工具欄:如果您的應用程式為使用者提供了一系列可在當前上下文中執行的動作,那麼您可以為使用者提供一個工具欄。工具欄的外觀要力爭與應用程式中的其它欄目的外觀保持一致。例如,如果您使用半透明的工具欄,就不要將它與不透明的導覽欄一起使用。此外,請避免在同一方向的不同螢幕中改變工具欄的顏色或半透明效果。
    螢幕快照 2013-08-26 上午1.17.07
  4. 標籤欄:標籤欄使使用能夠在應用程式的不同模式或不同視圖之間進行轉換,並且使用者應該能夠從應用程式的任何地方進入這些模式。
    螢幕快照 2013-08-26 上午1.19.50
  5. 在應用程式螢幕中使用視圖和控制元件
    螢幕快照 2013-08-26 上午1.21.38
  6. 表格視圖:裡面包含許多元素,並可以使用表格視圖實現常用的使用者操作。如:選項列表;導覽層次資訊;查看按概念分組的資訊
    螢幕快照 2013-08-26 上午1.23.11
    有幾個表格操作元素:
    1. 展開指示符:當這個元素出現時,使用者知道他們可以點選這一行中的任意位置來查看下一級的資訊,或是與當前列表項相關的選項。
      當選中一行後會顯示另一個列表時,應使用展開指示符。不要使用展開指示符來顯示某個列表項的詳細資訊;這種情況下應使用詳細資訊展開按鈕。
    2. 詳細資訊展開按鈕:使用者可以通過點選該元素來查看某個列表項的詳細資訊。在表格視圖中,可以在某一行中使用詳細資訊展開按鈕,來顯示與該列表項相關的詳細資訊。請注意,與展開指示符不同,詳細資訊展開按鈕所執行的動作可以獨立於行的選擇動作。
    3. 刪除按鈕:使用者通過點選該元素可以刪除對應的列表項。
    4. 刪除控制按鈕:使用者通過點選該元素可以顯示或隱藏每個列表項的“刪除”按鈕。
    5. 行插入按鈕:使用者通過點選該元素可以向列表中新增一行。
    6. 行排序控制元件:當該元素出現時,使用者可以拖動一行到列表中的另一位置上。
    7. 選定符號:該元素出現在列表項的右側,表明該項當前被選中。
    8. 開關控制元件
  7. 文字視圖
    螢幕快照 2013-08-26 上午1.29.31
  8. Web視圖:Web視圖是應用程式螢幕上可以顯示豐富的HTML內容的一片區域。除了顯示web內容之外,web視圖還提供了一些元素來支援使用者瀏覽開放的網頁。雖然您可以選擇向使用提供網頁瀏覽功能,但是最好避免讓您建立的應用程式看起來像是一個小型web瀏覽器。

應用程式控制元件

  1. 活動指示器:活動指示器表示有一項持續時間未知的任務或過程正在進行當中。(請參考UIActivityIndicatorView類)
    螢幕快照 2013-08-26 上午1.32.36
  2. 日期時間選擇器:日期時間選擇器為使用提供了一種簡單的選擇特定日期或時間的方式。(請參考UIDatePicker類)
    螢幕快照 2013-08-26 上午1.33.46
  3. 詳細資訊展開按鈕:詳細資訊展開按鈕提供了關於某一項的額外資訊或更詳細的資訊。(參考UIButton類)
    螢幕快照 2013-08-26 上午1.37.11
  4. 資訊按鈕(參考UIButton類)
    螢幕快照 2013-08-26 上午1.38.44
  5. 標籤:標籤是一種大小可變的靜態文字。(參考UILabel類)
    螢幕快照 2013-08-26 上午1.39.59
  6. 頁面指示符號(參考UIPageControl類)
    螢幕快照 2013-08-26 上午1.40.41
  7. 選擇器:選擇器是日期時間選擇器的通用版本,如果您需要顯示特別多數量的值,則您應該用表格視圖將這些值列出,而不是用選擇器。
    這是因為表格視圖俱有更高的高度,能夠更快速地進行滾動。(參考UIPickerView類)

    螢幕快照 2013-08-26 上午1.42.15

  8. 進度視圖:進度視圖顯示俱有確定持續時間的任務或過程的進度。如果您需要顯示未知持續時間的任
    務的進度,請使用活動指示器。(參考UIProgressView類)
    螢幕快照 2013-08-26 上午1.44.07
  9. 圓角矩形按鈕:圓角矩形按鈕是一種多功能的按鈕,您可以在視圖中使用它來執行一個動作。(參考UIButton類)
  10. 搜尋欄:搜尋欄是一片接收使用者輸入的文字的區域,您的應用程式可以以搜尋欄中的文字為輸入進行搜尋。(參考UISearchBar類)
    螢幕快照 2013-08-26 上午1.45.31
  11. 分段控制元件:分段控制元件是處在一條直線上的各段的集合,其中的每一段都相當於一個按鈕,可以顯示不同的視圖。(參考UISegmentedControl類)
    螢幕快照 2013-08-26 上午1.47.03
  12. 滑塊:滑塊允許使用者在允許的值的範圍內對一個值或一個過程進行調整。當使用者拖拉滑塊時,相應的值或過程也不斷被更新。(參考UISlider類)
    螢幕快照 2013-08-26 上午1.48.04
  13. 文字框:文字框是一個接收使用者輸入的圓角矩形的區域。當使用者點選文字框時,會出現一個鍵盤;當使用者點選鍵盤上的Return鍵時,文字框會以應用程式指定的方式處理使用者的輸入資訊。(參考UITextField類)
    螢幕快照 2013-08-26 上午1.49.26

用於工具欄和導覽欄的標準按鈕

有關這些按鈕的符號名稱和可用性的資訊請參考UIBarButtonSystemItem的文件。

發佈日期:

IPhone人機界面指南(HIG)

中文版下載:iPhone-HIG(人機界面指南)
英文版下載:MobileHIG

HIG(人機界面指南)是apple在審核app時,給開發者去參考的條文,
只要想要在ios平台上開發app的開發者,在上架時,都必需同意自己的應用程式符合裡面的規範。
這也是app開發者在開發完APP後,常常會被apple退件的原因。
因此建議有志要開發iphone app的人可以在開發前先研讀一下這本規範手冊。

HIG將應用程式分類成三大類型

  1. 生產力應用程式:幫忙使用者管理資訊及完成工作。資訊是階層架構的,可以透過向下深入更多層級而瀏覽更多資訊。
    效率型應用程式一般採用多個視圖,通常每一視圖顯示一個層次的資訊。使用介面通常簡單,整潔且由標準視圖和控制元件組成。效率型應用程式通常沒有很多自定義介面。原因在於效率型應用程式專注於資訊和任務,而非環境或體驗。

    螢幕快照 2013-08-25 下午2.18.11

  2. 融入式應用程式:遊戲是典型的例子,這種應用程式使用非常客製化的介面,讓使用者與裝置互動,HIG對這種應用程式的規範比較不那麼嚴格。
    使用者的焦點在於視覺上的內容和體驗,而非體驗背後的數據。
  3. 工具應用程式:透過盡可能少的互動與組態設定提供使用者特定的資訊。這種APP通常比生產力應用程式有更多的介面且更加被要求要符合HIG規範。
    實用型應用程式俱有視覺上的吸引力,但是又能夠突出它們顯示的資訊。使用者使用實用型應用程式來查看一些事情的狀態或是查找一些東西,所以使用者希望能夠快速方便地看到他們感興趣的資訊。因此,實用型應用程式的使用者介面十分簡潔,並提供簡單的,標準的視圖和控制元件。
    實用型應用程式一般以平面列表的方式顯示資訊;使用者通常不需要深入資訊層次結構。實用型應用程式中的每一個視圖通常都提供同樣的數據組織結構和細節深度,但是數據來源可以不同。由此,使用者可以打開單個實用型應用程式以對多個主題進行相似處理。一些實用型應用程式能顯示打開的視圖的數量;由此使用者可以按順序瀏覽,在一個視圖後選擇另一個視圖。(例如下圖使用者可以用上一層的設定界面讓下一層的天氣資料顯示不同地區的資訊)
    螢幕快照 2013-08-25 下午2.31.31

開發APP時要注意的點

  1. 畫面比電腦小很多:應考量將複雜的畫面簡化
  2. 記憶體有限:因為ios的記憶體不包括磁碟交換空間,所以在app開發時要注意不能同時使用太高的記憶體,ios在記憶體不足時,也是會從耗記憶體最高的app開始關閉。
  3. 每次只能顯示一個視窗:不能同時瀏覽多個視窗,只可以依序瀏覽。
  4. 同一時間只能運行一個程式:因為當接電話、切到另一個應用程式等,現有的應用程式將被關閉。應要注意在使用者離開再回來時的畫面順暢度。
  5. 簡單易懂的操作說明

 人機介面準則

  1.  當使用者操作螢幕上的對象時,這些對象保持可見,並且操作結果是一目了然的。
  2. 讓使用者做出選擇,而不是要求他們進行開放式的輸入,這樣能夠讓使用者能夠集中精力通過您的程式完成任務,而不是疲於記憶如何操作。
  3. 如果有一個動作,使用者需要長時間的等待,應該回饋一個音效或圖案。在完成資料下載時,也應讓使用者知道動作已完成。應隨時回饋使用者,讓他能了解現在系統正在做什麼。
  4. 使用者控制:由使用者來觸發和控制操作
  5. 美學完整性:美學上的完整性並不是用來衡量您的程式有多漂亮,而是衡量您程式的外觀和程式功能結合得有多好。例如,一個效率型應用程式應盡量精簡裝飾性的元素並置於背景中,同時使用標準控制元件和行為以突出任務。

優秀iPhone應用程式的共性

  1. 簡單和易用性
  2. 顯而易見:您可以最大限度地減少使用者必須選擇的控制元件數量,並清晰地標識這些控制元件以便使用者明白它們的功能。
  3. 由上而下的佈局:使用者可以用手指或大拇指點選一個iPhone OS的裝置的螢幕。使用者傾向於用他們的非慣用手握住裝置(或擱在手心),用慣用手的手指點選裝置。當使用大拇指時,人們要麼將裝置一手握住,然後用大拇指點選,要麼將裝置握於雙手間,同時用兩根大拇指點選。
    無論用哪一種方式,對於使用者來說螢幕最上方都是最顯眼的。因此把最重要的資訊放在上方。
  4. 最大限度地減少所需的輸入:向使用者請求輸入時,考慮使用表格視圖(或選擇器)來代替文字輸入框。
  5. 簡潔地表達資訊:當使用者介面上的文字簡短而又直接的話,使用者就能夠快速地理解它。
  6. 為控制元件提供指尖大小的目標區域:一個簡單易用的使用者介面應該合理地分配控制元件和其他使用者介面元素,使得使用者能夠更方便地點中控制元件。
  7. 將重點放在主要功能上:確定在每個上下文中甚麼是最重要。
  8. 有效地溝通:避免使用技術性術語,讓使用者看不懂
  9. 適當的支援手勢:例如在表格list裡抓取使用者向右滑動的手勢,來顯示刪除功能。
    螢幕快照 2013-08-25 下午11.10.05
  10. 慎重地融合品牌元素:應該以一種低調的方式引入您的品牌的顏色或圖片
發佈日期:

UIViewController切換、Notification、Delegate及繪圖練習

練習目標:http://www.youtube.com/watch?v=xiHBN2B1Vt4&list=UUPRP4bs_BNpx6XWI5Wm7O5g
老師範例:DrawSomething
我的作品:homework0810

在這個範例中,我使用了兩個viewController,去控制兩個頁面的畫面。

第一個用來顯示動畫的地方的viewController如下,
在這個頁面上除了球之外,還會有一個控制開關的鈕,當打開時代表不去管路徑如何直接讓球到圓點,
而關閉則會讓球一步步照著所繪的路線移動。
#import “ViewController.h”

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UISwitch *straightSwitch;
@property (weak, nonatomic) IBOutlet UIImageView *myBall;

@end

@implementation ViewController

– (void)viewDidLoad
{
[super viewDidLoad];
}

– (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}

/* 當切換畫面時會呼叫這個函數,可在此設定接收繪圖路徑資料的接收者為自己*/
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:@”toDrawing”]){
ViewController2 * modalView = (ViewController2 *) segue.destinationViewController;
modalView.delegate = self;
}
}

/*這個函數是讓另一個ViewController去呼叫的,傳入path*/
-(void) DrawViewController:(ViewController2 *) ViewController path:(NSMutableArray *) path{
if([path count] == 0) return;
if(self.straightSwitch.on){
NSValue *value = [path objectAtIndex:[path count]-1];
[self performSelector:@selector(changePosition:) withObject:value afterDelay:0];
}else{
for (int i=0; i<[path count]; i++) { NSValue *value = [path objectAtIndex:i]; [self performSelector:@selector(changePosition:) withObject:value afterDelay:i*0.1]; } } } /*改變球的位置*/ -(void)changePosition:(NSValue *) value{ CGPoint point = [value CGPointValue]; CGRect rect = [self.myBall frame]; rect.origin.x = point.x - 25; rect.origin.y = point.y - 25; [self.myBall setFrame:rect]; } @end[/code] 第二個view則是用來讓使用者繪製路線的地方, 在這邊我又將繪圖的地方獨立出來成為另一個繪圖版 而我讓view與繪圖間用notification來傳遞資料。 [code lang="c"]#import "ViewController2.h" #import "DrawPanel.h" @interface ViewController2 () @property (weak, nonatomic) IBOutlet UIImageView *myBall; @property (weak, nonatomic) IBOutlet DrawPanel * myDrawPanel; @end @implementation ViewController2{ NSMutableArray * path; } @synthesize myDrawPanel; - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization } return self; } - (void)viewDidLoad { [super viewDidLoad]; //註冊監聽事件 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(getPathData:) name:@"getPathData" object:nil]; } //監聽繪圖版的繪圖事件接收器 -(void) getPathData:(NSNotification *) note{ NSDictionary *dict = [note userInfo]; path = [dict valueForKey:@"path"]; } //將繪圖資料array傳回第一個view - (IBAction)ActionBtnTouch:(id)sender { [self dismissViewControllerAnimated:YES completion:^{ if([self.delegate respondsToSelector:@selector(DrawViewController:path:)]){ [self.delegate DrawViewController:self path:path]; } }]; } //在移除這個view時要順便將監聽事件移除 -(void)removeFromParentViewController{ [myDrawPanel removeObserver:self forKeyPath:@"price"]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } @end[/code] 這個則是繪圖版的code [code lang="c"]#import "DrawPanel.h" @implementation DrawPanel @synthesize path; - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // Initialization code } return self; } //每次碰觸時都清空array的值 -(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ path =[NSMutableArray array]; } //移動時將所移動到的位置紀錄下來 -(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{ UITouch *touch = [touches anyObject]; CGPoint touchLocation = [touch locationInView:self]; NSValue *value = [NSValue valueWithCGPoint:touchLocation]; [path addObject:value]; [self setNeedsDisplay];//請view更新畫面 } //將資料傳給繪圖的view(發送notification) -(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{ [[NSNotificationCenter defaultCenter] postNotificationName:@"getPathData" object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys: path , @"path",nil]]; } //實作繪圖方法 - (void)drawRect:(CGRect)rect{ CGContextRef context = UIGraphicsGetCurrentContext(); CGContextBeginPath(context); CGContextMoveToPoint(context, 55, 325); for(int i = 0;i<[path count];i++){ NSValue *value = [path objectAtIndex:i]; CGPoint newPoint = [value CGPointValue]; CGContextAddLineToPoint(context, newPoint.x, newPoint.y); } //CGContextClosePath(context); [[UIColor blackColor] setStroke]; CGContextDrawPath(context, kCGPathStroke); } @end[/code] 檔案下載:homework0810

發佈日期: 2 則留言

提升Flash效能的幾個注意事項

本文為看這篇文章之後的重點整理: http://www.adobe.com/devnet/flash/articles/efficiency-tips.html

這篇文章同時會對Flash開發程式師、動畫及美術有幫助。

提升效能

  1. 關掉沒有用到的物件的互動功能:
    減少畫面中active的物件能有效的增加效能,下面這段CODE可以關閉掉MovieClip和其他物件的所有互動關係。

    mouseEnabled = false;
    mouseChildren = false;

    如果仍要與其他的元件做互動則使用mouseChildren = false;就好。
    fig01

  2. 判斷何時該用點陣圖(Bitmap)何時該用形狀(Shape):
    使用Bitmap:當今天圖片有許多漸層、複雜圖案、顏色很多時,用Bitmap較好。
    使用Shape:當今天的圖片是大塊色塊組成,感覺不利於縮放、但卻不需要縮放時,則使用Shape。(點陣圖按CTRL+B)fig02
  3. 將線段轉成色塊:線段所需要耗用的效能較多,因此可將不必要的線段轉換為填色。(在修改>形狀>將線段轉換成填色)
    fig03
  4. 避免使用虛線或點線,因為此種線段很耗費效能。
  5. 避免使用圓角,圓角比起直角的處理上耗效能。
  6. 避免圖像的坐標坐落位置帶有小數點,因為小數點的運算比起整數會耗費更多效能。

向量圖形最佳化

  1. 減少圖形中的節點(按修改>圖像>最佳化),或使用平滑工具來減少節點。
    fig06
  2. 避免使用漸層:漸層是非常耗效能的,若是必需要使用漸層,可在完成後,將其轉為Bitmap格式,或者以純色去取代。
  3. 不要使用不必要大小的bitmap圖片,或多餘的aplha值=0的透明色塊。因為這樣會增加所耗費的效能。
    fig08
  4. 避免使用遮罩:使用遮罩時,每次進入下一個影格都會重新繪製並產生裡面的元件,因此會耗費大量的效能。所以我們要盡量避免使用遮罩功能,若真的有需要,可以改用程式裡的scrollRect功能來取代遮罩,這樣在實務上會省下許多的資源,缺點是只能做方形遮罩。
    fig09
  5. 靜態物件避免使用濾鏡特效:因為濾鏡特效是每次重繪時都要重新計算一次特效顯示的值,若是今天是靜態物件要做濾鏡效果,可先在PHOTOSHOP內做好,便可節省濾鏡特效的運算時間。
    fig10
  6. 將陰影效果的品質調低
    fig12
  7. 假如圖片要resize,不要直接在flash裡改變圖片大小,而應該在外部先做好resize再loading進來。可以使用mipmapping 來計算圖片的最佳大小。
  8. 降低影格速度
    fig13
  9. 避免MovieClip呈現槽狀結構
    fig14
  10. 動畫目標物件可設置快取為點陣圖以節省效能,但此時要注意不要對該元件設置任何濾鏡,不然他每一個影格都會重新快取一次目標物件,這會耗費非常高的效能。
    2013-08-23_165042
    fig15
  11. 濾鏡特效的設定值設為2的指數(ex: 2 4 8 16….)
    fig16
  12. 如果只是非常簡單的動畫(如單純的位移事件),可以用程式碼去替代(如TweenLite),會更高彈性且節省效能。
    fig18
  13. 2.5D的CPU圖像模式的運算會很耗效能,此時可以用”快取為點陣圖”來製作2.5D的圖像。
  14. 觀察重繪區塊,去知道是那邊耗費較多的效能。(在FLASH DEBUG按右鍵=>顯示重繪區域),盡量讓重繪的區塊降到最低。
  15. 假如要設一個元件為不可視,記得停掉該元件,避免他在背後繼續執行(下stop)。
    fig22
  16. 避免元件出現在可視範圍外,若是需要將元件移除或移入視線,可以使用addChild()及removeChild()
  17. 除非有需要做特殊的文字效果,否則不要使用TLF text Field。

最佳化檔案素材大小

  1. 選擇適當的圖像壓縮比、非必要時,避免勾選”平滑化”的選項。
    2013-08-23_180249
  2. 考慮使用一整張的圖片或是用BITMAP填色:因為若顯示的區塊很小,但我們用一張超大張的圖片來做填色,這一大塊的圖片都會被包在SWF裡,因此若遇到這個狀況,可以用CTRL+B將點陣圖打散成形狀,將其縮小後,再將其轉回點陣圖,直接使用該圖片做為底色。
    但假如現況是某一張小圖片,會重複的出現在眾多區塊做為底色,那這時後就推薦用以BITMAP來填滿區塊的方式。
  3. 盡量避免在畫面中RESIZE圖片的大小
    fig27
  4. 假使是很單純、色塊及線條極少的狀況,可以將點陣圖轉為向量圖,這樣可以縮小SWF的體積。(修改>點陣圖>轉換為向量圖)
    2013-08-23_190251
  5. 一格格的動畫改為移動漸變動畫(這樣是省空間,但會耗效能,所以要取決於現在你是需要效能或者空間,去決定該用那種作法)。
    fig29
  6. 當個向量圖會在很多地方重覆出現時,將其轉換為SYMBOLS(圖像),這樣會可以在很多地方共用一個資源。
  7. 要嵌入字型時,只嵌入自己所需要的字碼範圍
    fig30
  8. 可在發佈設定的地方建立專案的描述檔去觀察所有元件的大小(右顛齒輪可新增描述檔)
    2013-08-23_190943
  9. 在發佈設定=>SWF=>進階的地方,把”包含XMP中繼資料”選項取消,可以減少一些檔案大小。
    2013-08-23_191205

優雅的開發FLASH(重點整理)

  1. 避免元件的所在位置帶有小數點
    fig32
  2. 考慮現在該用BITMAP或是SHAPE
  3. 文字字型選擇”消除鋸齒增加易讀性”
  4. 除非必要,不要讓文字變成可選擇的
    fig35
  5. 沒有需要移動漸變的影格不要設為移動漸變,可按右鍵的”移除補間動畫”來移除。
    fig36
    2013-08-23_191910
  6. 將元件的APLHA設為0時,他依然會接受滑鼠事件,會耗費處理滑鼠事件的效能。將元件的VISIBLE設為FALSE,元件仍然在畫面上。最好的方式是將其整個圖像完全刪除。
  7. 不要把元件壓在另一個元件之下,因為他還是會耗廢效能,把他的visible設為false或直接移除都可節省效能。