自定义底部tabbar的两种方式

第一种:利用系统自带的tabbarItem加一个自定义按钮:

#import "SZMTabBarController.h"
#import "SZMTabBar.h"
#import "SZMHomeViewCtrl.h"
#import "SZMNavigationController.h"
#import "SZMDiscoerViewCtrl.h"
@interface SZMTabBarController ()<SZMTabBarDelegate>

@end

@implementation SZMTabBarController

- (void)viewDidLoad {
    [super viewDidLoad];
    //初始化一个自己的tabbar
    SZMTabBar *tabBar = [[SZMTabBar alloc]init];
    tabBar.delegate = self;
    //通过KVC去设置只读的属性
    [self setValue:tabBar forKey:@"tabBar"];

    //添加四个控制器
    //首页
    SZMHomeViewCtrl *homeCtrl = [[SZMHomeViewCtrl alloc]init];
    [self addChildVc:homeCtrl title:@"首页" imageName:@"tabbar_home" selImgName:@"tabbar_home_selected"];

    UITableViewController *messageCtrl = [[UITableViewController alloc]init];
    [self addChildVc:messageCtrl title:@"消息" imageName:@"tabbar_message_center" selImgName:@"tabbar_message_center_selected"];
    SZMDiscoerViewCtrl *discoveryCtrl = [[SZMDiscoerViewCtrl alloc]init];
    [self addChildVc:discoveryCtrl title:@"发现" imageName:@"tabbar_discover" selImgName:@"tabbar_discover_selected"];
    UITableViewController *profileCtrl = [[UITableViewController alloc]init];
    [self addChildVc:profileCtrl title:@"我" imageName:@"tabbar_profile" selImgName:@"tabbar_profile_selected"];

}
//设置tabbar的一些属性
- (void)addChildVc:(UIViewController *)Controller title:(NSString *)title imageName:(NSString *)imgName selImgName:(NSString *)selImgName{
    Controller.title = title;
    Controller.tabBarItem.image = [UIImage imageNamed:imgName];
    Controller.tabBarItem.selectedImage = [UIImage imageNamed:selImgName];
    self.tabBar.tintColor = [UIColor orangeColor];
    SZMNavigationController *navCtrl = [[SZMNavigationController alloc]initWithRootViewController:Controller];

    [self addChildViewController:navCtrl];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

-(void)TabBar:(SZMTabBar *)TabBar plusBtnDidClick:(UIButton *)btn{
    NSLog(@"1");
}

@end
#import <UIKit/UIKit.h>
@class SZMTabBar;
#warning 我们自定义的控件,如果是继承于系统的控件的话,而且系统的控件有代理,我们的协议一定要继承父类的协议
@protocol SZMTabBarDelegate <NSObject,UITabBarDelegate>

- (void)TabBar:(SZMTabBar *)TabBar plusBtnDidClick:(UIButton *)btn;

@end
@interface SZMTabBar : UITabBar

@property (nonatomic,weak) id<SZMTabBarDelegate> delegate;
@end
#import "SZMTabBar.h"

@interface SZMTabBar ()
@property (nonatomic,weak) UIButton *plusBtn;

@end
@implementation SZMTabBar
@dynamic delegate;
- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        //添加加号按钮
        UIButton *plusBtn = [[UIButton alloc]init];
        //给button设置不同状态下背景图片
        [plusBtn setImage:[UIImage imageNamed:@"tabbar_compose_icon_add"] forState:UIControlStateNormal];
        [plusBtn setImage:[UIImage imageNamed:@"tabbar_compose_icon_add_highlighted"] forState:UIControlStateHighlighted];
        [plusBtn setBackgroundImage:[UIImage imageNamed:@"tabbar_compose_button"] forState:UIControlStateNormal];
        [plusBtn setBackgroundImage:[UIImage imageNamed:@"tabbar_compose_button_highlighted"] forState:UIControlStateHighlighted];
        [self addSubview:plusBtn];
        self.plusBtn = plusBtn;

        plusBtn.size = plusBtn.currentBackgroundImage.size;
        //给按钮添加点击事件
        [plusBtn addTarget:self action:@selector(plusBtnClick:) forControlEvents:UIControlEventTouchUpInside];
        }
    return self;
}

