天天看點

iOS開發之自定義segment實作視圖切換

好久沒有更新部落格了,最近活比較忙,可能有3個禮拜沒有來更新部落格了。近期在做項目的時候,需求需要App中有一個可以控制視圖切換的控件,其實原理就是ios中的segment控件,但是sdk中的控件過于官方化,項目需要按照自己的設計圖來實作它。是以研究了一下自己寫了一個類似segment的控件,在這裡跟大家分享一下。ps:控件外觀還需要需改,這裡隻是将我實作的原理跟大家分享一下。

先看效果圖:

iOS開發之自定義segment實作視圖切換
iOS開發之自定義segment實作視圖切換

通過點選下面的控件來實作視圖的切換,目前的按鈕會更改外觀,而其他的按鈕則會恢複未點選的效果。

邏輯代碼如下:

//
//  CustomSegmentView.h
//  PanderStrategy
//
//  Created by silicon on 14-9-2.
//  Copyright (c) 2014年 silicon. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "UIButton+Icon.h"

@protocol CustomDelegate <NSObject>

- (void)buttonClick:(NSInteger)sender;

- (void)topButtonClick:(NSString *)sender;

@end


@interface CustomSegmentView : UIView

@property (nonatomic, strong) UIColor *cusBkColor;
@property (nonatomic, strong) UIColor *cusSelColor;
@property (nonatomic, strong) NSMutableArray *segmentArray;
@property (nonatomic, strong) UIColor *cusTextColor;
@property (assign) float cusbWidth;
@property (nonatomic, strong) UIColor *cusbColor;
@property (strong, nonatomic) id<CustomDelegate>myDelagte;


- (id)initWithFrame:(CGRect)frame
       segmentArray:(NSArray *)_array
         background:(UIColor *)_bkColor
      selectedColor:(UIColor *)_selColor
        borderColor:(UIColor *)_bColor
        borderWidth:(float)_bWidth
           textFont:(UIFont *)_font
          textColor:(UIColor *)_textColor
           position:(NSString *)_position;

//- (id)initWithOtherFrame:(CGRect)frame
//       segmentArray:(NSArray *)_array
//         background:(UIColor *)_bkColor
//      selectedColor:(UIColor *)_selColor
//        borderColor:(UIColor *)_bColor
//        borderWidth:(float)_bWidth
//           textFont:(UIFont *)_font
//          textColor:(UIColor *)_textColor
//           position:(NSString *)_position;





@end
           

實作檔案:

//
//  CustomSegmentView.m
//  PanderStrategy
//
//  Created by silicon on 14-9-2.
//  Copyright (c) 2014年 silicon. All rights reserved.
//

#import "CustomSegmentView.h"

@implementation CustomSegmentView
@synthesize cusBkColor = _cusBkColor;
@synthesize cusSelColor = _cusSelColor;
@synthesize segmentArray = _segmentArray;
@synthesize cusTextColor = _cusTextColor;

- (id)initWithFrame:(CGRect)frame
       segmentArray:(NSArray *)_array
         background:(UIColor *)_bkColor
      selectedColor:(UIColor *)_selColor
        borderColor:(UIColor *)_bColor
        borderWidth:(float)_bWidth
           textFont:(UIFont *)_font
          textColor:(UIColor *)_textColor
           position:(NSString *)_position
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        [self setBackgroundColor:_bkColor];
        self.cusBkColor = _bkColor;
        self.cusSelColor = _selColor;
        self.cusTextColor = _textColor;
        self.cusbWidth = _bWidth;
        self.cusbColor = _bColor;
        
        self.segmentArray = [[NSMutableArray alloc] init];
        
        float width = frame.size.width/_array.count;
        for (int i = 0; i < [_array count]; i++) {
            UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(width * i, 0, width, frame.size.height)];
//            [btn setImageWithTitle:[UIImage imageNamed:@"email"] withTitle:[_array objectAtIndex:i] position:@"right" font:_font forState:UIControlStateNormal];
            
            //不需要圖檔與文字一起顯示
            [btn setTitle:[_array objectAtIndex:i] forState:UIControlStateNormal];
            [btn setFont:_font];
            
            [btn addTarget:self action:@selector(clickSegment:) forControlEvents:UIControlEventTouchUpInside];
            
            [_segmentArray addObject:btn];
            [self addSubview:btn];
        }
        self.layer.masksToBounds=YES;
    }
    return self;
}


