- (void) showSectionListbyCount:(float)totalCount everyColCount:(float)paramColCount{
int curNum=1;
int TotalRow= ceilf(totalCount/paramColCount);// 總行數
for (int curRow=0; curRow
for (int curCol=0; curCol// 列數
if (totalCount
return;
}
UIButton *btn=[UIButton buttonWithType:UIButtonTypeCustom];
[btn setFrame:CGRectMake(10+(67+10)*curCol, (30+10)*curRow, 67, 30)];
[btn setTitle:[NSString stringWithFormat:@"%d",curNum] forState:UIControlStateNormal];
[btn setBackgroundImage:[UIImage imageNamed:@"btn_tv_n"]forState:UIControlStateNormal];
[btn setBackgroundImage:[UIImage imageNamed:@"btn_tv_h"]forState:UIControlStateHighlighted];
[btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[btn setTitleColor:[UIColor whiteColor] forState:UIControlStateHighlighted];
[btn addTarget:self action:@selector(ClickControlAction:)forControlEvents:UIControlEventTouchUpInside];
[btn setTag:curNum];
[self.view addSubview:btn];
curNum++;
}
}
}
如果,我們想用表格,那麼每個元素可以使用UITableViewCell來定義相近的項。
很簡單是吧,因爲,xCode,爲我們提供了這些UI控件供我們使用!所以,我們只需要用!
那麼,今天的問題也就來了!如果,我想搞一個能夠滿足自己的一些UI元素。別急,也就是這樣:
比如,我要搞這麼一個界面!
我想,首先可以肯定,蘋果不可能爲我量身定製了這麼一個控件。並且,如果,我用蘋果的默認控件來寫,那麼我肯定會崩潰的。。
也就是說,我們將每一項,寫成單獨的一個UI控件。那麼,可以根據數據進行填充!那就酷斃了!
繞了,一大圈,也就是要引用出來今天要學習的,東西!
自定義UI!!!
說起來,很牛X。其實很簡單,說白了,就是子類化(重寫)UIView。
我們常常重寫,UIButton,UIImageView,UITableView 等等。因爲,可能我們用到的跟這些已有控件很相似,稍微修改一些就能夠滿足我們。
但是,出入大的時候,我們就不能簡單的繼承於一個已有控件了!
那就是完全重寫!就是子類化UIView。
開始動手吧!!!
1.定義一UIView個的子類。
這個不解釋!
2.重寫drawRect方法。或者重寫layoutSubviews方法、
1. drawRect方法:
- (void)drawRect:(CGRect)rect
{
// Drawing code
for (int i=0; i<<span style="color: #2f2fd0">10; i++) {
UIButton *btn=[UIButton buttonWithType:UIButtonTypeCustom];
[btn setFrame:CGRectMake(10, 10+i*40, 67, 30)];
[btn setBackgroundImage:[UIImage imageNamed:@"btn_n"] forState:UIControlStateNormal];
[btn setBackgroundImage:[UIImage imageNamed:@"btn_h"] forState:UIControlStateHighlighted];
[btn addTarget:self action:@selector(ClickControlAction:)forControlEvents:UIControlEventTouchUpInside];
[btn setTag:i];
[self addSubview:btn];
}
}
2. layoutSubviews 方法
- (void)layoutSubviews{
[super layoutSubviews];
[self setBackgroundColor:[UIColor clearColor]];
[_imgPic setFrame:CGRectMake(7, 6, 86, 108)];
[_imgPic setImage:[UIImage imageNamed:[self.dictData objectForKey:@"img_content"]]];
[_imgPic.layer setShouldRasterize:NO];
[_imgPic.layer setBorderColor: [[UIColor whiteColor] CGColor]];
[_imgPic.layer setBorderWidth: 1.0];
[[_imgPic layer] setShadowRadius:2];
[[_imgPic layer] setShadowOpacity:1];
[[_imgPic layer] setShadowColor:[UIColor blackColor].CGColor];
[[_imgPic layer] setShadowOffset:CGSizeMake(0, 1)];
[self addSubview:self.imgPic];
}
可見,這兩種方法都可以的。具體的區別,就是drawRect方法和layoutSubviews方法之間的區別了。
但是,經過測試,我發現,應該使用drawRect方法,來完成界面的繪製。因爲,如果我們使用的是layoutSubviews方法,那麼每一次改變frame的時候,layoutSubviews都將重新執行。顯然不科學。
在網上,我看到,大部分例子使用的是drawRect方法,來重繪界面。(繪製界面)
我使用了layoutSubviews方法。在frame改變時,會自動調用。(重定向子視圖)
根據需要選擇使用哪一種方法!
關於兩種方法,在網上搜了一下,總結如下:
layoutSubviews在以下情況下會被調用:
1、init初始化不會觸發layoutSubviews。
2、addSubview會觸發layoutSubviews。
3、設置view的Frame會觸發layoutSubviews,當然前提是frame的值設置前後發生了變化。
4、滾動一個UIScrollView會觸發layoutSubviews。
5、旋轉Screen會觸發父UIView上的layoutSubviews事件。
6、改變一個UIView大小的時候也會觸發父UIView上的layoutSubviews事件。
7、直接調用setLayoutSubviews。
drawRect在以下情況下會被調用:
1、如果在UIView初始化時沒有設置rect大小,將直接導致drawRect不被自動調用。drawRect 掉用是在Controller->loadView, Controller->viewDidLoad 兩方法之後掉用的.所以不用擔心在 控制器中,這些View的drawRect就開始畫了.這樣可以在控制器中設置一些值給View(如果這些View draw的時候需要用到某些變量 值).
2、該方法在調用sizeToFit後被調用,所以可以先調用sizeToFit計算出size。然後系統自動調用drawRect:方法。
3、通過設置contentMode屬性值爲UIViewContentModeRedraw。那麼將在每次設置或更改frame的時候自動調用drawRect:。
4、直接調用setNeedsDisplay,或者setNeedsDisplayInRect:觸發drawRect:,但是有個前提條件是rect不能爲0。
以上1,2推薦;而3,4不提倡
drawRect方法使用注意點:
1、 若使用UIView繪圖,只能在drawRect:方法中獲取相應的contextRef並繪圖。如果在其他方法中獲取將獲取到一個invalidate 的ref並且不能用於畫圖。drawRect:方法不能手動顯示調用,必須通過調用setNeedsDisplay 或 者 setNeedsDisplayInRect,讓系統自動調該方法。
2、若使用calayer繪圖,只能在drawInContext: 中(類似於drawRect)繪製,或者在delegate中的相應方法繪製。同樣也是調用setNeedDisplay等間接調用以上方法
3、若要實時畫圖,不能使用gestureRecognizer,只能使用touchbegan等方法來掉用setNeedsDisplay實時刷新屏幕
3.自定義UIView的初始化方法。
我們常常在UIViewController中,看到initWithNibName方法:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// coding
}
return self;
}
這是xCode給我們定義好的初始化方法。
既然,我們要自定義UIView,那麼最好,根據自己的業務邏輯,來完成子類化UIView的初始化方法:
#pragma mark - Initialization 根據業務邏輯,傳入數據,初始化自己
- (id)initItemWithFram:(CGRect)frame andData:(NSMutableDictionary *)paramData{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
_dictData=[[NSMutableDictionary alloc] init];
_imgPic=[[UIImageView alloc] init];
_imgCover=[[UIImageView alloc] init];
_btnClick=[[UIButton alloc] init];
_btnDel=[[UIButton alloc] init];
_lblTips=[[UILabel alloc] init];
_lblName=[[UILabel alloc] init];
}
self.dictData=paramData;
return self;
}
+ (id) initItemWithFrame:(CGRect)frame andData:(NSMutableDictionary *)paramData{
WTVTVCollectionItem *tmpInstance=[[WTVTVCollectionItem alloc] initItemWithFram:frameandData:paramData];
return tmpInstance;
}
這樣,就可以初始化:
NSMutableArray *items = [NSMutableArray array];
[items addObject:[WTVTVCollectionItem initItemWithFrame:CGRectMake(10, 10, 100, 150)andData:dict]];
[items addObject:[WTVTVCollectionItem initItemWithFrame:CGRectMake(10, 10, 100, 150)andData:dict]];
[items addObject:[WTVTVCollectionItem initItemWithFrame:CGRectMake(10, 10, 100, 150)andData:dict]];
4.爲UIView加入一些動畫
動畫是UI操作的靈魂!給予動畫效果,就看上去有神了。
添加動畫,一般也用2種方法:
1.重寫UIView的方法,在調用時,進行動畫操作。
# pragma mark - 重寫父類的removeFromSuperview方法,在刪除時,使用相應的動畫效果
- (void) removeFromSuperview {
[UIView animateWithDuration:0.2 animations:^{
self.alpha = 0.0;
[self setFrame:CGRectMake(self.frame.origin.x+50, self.frame.origin.y+50, 0, 0)];
[_btnDel setFrame:CGRectMake(0, 0, 0, 0)];
}completion:^(BOOL finished) {
[super removeFromSuperview];
}];
}
2.直接在UIView元素上,進行動畫對象的添加
- (void) enableEditing {
if (self.isInEditingMode == YES)
return;
// 設置爲編輯狀態
self.isInEditingMode = YES;
[_btnDel setHidden:NO];
// 開始晃動動畫
CATransform3D transform;
// 獲取0到x-1之間的整數
if (arc4random() % 2 == 1)
transform = CATransform3DMakeRotation(-0.08, 0, 0, 1.0);
else
transform = CATransform3DMakeRotation(0.08, 0, 0, 1.0);
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"];
animation.toValue = [NSValue valueWithCATransform3D:transform];
animation.autoreverses = YES;
animation.duration = 0.1;
animation.repeatCount = 10000;
animation.delegate = self;
[[self layer] addAnimation:animation forKey:@"wiggleAnimation"];
[(WTVTVSprintBoard*)self.delegate enableEditingMode];
}
5.子類化UIView的交互
如何將操作鏈接起來!?就是說,在控件外,對我們自定義的控件進行操作?!
也有2種方法:
1.消息
2.代理
總結:
我想,我過多的將思路就可以了,因爲業務需求不同,控件的自定義需求也不同,所以,不能用具體來固定!但是,思路是想通的,知道了原理,我們就可以發揮我們的聰明智慧,創造出千變萬化的控件來!
希望對你有所幫助!!!