網址:http://www.2cto.com/kf/201408/329492.html
? ?之前如果做過Web前端頁面的小伙伴們铆隘,看到絕對定位和相對定位并不陌生,并且使用起來也挺方便肮帐。在IOS的UI設計中也有絕對定位和相對定位咖驮,和我們的web前端的絕對定位和相對定位有所不同但又有相似之處。下面會結合兩個小demo來學習一下我們IOS開發(fā)中UI的絕對定位和相對定位训枢。在前面的博客中所用到的UI事例用的全是絕對定位,用我們Storyboard拖拽出來的控件全是絕對定位的忘巧,就是我們可以同改變組件的frame來改變組件的位置和大小恒界。而相對定位則不同,相對定位是參考組件周圍的元素來確定組件的大小或位置砚嘴,相對定位即約束和周圍組件的距離來布局的十酣,即layoutConstraint. 在布局中LayoutConstraint和Fram布局方式是不能并存的。
上面說了這么多了际长,可能說的不太明白耸采,還是那句話,怎么能少的了代碼和實例的支持呢工育,下面會通過屏幕適配的事例來用絕對布局和相對布局同時實現下面的描述效果虾宇。
我們要實現的效果:當上面的view的大小及位置改變時,為了不覆蓋掉下面的view,我們同時要改變下view的位置如绸。 或者說在我們4.0寸正常顯示的內容嘱朽,在3.5寸屏上也能正常顯示旭贬,即通常我們所說的屏幕的適配。為了便于觀察效果搪泳,我們可以用Slider控件來動態(tài)的改變上面view的大小稀轨,觀察下面view的位置變化,下面是我們要實現的效果圖:
1.用絕對布局來實現上述效果岸军,為了節(jié)省我們代碼編寫的時間奋刽,上面的控件是通過storyborad來實現的,然后在對應的ViewController里添加組件和控件回調的方法艰赞,主要是在slider滑動的時候來獲取slider的值杨名,然后動態(tài)的設置上面View的frame坐標(當然,如果讓view往四周擴展得計算一下新的fram的值猖毫,然后動態(tài)的修改)台谍,上面的view位置和大小改變了,那么下面的view不能被上面的覆蓋掉吁断,所以也得修改blackView的fram的值趁蕊。這種通過修改frame的值的方式來確定組件位置即為絕對布局
下面是由storyboard拖拽過來的屬性:
//把最上邊的view拖拽到我們的代碼中
@property (strong, nonatomic) IBOutlet UIView *myView;
//添加slider
@property (strong, nonatomic) IBOutlet UISlider *mySlider;
//添加下面黑色的view
@property (strong, nonatomic) IBOutlet UIView *blackView;
下面是當slider的值改變時要回調的方法:
//當slider的值改變的時候回調的方法
- (IBAction)sliderFunction:(id)sender
{
//獲取slider的當前值(在storyboard設置的范圍為0-120)
double value = self.mySlider.value;
//獲取myView的位置
CGRect frame = self.myView.frame;
//根據slider的值動態(tài)的設置myView的坐標和寬高,設置的時候view中心不變
frame.origin.x =? 120-value;
frame.origin.y = 66 * (1-value/120);
frame.size.height = 320-frame.origin.x*2;
frame.size.width = 320-frame.origin.x*2;
//更新myView的位置
self.myView.frame = frame;
//同時改變下面黑色view的坐標
CGRect bf = self.blackView.frame;
bf.origin.y = frame.size.height + frame.origin.y + 30;
self.blackView.frame = bf;
}
2.上面是我們的絕對布局的方式仔役,接下來要學習一下相對布局的方式掷伙。相對布局使用起來會比絕對布局要復雜一些,下面先做屏幕適配的例子又兵,圖一是在iPhone的4.0寸的效果圖任柜, 當我們不做任何處理的時候在3.5寸屏上是顯示不出來的如第二張圖:
(1)我們如何讓在3.5寸屏上也顯示正常呢,接下啦就是相對布局出出場的時候了沛厨,我們用相對布局的方式把最下面的view的位置改為相對于主視圖的底部和左邊的像素值固定宙地,同時設置slider的位置相對于下面的view的位置相對固定。也就是下面的veiw的位置改變逆皮,則上面的slider的位置也會改變宅粥,用storyboard修改如下:(第一張圖是修改最下面view的相對位置,第二張圖是設置我們slider為相對布局) 电谣,不需要在ViewController中添加任何動態(tài)嗎我們就可以實現屏幕的適配秽梅。
(2)那么我如何用相對布局實現上面那種view放大的效果呢,接下來我們需要新建一個工程剿牺,因為相對布局和絕對布局在同一個組件中無法并存企垦。在新建工程中用storyboard把我們用到的控件進行拖拽 繁调,界面和上面的是一樣的即硼。
(1)首先給我們最上面的View設置相對布局的屬性,如下面的圖一
(2)? 再給黑色的View設置相對布局的屬性遭赂,入下面的圖二所示:
(3) 設置上面兩個View相對中心對齊,選中上面的View,按著Ctrl往下面的View中拖拽臭增,在彈出的框中選中Center X入圖三
(4).給我們相應的組件在storyboard中添加上約束以后懂酱,怎樣來動態(tài)的改變最上面view的寬和高的約束范圍呢?(即改變水平約束和垂直約束的值)第一部就得把最上面的view的水平約束和垂直約束從我們的storyboard中把最上面View中我們要用的約束拖入到我們的Viewcontroller, 第一張圖是storyboard中約束所在的位置誊抛,第二張圖把約束添加到ViewController中列牺。
?? ? ?? ? ?? (5)至此我們用storyboard的工作已經做完,程序員是少不了敲代碼的拗窃,也只有正兒八經的敲代碼瞎领,程序員才會成長。所以嘍下面就是我們在ViewController中添加的代碼部分随夸。絕對布局直接改frame的坐標值就可以啦九默,那么在程序中我們如何去動態(tài)的改變我們約束的值呢?下面的代碼將會用到宾毒。 我們要做的事情就是在ViewController中通過改變slider的值來改變最上面View的水平約束和垂直約束驼修,水平約束和垂直約束的相關變量我們已經拖拽過來了,下面就需要在Slider回調的方法中來改變水平和垂直約束的值诈铛。先段代碼乙各,之后在說兩句。? ? ?? ? ?
//slider的值改變調用的方法
- (IBAction)sliderChange:(id)sender
{
//為了避免沖突移除myView的水平和垂直約束,注意是從主視圖上移除幢竹,因為約束是加載我們的主視圖上耳峦,即相對于我們的主視圖
[self.view removeConstraint:self.widthC];
[self.view removeConstraint:self.heightC];
//獲取slider的值
double sliderValue = self.mySlider.value;
//由slider的值重設我們的約束值,H代表水平約束, V代表垂直約束
NSString *widthValue = [NSString stringWithFormat:@"H:[_myView(%lf)]", sliderValue];
NSString *heightValue = [NSString stringWithFormat:@"V:[_myView(%lf)]", sliderValue];
//新建約束
NSArray *widthConstraint = [NSLayoutConstraint constraintsWithVisualFormat:widthValue options:0 metrics:nil views:NSDictionaryOfVariableBindings(_myView)];
//給水平約束重新賦值
self.widthC = widthConstraint[0];
//給垂直約束重新賦值
NSArray * heightConstraint = [NSLayoutConstraint constraintsWithVisualFormat:heightValue options:0 metrics:nil views:NSDictionaryOfVariableBindings(_myView)];
self.heightC = heightConstraint[0];
//往主視圖上添加新的約束
[self.view addConstraint:self.widthC];
[self.view addConstraint:self.heightC];
}
代碼說明:
? ? 1.一個組件中只能有一中約束焕毫,如在myView中我們已經有一個垂直約束蹲坷,我們如果再給他添加一個垂直約束的話,那么程序在運行時就會報錯邑飒,錯誤內容:“Unable to simultaneously satisfy constraints.……”循签;
? ? 2.所以在添加新的約束之前,我們得把之前加在我們組件中相應的約束給去掉幸乒;約束是加在我們對應組件的父視圖上懦底,移除也得從組件的父視圖上移除;
? ? 3.在設置約束的值的時候我們是以字符串的形式把參數傳遞給約束的罕扎,如:H:[_myView(200)] H代表水平約束,V代表垂直約束丐重。中括號里是我們要為那個組件添加約束以及約束的值是多少腔召;
? ? 4.給我們的約束更新我們新建的約束
? ? 5.在把更新的約束添加到我們的父視圖上,到此我們就可以實現上面我們上面用絕對布局實現的功能
補充說明:
? ? ?在絕對布局時我們還可以獲取屏幕的尺寸扮惦,通過屏幕的尺寸來計算我們組件所在的位置臀蛛,主要代碼如下:
//獲取屏幕大小
UIScreen *s = [UIScreen mainScreen];
//獲取屏幕邊界
CGRect bounds = s.bounds;
//獲取屏幕的高度
float height = bounds.size.height;