一些小的功能點(diǎn)执庐,雖然很小酪耕,但是里面有些彎,值得注意轨淌。(同系列文章會(huì)持續(xù)更新.......)
1.tableHeaderView的使用:
這個(gè)效果的實(shí)現(xiàn)有種比較巧妙的地方:
self.HeadImgView= [[UIImageViewalloc]initWithFrame:CGRectMake(0,0,Width,HeadImgHeight)];
self.HeadImgView.image= [UIImageimageNamed:@"eee"];
[self.tableView ?addSubview:self.HeadImgView];
//與圖像高度一樣防止數(shù)據(jù)被遮擋
self.tableView.tableHeaderView= [[UIViewalloc]initWithFrame:CGRectMake(0,0,Width,HeadImgHeight)];
? 然后在scrollViewDidScroll 的代理方法中根據(jù) sc 的偏移來動(dòng)態(tài)的改變? self.HeadImgView 的 frame就可以達(dá)到這樣的效果了因妇。
但是,這里有個(gè)彎猿诸,如果不是把這個(gè)試圖?addSubview? 在tableView 上的話婚被,直接
self.tableView.tableHeaderView= self.HeadImgView
的話,在代理中再改變? self.HeadImgView的 frame ?就會(huì)出現(xiàn)下拉時(shí)上面出現(xiàn)空白的情況梳虽。
2.在導(dǎo)航條上放視圖址芯,點(diǎn)擊字體變大:
往導(dǎo)航條上加試圖的關(guān)鍵點(diǎn):
? ?self.navigationItem.titleView= view;(這個(gè)view 是 UIScrollView)也就是上面的標(biāo)題區(qū)域
放縮關(guān)鍵點(diǎn):
bgview.transform=CGAffineTransformScale(CGAffineTransformIdentity,0.85,0.85);
或者 ? ? ? ? ? ?bgview.transform=CGAffineTransformMakeScale(0.85, 0.85);
3.上滑顯示和隱藏導(dǎo)航條:
? ? ? NavigationBar他背后是有一張類型為_UINavigationBarBackground(UIImageView的子類)的視圖,我們平時(shí)看到的大部分其實(shí)都是它窜觉,第二個(gè)箭頭那里的ImageView就是那根細(xì)線,他是加在我們背景的ImageView上面的谷炸,我們?cè)O(shè)置BackgroundImage其實(shí)就是設(shè)置_UINavigationBarBackground的image。
? ? 設(shè)置導(dǎo)航條變透明:
? ? ? ?[self.navigationController.navigationBar setBackgroundImage:[UIImage new] ??forBarMetrics:UIBarMetricsDefault];
設(shè)置導(dǎo)航條下的那條線隱藏起來:(這三條都實(shí)現(xiàn)才行)
方法一:
? ? ? ? [self.navigationController.navigationBar setBackgroundImage:[UIImage new]forBarMetrics:UIBarMetricsDefault];//這樣帶來的壞處是導(dǎo)航條會(huì)占位64像素
self.navigationController.navigationBar.shadowImage= [UIImage new];
self.navigationController.navigationBar.translucent=NO;
方法二:
//遞歸查找出那條線
navBarHairlineImageView = [[MethodTool shareTool] findHairlineImageViewUnder:self.navigationController.navigationBar];
//隱藏
navBarHairlineImageView.hidden = YES禀挫;
實(shí)現(xiàn)這個(gè)效果的關(guān)鍵點(diǎn):
barImageView=self.navigationController.navigationBar.subviews.firstObject;//用一個(gè)全局的指針旬陡,指向那個(gè) imageView,根據(jù)表的y值上的偏移量语婴,要?jiǎng)討B(tài)的改變 ?這個(gè)imageview的 透明度即可描孟,。
- (void)scrollViewDidScroll:(UIScrollView*)scrollView
{
NSLog(@"YYYY:%f",scrollView.contentOffset.y);
CGFloatoffset = scrollView.contentOffset.y;
CGFloatalpha = (offset/100);
barImageView.alpha= alpha;
}
PS:其實(shí)可以用一個(gè)自定義的導(dǎo)航條砰左,根據(jù)表的偏移量要?jiǎng)討B(tài)的改變自定義試圖的透明度匿醒。。
4.隱藏導(dǎo)航條下的細(xì)線(兩種方法):
(1)
[self.navigationController.navigationBarsetBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
self.navigationController.navigationBar.shadowImage= [UIImage new];
self.navigationController.navigationBar.translucent=NO;
這種方式有個(gè)副作用就是他回使導(dǎo)航條占64個(gè)像素缠导,如果是整個(gè)項(xiàng)目都做完之后使用這種方法隱藏的話需要修改全局 試圖的 ?Y坐標(biāo)起始點(diǎn)是 0 而不是原來的64 廉羔,所以建議 設(shè)置一個(gè)全局的宏定義 NAVHEIGHT 導(dǎo)航條的高度,來隨時(shí)更改僻造,更可控更方便
(2)
? ? UIImageView ? *navBarHairlineImageView;//一個(gè)全局的指針
navBarHairlineImageView= [selffindHairlineImageViewUnder:self.navigationController.navigationBar];
navBarHairlineImageView.hidden=YES;
//使用了一個(gè)遞歸調(diào)用找到那個(gè)1像素高度的線憋他,并隱藏它
- (UIImageView*)findHairlineImageViewUnder:(UIView*)view {
if([view isKindOfClass:UIImageView.class] && view.bounds.size.height<=1.0) {
return(UIImageView*)view;
}
for(UIView*subview in view.subviews) {
UIImageView*imageView = [self findHairlineImageViewUnder:subview];
if(imageView) {
returnimageView;
}}returnnil;
}
5.點(diǎn)擊旋轉(zhuǎn)全屏顯示:
- (void)frameChange:(UIButton*)sender {
NSIntegeri = sender.tag;
if(!sender.selected) {
sender.selected=YES;
origanRect=viewPlay[i].frame;
origanSuperV=viewPlay[i].superview;
[UIViewbeginAnimations:nilcontext:nil];
[UIViewsetAnimationDuration:0.3];
viewPlay[i].transform=CGAffineTransformMakeRotation(M_PI*(90)/180.0);
viewPlay[i].bounds=CGRectMake(0,0,HEIGHT,WIDTH);
viewPlay[i].center=CGPointMake(WIDTH/2,HEIGHT/2);
[[UIApplicationsharedApplication].keyWindowaddSubview:viewPlay[i]];
[UIViewcommitAnimations];
sender.frame=CGRectMake(0,0,CGRectGetHeight(viewPlay[i].frame),CGRectGetWidth(viewPlay[i].frame));
}else{
sender.selected=NO;
[UIViewbeginAnimations:nilcontext:nil];
[UIViewsetAnimationDuration:0.3];
viewPlay[i].transform=CGAffineTransformMakeRotation(0);
viewPlay[i].frame=origanRect;
[origanSuperVaddSubview:viewPlay[i]];
[UIViewcommitAnimations];
sender.frame=CGRectMake(0,0,CGRectGetWidth(viewPlay[i].frame),CGRectGetHeight(viewPlay[i].frame));
}
}
UIView*viewPlay[PAGECOUNT*PAGEVIEWCOUNT]; ?聲明一個(gè)數(shù)組行的UIview 組孩饼。
viewPlay[i].center的設(shè)置很重要,不管是使用? viewPlay[i].bounds? 還是?viewPlay[i].frame?都需要設(shè)置竹挡,是因?yàn)?系統(tǒng)自帶的旋轉(zhuǎn)是按照一段弧形的軌跡而不是中心點(diǎn)旋轉(zhuǎn)捣辆,如果不設(shè)置
個(gè)人更推薦第二個(gè)
6.使用 UICollectionView? 來展示圖片多選:
圖片多選擇中使用 UICollectionView ?來展示圖片,好處:展示簡(jiǎn)單此迅,刪除更簡(jiǎn)單汽畴。
實(shí)現(xiàn)關(guān)鍵點(diǎn):
-(UICollectionViewCell*)collectionView:(UICollectionView*)collectionView ? ? ? ? ? ? ?cellForItemAtIndexPath:(NSIndexPath*)indexPath{
?**最后一個(gè)item**
?if(indexPath.item==arrayImages.count) {
? ?CleandarCollectionViewCell*cell = ? ? ?[collectionViewdequeueReusableCellWithReuseIdentifier:@"CleandarCollectionViewCell"fo rIndexPath:indexPath];
cell.imgV.image= [UIImageimageNamed:@"add_photo"];
cell.backgroundColor= [UIColorgrayColor];
returncell;
}
**其他item**
CleandarCollectionViewCell*cell = ? [collectionViewdequeueReusableCellWithReuseIdentifier:@"CleandarCollectionViewCell"forIndexPath:indexPath];
[cell.imgVsetImage:arrayImages[indexPath.item]];
returncell;
}
-(void)collectionView:(UICollectionView*)collectionView didSelectItemAtIndexPath:(NSIndexPath*)indexPath{
[self.viewendEditing:YES];
**最后一個(gè)**
if(indexPath.item==arrayImages.count) {
UIActionSheet*sheet = [[UIActionSheetalloc]initWithTitle:@"相片來源"delegate:selfcancelButtonTitle:@"取消"destructiveButtonTitle:nilotherButtonTitles:@"相機(jī)",@"相冊(cè)",nil];
[sheetshowInView:self.view];
}else{
UIAlertController*alertController = [UIAlertControlleralertControllerWithTitle:@"確定刪除該張圖片"message:nilpreferredStyle:UIAlertControllerStyleAlert];
UIAlertAction*action = [UIAlertActionactionWithTitle:@"是"style:UIAlertActionStyleDefaulthandler:^(UIAlertAction*action) {
[arrayImagesremoveObject:arrayImages[indexPath.item]];
[self.collectionreloadData];
}];
[alertControlleraddAction:action];
UIAlertAction*actionDelete = [UIAlertActionactionWithTitle:@"否"style:UIAlertActionStyleDefaulthandler:^(UIAlertAction*action) {
}];
[alertControlleraddAction:actionDelete];
[selfpresentViewController:alertControlleranimated:YEScompletion:nil];
}
[self.collection reloadData];
}
7.類似滴滴打車軟件中左邊側(cè)滑時(shí)動(dòng)態(tài)隱藏 狀態(tài)欄:
相信細(xì)心的朋友會(huì)發(fā)現(xiàn)耸序,狀態(tài)欄是動(dòng)態(tài)隱藏了忍些,可是由于缺少狀態(tài)欄的20像素,造成了背部的視圖整體上移了20像素坎怪,我使用的是系統(tǒng)自帶的導(dǎo)航欄罢坝,也嘗試了動(dòng)態(tài)增加 導(dǎo)航欄的高度從44變?yōu)?4,可是總有瞬間形變?cè)斐傻牟蛔匀桓薪亮詈蠹?xì)心研究發(fā)現(xiàn)**滴滴打車是自定義的導(dǎo)航欄**嘁酿,所以我使用的方法是沒錯(cuò)的,只要需要的時(shí)候使用自定義的導(dǎo)航欄就可以達(dá)到 跟 滴滴打車一樣的效果啦男应。
關(guān)鍵代碼:
(1) View controller-based status bar appearance設(shè)為NO,這時(shí)application的設(shè)置優(yōu)先級(jí)最高闹司,用下面的方式隱藏status bar:
[[UIApplicationsharedApplication]setStatusBarHidden:YES ?withAnimation:UIStatusBarAnimationSlide];
(2)如果View controller-based status bar appearance設(shè)為YES。這時(shí)view controller中對(duì)status bar的設(shè)置優(yōu)先級(jí)高于application的設(shè)置沐飘,用下面的方式隱藏status bar:
1游桩、在view controller中調(diào)用setNeedsStatusBarAppearanceUpdate,更新status bar的顯示耐朴。
- (void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];if ([self respondsToSelector:@selector(setNeedsStatusBarAppearanceUpdate)]) {
[self prefersStatusBarHidden];
[self performSelector:@selector(setNeedsStatusBarAppearanceUpdate)];
}}
2借卧、覆蓋view controller的prefersStatusBarHidden的實(shí)現(xiàn),返會(huì)YES筛峭。
- (BOOL)prefersStatusBarHidden
{
return YES;
}
就可以達(dá)到動(dòng)態(tài)隱藏和顯示狀態(tài)欄的目的铐刘。
8.朗讀文字
使用到的是 iOS 原聲的? AVFoundation.framework 里面的API。?
使用到的類是 :AVSpeechSynthesizer?里面包括 ?開始影晓、暫停镰吵、繼續(xù)朗讀等功能。
所有的嗓音如下:
"[AVSpeechSynthesisVoice 0x978a0b0] Language: th-TH",
"[AVSpeechSynthesisVoice 0x977a450] Language: pt-BR",
"[AVSpeechSynthesisVoice 0x977a480] Language: sk-SK",
"[AVSpeechSynthesisVoice 0x978ad50] Language: fr-CA",
"[AVSpeechSynthesisVoice 0x978ada0] Language: ro-RO",
"[AVSpeechSynthesisVoice 0x97823f0] Language: no-NO",
"[AVSpeechSynthesisVoice 0x978e7b0] Language: fi-FI",
"[AVSpeechSynthesisVoice 0x978af50] Language: pl-PL",
"[AVSpeechSynthesisVoice 0x978afa0] Language: de-DE",
"[AVSpeechSynthesisVoice 0x978e390] Language: nl-NL",
"[AVSpeechSynthesisVoice 0x978b030] Language: id-ID",
"[AVSpeechSynthesisVoice 0x978b080] Language: tr-TR",
"[AVSpeechSynthesisVoice 0x978b0d0] Language: it-IT",
"[AVSpeechSynthesisVoice 0x978b120] Language: pt-PT",
"[AVSpeechSynthesisVoice 0x978b170] Language: fr-FR",
"[AVSpeechSynthesisVoice 0x978b1c0] Language: ru-RU",
"[AVSpeechSynthesisVoice 0x978b210] Language: es-MX",
"[AVSpeechSynthesisVoice 0x978b2d0] Language: zh-HK",? 中文(香港) 粵語
"[AVSpeechSynthesisVoice 0x978b320] Language: sv-SE",
"[AVSpeechSynthesisVoice 0x978b010] Language: hu-HU",
"[AVSpeechSynthesisVoice 0x978b440] Language: zh-TW",? 中文(臺(tái)灣)
"[AVSpeechSynthesisVoice 0x978b490] Language: es-ES",
"[AVSpeechSynthesisVoice 0x978b4e0] Language: zh-CN",? 中文(普通話)
"[AVSpeechSynthesisVoice 0x978b530] Language: nl-BE",
"[AVSpeechSynthesisVoice 0x978b580] Language: en-GB",? 英語(英國(guó))
"[AVSpeechSynthesisVoice 0x978b5d0] Language: ar-SA",
"[AVSpeechSynthesisVoice 0x978b620] Language: ko-KR",
"[AVSpeechSynthesisVoice 0x978b670] Language: cs-CZ",
"[AVSpeechSynthesisVoice 0x978b6c0] Language: en-ZA",
"[AVSpeechSynthesisVoice 0x978aed0] Language: en-AU",
"[AVSpeechSynthesisVoice 0x978af20] Language: da-DK",
"[AVSpeechSynthesisVoice 0x978b810] Language: en-US",? 英語(美國(guó))
"[AVSpeechSynthesisVoice 0x978b860] Language: en-IE",
"[AVSpeechSynthesisVoice 0x978b8b0] Language: hi-IN",
"[AVSpeechSynthesisVoice 0x978b900] Language: el-GR",
"[AVSpeechSynthesisVoice 0x978b950] Language: ja-JP" )
代碼:
#import
// 創(chuàng)建嗓音俯艰,指定嗓音不存在則返回nil
AVSpeechSynthesisVoice *voice = [AVSpeechSynthesisVoice voiceWithLanguage:@"zh-CN"];
// 創(chuàng)建語音合成器
AVSpeechSynthesizer *synthesizer = [[AVSpeechSynthesizer alloc] init];
// 實(shí)例化發(fā)聲的對(duì)象
AVSpeechUtterance *utterance = [AVSpeechUtterance speechUtteranceWithString:@"朗讀完畢"];
utterance.voice = voice;
utterance.rate = 0.5; ? ? ? ? // 語速
speech.pitchMultiplier=1; ?//音高 ? 越高聲音越尖
speech.postUtteranceDelay=0.1f;//目的是讓語音合成器播放下一語句前有短暫的暫停
speech.volume=1; ? ? ? ? ? ? //音量
[synthesizer speakUtterance:utterance];? // 朗讀的內(nèi)容
如果提示這種錯(cuò)誤:
|AXSpeechAssetDownloader|error| ASAssetQuery error fetching results (for com.apple.MobileAsset.MacinTalkVoiceAssets) Error Domain=ASError Code=21 "Unable to copy asset information" UserInfo={NSDescription=Unable to copy asset information}
請(qǐng)去iPhone里設(shè)置:
進(jìn)入iPhone的 設(shè)置 > 通用 > 輔助功能 > 語音捡遍,開啟“朗讀所選項(xiàng)”锌订,并在“嗓音”中選擇“中文”
? ? ?在真機(jī)測(cè)試的時(shí)候竹握,碰巧那臺(tái)手機(jī)的加減音量按鍵失效了,于是在手機(jī)設(shè)置里把音量調(diào)到最大辆飘,可是在測(cè)試的時(shí)候還是音量很小啦辐,最后換了一臺(tái)手機(jī)谓传,在測(cè)試的時(shí)候使用+-鍵加大了音量,聲音果然大了起來芹关,才發(fā)現(xiàn)手機(jī)設(shè)置-> 聲音-> ?設(shè)置的聲音大小是來電鈴聲的音量大小续挟,并不是揚(yáng)聲器的音量。+-鍵才能設(shè)置的是揚(yáng)聲器的音量侥衬。
9.語音轉(zhuǎn)文字
使用的是第三方 ?科大訊飛的SDK ? ? ??github 地址
10.別人的模擬器運(yùn)行起我們開發(fā)的app
場(chǎng)景:無法真機(jī)裝app| 公司的UUID 已經(jīng)使用完了 |?
解決辦法:
解決思路诗祸,想要?jiǎng)e人的模擬器運(yùn)行起我們開發(fā)的app,最簡(jiǎn)單的辦法就是把我們DerivedData的數(shù)據(jù)直接拷貝到別人模擬器上面轴总,就可以了直颅。
ditto -ck --sequesterRsrc --keepParent `ls -1 -d -t ~/Library/Developer/Xcode/DerivedData/*/Build/Products/*-iphonesimulator/*.app | head -n 1`?
我們運(yùn)行完上面的ditto命令會(huì)產(chǎn)生一個(gè)zip文件,解壓出來怀樟,會(huì)得到一個(gè)app文件功偿,這個(gè)就是debug包了。debug包就是我們要給設(shè)計(jì)師的app包了往堡。
如何能讓設(shè)計(jì)師傻瓜式的安裝這個(gè)app呢械荷?這里介紹一個(gè)命令行工具,ios-sim命令行工具虑灰。
ios-sim 是一個(gè)可以在命令控制iOS模擬器的工具吨瞎。利用這個(gè)命令,我們可以啟動(dòng)一個(gè)模擬器穆咐,安裝app关拒,啟動(dòng)app,查詢iOS SDK庸娱。它可以使我們像自動(dòng)化測(cè)試一樣不用打開Xcode着绊。