//- (id)initWithOtherFrame:(CGRect)frame segmentArray:(NSArray *)_array background:(UIColor *)_bkColor selectedColor:(UIColor *)_selColor borderColor:(UIColor *)_bColor borderWidth:(float)_bWidth textFont:(UIFont *)_font textColor:(UIColor *)_textColor position:(NSString *)_position{
//    self = [super initWithFrame:frame];
//    if (self) {
//        // Initialization code
//        [self setBackgroundColor:_bkColor];
//        self.cusBkColor = _bkColor;
//        self.cusSelColor = _selColor;
//        self.cusTextColor = _textColor;
//        self.cusbWidth = _bWidth;
//        self.cusbColor = _bColor;
//        
//        self.segmentArray = [[NSMutableArray alloc] init];
//        
//        float width = frame.size.width/_array.count;
//        for (int i = 0; i < [_array count]; i++) {
//            UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(width * i, 0, width, frame.size.height)];
//            [btn setTitle:[_array objectAtIndex:i] forState:UIControlStateNormal];
//            [btn setFont:_font];
//            [btn addTarget:self action:@selector(clickOtherSegment:) forControlEvents:UIControlEventTouchUpInside];
//            
//            [_segmentArray addObject:btn];
//            [self addSubview:btn];
//        }
//        self.layer.masksToBounds=YES;
//    }
//    return self;
//}

/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
    // Drawing code
}
*/

- (void)clickSegment:(id)sender{
    UIButton *btn = (UIButton *)sender;
    NSUInteger index = [_segmentArray indexOfObject:btn];
    
    [self.myDelagte buttonClick:index];
    [self updateSegmentStates:index];
    
}

//- (void)clickOtherSegment:(id)sender{
//    UIButton *btn = (UIButton *)sender;
//    NSUInteger index = [_segmentArray indexOfObject:btn];
//    
//    [self.myDelagte topButtonClick:btn.titleLabel.text];
//    [self updateSegmentStates:index];
//}