- (void)plusBtnClick:(UIButton *)btn{

    //代理方法的实现
    if ([self.delegate respondsToSelector:@selector(TabBar:plusBtnDidClick:)]) {
        [self.delegate TabBar:self plusBtnDidClick:btn];
    }
}

-(void)layoutSubviews{
    [super layoutSubviews];
    //调整加号按钮的位置
    self.plusBtn.centerX = self.width *0.5;
    self.plusBtn.centerY = self.height *0.5;

    //调整uitabbarbutton的大小和位置
    CGFloat tabBarBtnW = self.width *0.2;
    NSInteger index = 0;
    for (UIView *view in self.subviews) {
        if ([view isKindOfClass:NSClassFromString(@"UITabBarButton")]) {
            view.width = tabBarBtnW;
            view.x = index * tabBarBtnW;

            if (index == 1) {
                index++;
            }
             index++;
        }
    }

}
@end

第二种:自己完全自定义底部tabbar:

#import "SZMMainTabBarController.h"
#import "SZMBottomBarView.h"
@interface SZMMainTabBarController ()<SZMBottomBarViewDelegate>

@end

@implementation SZMMainTabBarController

- (void)viewDidLoad {
    [super viewDidLoad];

    //加载子控制器
    [self loadSubControllers];

    //加载底部自定义view
    [self loadBottomView];

}

//加载底部自定义的view
- (void)loadBottomView{

    //创建底部的自定义的tabbarview
    SZMBottomBarView *BottomView = [[SZMBottomBarView alloc]init];
    BottomView.delegate = self;
    BottomView.backgroundColor = [UIColor redColor];

    BottomView.frame = self.tabBar.bounds;

    [self.tabBar addSubview:BottomView];

    //给自定义view里添加按钮

    for (int i = 0; i < self.viewControllers.count; i++) {                    

        NSString *NormalImgName = [NSString stringWithFormat:@"TabBar%d",i+1];
        NSString *SelectedImgName = [NSString stringWithFormat:@"TabBar%dSel",i+1];

        [BottomView addBarButtonWithNormalImgName:NormalImgName andSelectedImgName:SelectedImgName];

    }

}

- (void)SZMBottomBarView:(SZMBottomBarView *)SZMBottomBarViewWith didSclectedBtnIndex:(int)index{
    self.selectedIndex = index;
}
//加载五个子控制器到tabbar控制器
- (void)loadSubControllers{
    //购彩大厅
    UINavigationController *navHall = [self navigationControllerWithStoryboardName:@"Hall"];

    //竞技场
    UINavigationController *navArena = [self navigationControllerWithStoryboardName:@"Arena"];

    //发现
    UINavigationController *navDiscovery = [self navigationControllerWithStoryboardName:@"Discovery"];

    //开奖信息
    UINavigationController *navHistory = [self navigationControllerWithStoryboardName:@"History"];

    //我的彩票
    UINavigationController *navMyLottery = [self navigationControllerWithStoryboardName:@"MyLottery"];

    self.viewControllers = @[navHall,navArena,navDiscovery,navHistory,navMyLottery];
}

//加载对应的初始化控制器的方法
- (UINavigationController *)navigationControllerWithStoryboardName:(NSString *)storyboard{
    //1.创建stroyboard对象
    UIStoryboard *S1 = [UIStoryboard storyboardWithName:storyboard bundle:nil];

    //2.实例化这个stroyboard中的初始化控制器
    UINavigationController *nav = [S1 instantiateInitialViewController];

    return nav;
}
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end
#import <UIKit/UIKit.h>
@class SZMBottomBarView;
@protocol SZMBottomBarViewDelegate <NSObject>
@optional
- (void)SZMBottomBarView:(SZMBottomBarView *)SZMBottomBarViewWith didSclectedBtnIndex:(int)index;

