iOS笔记060 - 自定义控件
自定义tabBar
- 系统自带的tabBar不能满足需求
- 自己定义UITabBar
- 自定义一个类继承自UITabBar
- 实现initWithFrame和layoutSubviews方法即可。
//#import "SLQTabBar.h"
@interface SLQTabBar ()
/**发布按钮*/
@property (nonatomic, strong) UIButton *publishBtn;
@end
@implementation SLQTabBar
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
// 添加一个自定义按钮到tabBar
UIButton *addBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[addBtn setBackgroundImage:[UIImage imageNamed:@"tabBar_publish_icon"] forState:UIControlStateNormal];
[addBtn setBackgroundImage:[UIImage imageNamed:@"tabBar_publish_click_icon"] forState:UIControlStateHighlighted];
[self addSubview:addBtn];
self.publishBtn = addBtn;
}
return self;
}
- (void)layoutSubviews
{
[super layoutSubviews];
// 设置发布按钮的frame
self.publishBtn.frame =CGRectMake(0, 0, self.publishBtn.currentBackgroundImage.size.width, self.publishBtn.currentBackgroundImage.size.height);
self.publishBtn.center = CGPointMake(self.frame.size.width * 0.5, self.frame.size.height * 0.5);
// 设置其他item的位置
CGFloat x = 0.0;
CGFloat y = 0;
CGFloat width = self.frame.size.width / 5;
CGFloat height = self.frame.size.height;
NSInteger index = 0;
for (UIView *btn in self.subviews) {
// 判断按钮属性
if(![btn isKindOfClass:NSClassFromString(@"UITabBarButton")] || (btn == self.publishBtn))
// if (![btn isKindOfClass:[UIControl class]] || (btn == self.publishBtn))
{
continue;
}
// 计算x坐标
x = ((index > 1)?(index + 1):index ) * width; // 跳过加号按钮,然后继续设置frame
btn.frame = CGRectMake(x, y, width, height);
// 索引增加
index ++;
}
}
自定义UIView工具类
- 因为要经常获取控件的frame、height等属性进行设置,这里对UIView写一个分类,添加一些自定义的setter和getter方法
- 这样做得依据是
- 分类中声明@property, 只会生成方法的声明, 不会生成方法的实现和带有_下划线的成员变量
- 所以可以直接写几个关于这个常用属性的方法
#import <UIKit/UIKit.h>
@interface UIView (SLQExtension)
/** 在分类中声明@property, 只会生成方法的声明, 不会生成方法的实现和带有_下划线的成员变量*/
/**height*/
@property (nonatomic, assign) CGFloat height;
/**width*/
@property (nonatomic, assign) CGFloat width;
/**size*/
@property (nonatomic, assign) CGSize size;
/**x*/
@property (nonatomic, assign) CGFloat x;
/**y*/
@property (nonatomic, assign) CGFloat y;
@end
//#import "UIView+SLQExtension.h"
@implementation UIView (SLQExtension)
- (void)setWidth:(CGFloat)width
{
CGRect rect = self.frame;
rect.size.width = width;
self.frame = rect;
}
- (CGFloat)width
{
return self.frame.size.width;
}
- (void)setHeight:(CGFloat)height
{
CGRect rect = self.frame;
rect.size.height = height;
self.frame = rect;
}
- (CGFloat)height
{
return self.frame.size.height;
}
- (void)setSize:(CGSize)size
{
CGRect rect = self.frame;
rect.size = size;
self.frame = rect;
}
- (CGSize)size
{
return self.frame.size;
}
- (void)setY:(CGFloat)y
{
CGRect rect = self.frame;
rect.origin.y = y;
self.frame = rect;
}
- (CGFloat)y
{
return self.frame.origin.y;
}
- (void)setX:(CGFloat)x
{
CGRect rect = self.frame;
rect.origin.x = x;
self.frame = rect;
}
- (CGFloat)x
{
return self.frame.origin.x;
}
@end
自定义scrollView
- 按钮添加指示器以及实现滚动view效果
/**
* 设置顶部的标签栏
*/
- (void)setTitlesView
{
// 一个UIView + 5个UIButton
UIView *titleView = [[UIView alloc] init];
titleView.backgroundColor = SLQRGBColor(241, 241, 241);
// 指定尺寸和位置
titleView.frame = CGRectMake(0, 64, self.view.width, 44);
NSArray *title = @[@"全部",@"视频",@"声音",@"图片",@"段子"];
// 添加5个按钮
CGFloat x = 0;
CGFloat width = titleView.width / title.count;
for (NSInteger i = 0 ; i < 5; i ++) {
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
x = i * width;
btn.frame = CGRectMake(x, 0, width, titleView.height);
[btn setTitle:title[i] forState:UIControlStateNormal];
[btn setTitleColor:[UIColor grayColor] forState:UIControlStateNormal];
[btn addTarget:self action:@selector(titleClick:) forControlEvents:UIControlEventTouchUpInside];
[titleView addSubview:btn];
}
// 添加底部指示条indicator
UIView *indicatorView = [[UIView alloc] init];
indicatorView.backgroundColor = [UIColor redColor];
// 位置动态计算,添加到按钮底部
indicatorView.height = 2;
indicatorView.y = titleView.height - indicatorView.height;
[titleView addSubview:indicatorView];
self.indicatorView = indicatorView;
[self.view addSubview:titleView];
}
/**
* 点击按钮首先切换指示器的位置
*/
- (void)titleClick:(UIButton *)btn
{
[UIView animateWithDuration:0.1 animations:^{
// 设置位置
self.indicatorView.width = btn.titleLabel.width;
self.indicatorView.centerX = btn.centerX;
}];
}
自定义的子控制器的返回按钮
- 如果想要保持整个应用中额返回按钮一致,可以这样实现
//#import "SLQNavigationController.h"
@implementation SLQNavigationController
// 自定义导航控制器,在弹出窗口之前设置返回按钮样式。
// 每一个控制器弹出之前都会调用这个方法,所以可以保证所有的控制器的返回按钮样式一致。
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
// 判断是不是第一个控制器,如果不是就设置返回按钮
if (self.childViewControllers.count > 0) {
UIButton *backBtn = [UIButton buttonWithType:UIButtonTypeCustom];
// 设置图片
[backBtn setImage:[UIImage imageNamed:@"navigationButtonReturn"] forState:UIControlStateNormal];
[backBtn setImage:[UIImage imageNamed:@"navigationButtonReturnClick"] forState:UIControlStateHighlighted];
[backBtn setTitle:@"返回" forState:UIControlStateNormal];
// 让按钮内部的所有内容左对齐
backBtn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
backBtn.size = CGSizeMake(70, 30);
// 文字颜色
[backBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[backBtn setTitleColor:[UIColor redColor] forState:UIControlStateHighlighted];
// 设置内边距,使得按钮紧靠边
[backBtn setContentEdgeInsets:UIEdgeInsetsMake(0, -15, 0, 0)];
[backBtn addTarget:self action:@selector(back) forControlEvents:UIControlEventTouchUpInside];
viewController.navigationItem.leftBarButtonItems = @[
[[UIBarButtonItem alloc] initWithCustomView:backBtn]
];
// 隐藏tabBar
viewController.hidesBottomBarWhenPushed = YES;
}
// 设置过控制器后再弹出
// 这句super的push要放在后面, 让viewController可以覆盖上面设置的leftBarButtonItem
[super pushViewController:viewController animated:animated];
}
- (void)back
{
[self popViewControllerAnimated:YES];
}
@end
自定义按钮
- 按钮默认显示是图片在左,文字在右
- 如果想实现其他排列,如文字在下,图片在上,可以重写layoutSubviews方法
//#import "SLQVerticalButton.h"
@implementation SLQVerticalButton
- (void)setup
{
self.titleLabel.textAlignment = NSTextAlignmentCenter;
}
/**
* 通过xib创建按钮
*/
- (void)awakeFromNib
{
[self setup];
}
/**
* 通过代码创建按钮
*/
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
[self setup];
}
return self;
}
/**
* 重新布局子控件
*/
- (void)layoutSubviews
{
[super layoutSubviews];
// 调整imageView位置
self.imageView.x = 0;
self.imageView.y = 0;
self.imageView.width = self.width;
self.imageView.height = self.imageView.width;
// 调整lable位置
self.titleLabel.x = 0;
self.titleLabel.y = self.imageView.height;
self.titleLabel.width = self.width;
self.titleLabel.height = self.height - self.imageView.height;
}
@end
iOS笔记060 - 自定义控件的更多相关文章
- 荼菜的iOS笔记--UIView的几个Block动画
前言:我的第一篇文章荼菜的iOS笔记–Core Animation 核心动画算是比较详细讲了核心动画的用法,但是如你上篇看到的,有时我们只是想实现一些很小的动画,这时再用coreAnimation就会 ...
- 【转】iOS笔记-自定义控件(OC)
原文网址:http://www.jianshu.com/p/f23862eb7b8a 导读: iOS开发中,很多时候系统提供的控件并不能很好的满足我们的需求,因此,自定义控件便成为搭建UI界面中必不可 ...
- 【IOS笔记】View Programming Guide for iOS -1
原文:View Programming Guide for iOS View and Window Architecture Views and windows present your applic ...
- IOS笔记 1
< ![CDATA[ 笔记 UIWindows 与UIView的关系iOS的坐标系统视图层次结构视图坐标(Frame和Bounds区别)UIView的常用属性和方法坐标系统的变换UIView内容 ...
- Android笔记——Android自定义控件
目录: 1.自定义控件概述 01_什么是自定义控件 Android系统中,继承Android系统自带的View或者ViewGroup控件或者系统自带的控件,并在这基础上增加或者重新组合成我们想要的效果 ...
- iOS笔记———数据存储
应用沙盒:应用文件系统的根目录,每个应用都有独自的沙盒相互:在xcode中可以用NSHomeDirectory()函数,打印当前应用的沙盒根路径. 应用程序包:包含了所有资源文件和执行文件; * Do ...
- iOS开发:自定义控件实现手势解锁
自定义控件 1.提供initWithFrame:及initWithCoder:方法来初始化: 2.解锁控件只负责展示.触摸.绘图等,存储轨迹.判断轨迹等操作不是解锁控件要做的.因此要定义一个代理,将轨 ...
- Xamarin开发IOS笔记:切换输入法时输入框被遮住
在进行IOS开发的过程中,出现类似微信朋友圈的交互界面,当用户遇到感兴趣的内容可以进行评论.为了方便评论输入,当出现评论输入框的时候自动将评论输入框移动至键盘的上方,这样方便边输入边查看. 当用户隐藏 ...
- IOS中在自定义控件(非视图控制器)的视图跳转中 代理方法与代码块的比较
//代码块与代替代理的设计方法 我就以在自定义视图中(非视图控制器,不能实现视图控制功能),通过代理和代码块两种方法分别实现视图的跳转,进行对比 首先自定义了一个视图,上面有一个已经注册了得BUtto ...
随机推荐
- mac 下使用 ikbcG87 及使用 karabiner 改大小写键
前言 一直使用 mac ,对于机械键盘还处于刚入坑阶段,作为小白还是选择能够兼容 mac 的机械键盘,于是选择了 ikbcG87 "双子座" 1.使用 ikbc G87 mac 模 ...
- [转载]Memcached缓存服务的简单安装
1.Linux下的安装方法 下载:wget http://memcached.org/latest tar -zxvf memcached-1.x.x.tar.gz cd memcached-1.x. ...
- 2018.7.30 Oracle的Blog数据库类型读取和存
package com.lanqiao.shopping.test; import java.io.BufferedInputStream; import java.io.BufferedOutput ...
- Win10预览版激活信息
微软在10月2日零点正式公开了Win10预览版的下载地址,这个时间大家应该逐步开始安装工作了,因此提出下面两个问题的用户特别多,IT之家再稍作告知一下.1.Win10预览版安装密钥是什么?答:NKJF ...
- js动画效果
js能够按照预定的时间间隔重复调用一个函数,而这意味着我们可以随着时间的推移而不断改变某个元素的样式.动画是样式随时间变化的完美例子之一. js函数setTimeout能够让某个函数在经过一段预定的时 ...
- 2.Netty的粘包、拆包(一)
Netty粘包.拆包 1.什么是拆包.粘包 (1)拆包.粘包介绍 TCP是个"流"协议,所谓流,就是没有界限的一串数据.大家可以想想河里的流水,是连成一片的,其间并没有分界线.TC ...
- 使用nsis开发自定义安装包使用心得,以及遇到坑
因为新公司需要开发pc应用的自定义安装包,开始时候计划使用nsis开发,论坛上面有很多不错的例子,而且完成度很强, 随便拿来修改使用,但是后续的开发过程中遇到的问题就逐个出现. 首先说一下nsis的优 ...
- Webpack4 学习笔记二 CSS模块转换
前言 此内容是个人学习笔记,以便日后翻阅.非教程,如有错误还请指出 webpack 打包css模块 webpack是js模块打包器, 如果在入口文件引入css文件或其它的less.sass等文件,需要 ...
- 时间戳与QDateTime相互转换
最近项目中需要将日期时间输出到Excel中,程序使用Qt开发,使用第三方库QtXlsx进行Excel读写操作.Excel中第一列为时间,时间间隔为1小时,如图所示. 赋值起始时间stDTime,则后续 ...
- finddler的安装与设置
这是抓取手机包的设置 过滤 新安装的,可能还需要证书问题