- (void)updateSegmentStates:(NSUInteger )index{
    self.layer.borderWidth=self.cusbWidth;
    self.layer.borderColor=self.cusbColor.CGColor;
    
    for (int i = 0; i < [_segmentArray count]; i++) {
        if(i == index){
            UIButton *btn = [_segmentArray objectAtIndex:index];
            [btn setBackgroundColor:_cusSelColor];
            [btn setTitleColor:_cusTextColor forState:UIControlStateNormal];
        }else{
            UIButton *btn = [_segmentArray objectAtIndex:i];
            [btn setBackgroundColor:_cusBkColor];
            [btn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
        }
    }
}
@end<span style="color: rgb(255, 255, 255); font-family: Menlo; font-size: 13px;">egmentView</span>
           

接下來,我們就來分析一下代碼:

CustomSegmentView繼承自UIView,這樣在它初始化完成以後,我們就可以直接得到一個UIview的類型,然後通過addSubView的方式将他加入到主視圖中。

我将他的initWithFrame函數擴充了一下,使它可以傳入我們自定義的參數來初始化視圖。

- (id)initWithFrame:(CGRect)frame

       segmentArray:(NSArray *)_array

         background:(UIColor *)_bkColor

      selectedColor:(UIColor *)_selColor

        borderColor:(UIColor *)_bColor

        borderWidth:(float)_bWidth

           textFont:(UIFont *)_font

          textColor:(UIColor *)_textColor

           position:(NSString *)_position

segmentArray:存放需要顯示的視圖名稱标題

background:背景色

selectedColor:選中狀态顔色

borderColor:邊框顔色

borderWidth:邊框粗細

textFont:标題字型及大小

textColor:字型顔色

position:顯示位置,這個參數的作用是當segment中需要顯示文字加圖示的形式的時候,來定義圖示顯示方位的參數

邏輯代碼很簡單直接看源碼就能了解了。

- (void)clickSegment:(id)sender函數是按鈕響應的函數,在該類中,我們使用了代理的方式,告知使用該控件的視圖,使用者是點選的哪一個視圖。

- (void)updateSegmentStates:(NSUInteger )index:函數則是用于更新按鈕狀态的函數,當某一個按鈕被幾點之後,外觀需要怎麼更改,以及其他未被點選的按鈕背景外觀如何

顯示。

@protocol CustomDelegate <NSObject>

- (void)buttonClick:(NSInteger)sender;

- (void)topButtonClick:(NSString *)sender;

@end

則是我定義的代理,ios代理模式怎麼使用我這裡就不加解釋了,我之前的文章有講過,使用者可自行檢視。

接下來,由于有時候要顯示的時圖檔加标題形式的segment,類似微信的底端,如圖所示:

iOS開發之自定義segment實作視圖切換

因為我們添加的都是UIButton,如果要顯示成帶文字跟圖檔的那我目前能想到的就隻有兩種情況,一種就是做背景圖檔檔案跟圖示一起做上去,然後點選的時候換背景。

還有一種情況就是我們去擴充一下UIButton的類别,使之可以支援文字跟圖檔。既然做開發麼,當然不能偷懶選擇第一種方式了,除非萬不得已哦。我自定義了一個

UIButton+Icon的類别,然後在裡面添加了擴充函數,代碼如下:

#import <Foundation/Foundation.h>

@interface UIButton (CustomBtn)

- (void)setImageWithTitle:(UIImage *)image withTitle:(NSString *)title position:(NSString *)_position font:(UIFont *)_font forState:(UIControlState)stateType;

@end
           
#import "UIButton+Icon.h"

@implementation UIButton (CustomBtn)

- (void)setImageWithTitle:(UIImage *)image withTitle:(NSString *)title position:(NSString *)_position font:(UIFont *)_font forState:(UIControlState)stateType{
    CGSize titleSize = [title sizeWithFont:[UIFont systemFontOfSize:11.0f]];
    [self.imageView setContentMode:UIViewContentModeCenter];
    
    if([_position isEqualToString:@"left"]){
        [self setImageEdgeInsets:UIEdgeInsetsMake((self.frame.size.height - 50)/2, 10.0, 0.0, 0)];
    }else if([_position isEqualToString:@"top"]){
        [self setImageEdgeInsets:UIEdgeInsetsMake(5.0, 0.0, 20.0, -titleSize.width)];
    }else if([_position isEqualToString:@"right"]){
        [self setImageEdgeInsets:UIEdgeInsetsMake((self.frame.size.height - 50)/2, titleSize.width + 25, 0.0, 0.0)];
    }

    
    [self setImage:image forState:stateType];
    
    [self.titleLabel setContentMode:UIViewContentModeCenter];
    [self.titleLabel setBackgroundColor:[UIColor clearColor]];
    [self.titleLabel setFont:_font];
    
    if([_position isEqualToString:@"left"]){
        [self setTitleEdgeInsets:UIEdgeInsetsMake((self.frame.size.height - 50)/2,
                                                  image.size.width,
                                                  0.0,
                                                  0.0)];
    }else if([_position isEqualToString:@"top"]){
        [self setTitleEdgeInsets:UIEdgeInsetsMake(30.0,
                                                  -image.size.width,
                                                  0.0,
                                                  0.0)];
    }else if([_position isEqualToString:@"right"]){
        [self setTitleEdgeInsets:UIEdgeInsetsMake((self.frame.size.height - 50)/2,
                                                  -40.0,
                                                  0.0,
                                                  0)];
    }
    
    
    [self setTitle:title forState:stateType];
}

@end
           

- (void)setImageWithTitle:(UIImage *)image withTitle:(NSString *)title position:(NSString *)_position font:(UIFont *)_font forState:(UIControlState)stateType;函數就是用來

設定圖檔以及文字共存的方法,使用者可以通過傳遞 “left”,"top","right"參數來設定圖示的顯示位置。使用方法很簡單,在我們添加UIButton的時候,調用該方法來進一步初始化按鈕的顯示。添加該方法後的顯示效果如下:

iOS開發之自定義segment實作視圖切換
iOS開發之自定義segment實作視圖切換
iOS開發之自定義segment實作視圖切換

我這邊圖省事,就全都使用了一個圖示,當然界面還需要做的更加精細一些,在日後我會慢慢完善。

本文就到這吧,有什麼錯誤的地方請大家指出來,謝啦!!!

繼續閱讀