@end

@interface SZMBottomBarView : UIView

- (void)addBarButtonWithNormalImgName:(NSString *)NormalImgName andSelectedImgName:(NSString *)SelectedImgName;

@property (nonatomic,weak) id<SZMBottomBarViewDelegate> delegate;

@end
#import "SZMBottomBarView.h"
#import "SZMBottomBarBtn.h"

@interface SZMBottomBarView ()

@property (nonatomic,weak) UIButton *selectedBtn;

@end

@implementation SZMBottomBarView
- (void)addBarButtonWithNormalImgName:(NSString *)NormalImgName andSelectedImgName:(NSString *)SelectedImgName
{
    //创建一个uibutton
    SZMBottomBarBtn *btn = [[SZMBottomBarBtn alloc]init];

    //设置uibutton的背影图片
    UIImage *NorImg = [UIImage imageNamed:NormalImgName];
    UIImage *SelImg = [UIImage imageNamed:SelectedImgName];

    [btn setBackgroundImage:NorImg forState:UIControlStateNormal];
    [btn setBackgroundImage:SelImg forState:UIControlStateSelected];

    //把uibutton添加到自己身上
    [self addSubview:btn];

    //给每个底部的按钮添加点击事件
    [btn addTarget:self action:@selector(bottomBarButtonTouchDown:) forControlEvents:UIControlEventTouchDown];

}

//底部按钮点击事件的方法(占击哪个把哪个设置为选中状态)
- (void)bottomBarButtonTouchDown:(UIButton *)sennder
{
    //设置被点击按钮的状态
    self.selectedBtn.selected = NO;
    sennder.selected = YES;
    self.selectedBtn = sennder;

    //切换控制器
    if ([self.delegate respondsToSelector:@selector(SZMBottomBarView:didSclectedBtnIndex:)]) {
        [self.delegate SZMBottomBarView:self didSclectedBtnIndex:(int)sennder.tag];
    }
}
- (void)layoutSubviews
{
    [super layoutSubviews];

    CGFloat y = 0;
    CGFloat w = self.bounds.size.width / self.subviews.count;
    CGFloat h = self.bounds.size.height;
    for (int i = 0; i < self.subviews.count; ++i) {
        CGFloat X = w *i;
        UIButton *button = (UIButton *)self.subviews[i];
        button.tag = i;
        button.frame = CGRectMake(X, y, w, h);
        //设置进入页面后第一个按钮为选中状态
        if (i == 0) {
            self.selectedBtn.selected = NO;
            button.selected = YES;
            self.selectedBtn = button;
        }
    }

}

@end
#import <UIKit/UIKit.h>

@interface SZMBottomBarBtn : UIButton

@end
#import "SZMBottomBarBtn.h"

@implementation SZMBottomBarBtn

- (void)setHighlighted:(BOOL)highlighted{

}
@end
时间: 2024-08-24 10:04:03

自定义底部tabbar的两种方式的相关文章

EntityFramework Core 2.0自定义标量函数两种方式

前言 上一节我们讲完原始查询如何防止SQL注入问题同时并提供了几种方式.本节我们继续来讲讲EF Core 2.0中的新特性自定义标量函数. 自定义标量函数两种方式 在EF Core 2.0中我们可以将方法映射到数据库中的标量函数,我们可在LINQ中调用此方法并会被正确翻译成SQL语句,这为编写数据访问层的开发人员提供了一个很棒的功能来创建一个方法并在其上应用DbFunction特性即可.该属性会将静态CLR方法映射到数据库函数,以便可以在LINQ查询中使用此方法.默认情况下,数据库函数中的CLR

开辟线程的两种方式

/** 自定义执行单元的两种方式 区别 runnable避免了单继承的局限性 runnable资源可以被独立共享 多线程如何找问题1.明确哪些代码是多线程运行代码2.明确哪些是共享数据3.明确多线程代码中哪些语句是操作共享数据的 @author WangShuang /public class Test {public static void main(String[] args) {/MyThread t0=new MyThread();MyThread t1=new MyThread();t

iOS 自定义layer的两种方式

在iOS中,你能看得见摸得着的东西基本都是UIView,比如一个按钮,一个标签,一个文本输入框,这些都是UIView: 其实UIView之所以能显示在屏幕上,完全是因为它内部的一个图层 在创建UIView对象时,UIView内部会自动创建一个图层(即CALayer对象),通过UIView的layer属性可以访问这个图层 @property(nonatomic,readonly,retain) CALayer *layer; 每一个UIView内部都默认关联一个CALayer,我们可称这个Laye

【REACT NATIVE 系列教程之十三】利用LISTVIEW与TEXTINPUT制作聊天/对话框&&获取组件实例常用的两种方式

本站文章均为 李华明Himi 原创,转载务必在明显处注明: 转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/react-native/2346.html 本篇Himi来利用ListView和TextInput这两种组件实现对话.聊天框. 首先需要准备的有几点:(组件的学习就不赘述了,简单且官方有文档) 1. 学习下 ListView: 官方示例:http://reactnative.cn/docs/0.27/tutorial.html#content

JAVA中Arrays.sort()使用两种方式(Comparable和Comparator接口)对对象或者引用进行排序

一.描述 自定义的类要按照一定的方式进行排序,比如一个Person类要按照年龄进行从小到大排序,比如一个Student类要按照成绩进行由高到低排序. 这里我们采用两种方式,一种是使用Comparable接口:让待排序对象所在的类实现Comparable接口,并重写Comparable接口中的compareTo()方法,缺点是只能按照一种规则排序. 另一种方式是使用Comparator接口:编写多个排序方式类实现Comparator接口,并重写新Comparator接口中的compare()方法,

创建TabHost的两种方式的简单分析

最近做了一个TabHost的界面,在做的过程中发现了一些问题,故和大家分享一下. 首先我的界面如下: 目前就我所知,创建TabHost有两种方式,第一种是继承TabActivity类,然后用getTabHost方法来得到一个TabHost的实例,然后就可以给这个TabHost添加Tab了.示例代码如下: [java] view plaincopy public class PlotHost extends TabActivity  { @Override protected void onCre

jQuery开发插件的两种方式

最近挺多人写jQuery的,都是关于jQuery扩展方面的,使用方面的讲的比较多,但是关于详细的一个基础的过程讲的比较少一点,做web开发的基本上都会用到jQuery,本人就根据jQuery的使用经验讲讲插件开发.jQuery插件开发两种方式:一种是类扩展的方式开发插件,jQuery添加新的全局函数(jQuery的全局函数是属于jQuery命名空间的函数),如果将jQuery看成一个类,那么就相当于给jQuery类本身添加方法.第二种是对象扩展的方式开发插件,即jQuery对象添加方法. 类扩展

从源代码剖析Struts2中用户自定义配置转换器的两种方式——基于字段的配置转换器和基于类型的配置转换器(解决了实际系统中,因没有区分这两种工作方式的生命周期而引起的异常错误问题)

自定义类型转换器必须实现ongl.TypeConverter接口或对这个接口的某种具体实现做扩展 <<interface>>com.opensymphony.xwork2.conversion.TypeConverter à com.opensymphony.xwork2.conversion.impl.DefaultTypeConverter à org.apache.struts2.util.StrutsTypeConverter 接口及类进行解析 TypeConverter(

《连载 | 物联网框架ServerSuperIO教程》- 10持续传输大块数据流的两种方式(如:文件)

1.C#跨平台物联网通讯框架ServerSuperIO(SSIO)介绍 <连载 | 物联网框架ServerSuperIO教程>1.4种通讯模式机制. <连载 | 物联网框架ServerSuperIO教程>2.服务实例的配置参数说明 <连载 | 物联网框架ServerSuperIO教程>- 3.设备驱动介绍 <连载 | 物联网框架ServerSuperIO教程>-4.如开发一套设备驱动,同时支持串口和网络通讯. <连载 | 物联网框架ServerSupe