当前位置:网站首页>Uibutton status exploration and customization
Uibutton status exploration and customization
2022-07-06 14:20:00 【Code&Ocean】
original text :UIButton New state solution – Netease cloud music big front end
Control state
As iOS developer , When it comes to controls , I have to mention UIButton, It serves as a iOS The most commonly used control in the system to respond to user click operations , It provides us with quite rich functions and customizability . And our daily work 80% ~ 90% Doing is with UI Dealing with , Handle different states of controls under different operations of users , The simplest , For example, when the user is not logged in , The button is grayed out and cannot be clicked , When the user clicks, a reverse color effect will appear and be fed back to the user, and so on . Definition of common States , The system gave it very early :
typedef NS_OPTIONS(NSUInteger, UIControlState) {
UIControlStateNormal = 0,
UIControlStateHighlighted = 1 << 0, // used when UIControl isHighlighted is set
UIControlStateDisabled = 1 << 1,
UIControlStateSelected = 1 << 2, // flag usable by app (see below)
UIControlStateFocused API_AVAILABLE(ios(9.0)) = 1 << 3, // Applicable only when the screen supports focus
UIControlStateApplication = 0x00FF0000, // additional flags available for application use
UIControlStateReserved = 0xFF000000 // flags reserved for internal framework use
};
NS_OPTIONS Enumeration type
We usually preset UIButton Styles in different states , Then directly change the corresponding state bool value , Easy to use .
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
// The normal state
[button setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
// Click to highlight
[button setTitleColor:[UIColor whiteColor] forState:UIControlStateHighlighted];
[button setBackgroundImage:[UIImage imageNamed:@"btn_highlighted"] forState:UIControlStateHighlighted];
// Unavailable
[button setTitleColor:[UIColor grayColor] forState:UIControlStateDisabled];
// When the user login status changes , Modify attribute values
if (/* The user is not logged in */) {
button.enabled = NO;
} else {
button.enabled = YES;
}
that UIButton Are there only four states available ? In real development , The state of the control may be many , Four kinds must not be enough .
State combination
First of all, we noticed ,UIControlState The definition of is a NS_OPTIONS, instead of NS_ENUM, Three effective bit The pairwise combination should have 8 States . It's just that we can write Demo Test it :
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn setTitle:@"Normal" forState:UIControlStateNormal];
[btn setTitle:@"Selected" forState:UIControlStateSelected];
[btn setTitle:@"Highlighted" forState:UIControlStateHighlighted];
[btn setTitle:@"Highlighted & Disabled" forState:UIControlStateHighlighted | UIControlStateDisabled];
[btn setTitle:@"Disabled" forState:UIControlStateDisabled];
[btn setTitle:@"Selected & Disabled" forState:UIControlStateSelected | UIControlStateDisabled];
[btn setTitle:@"Selected & Highlighted & Disabled" forState:UIControlStateSelected | UIControlStateHighlighted | UIControlStateDisabled];
[btn setTitle:@"Selected & Highlighted" forState:UIControlStateSelected | UIControlStateHighlighted];
Practice has proved ,
UIControlStateHighlightedFollowUIControlStateHighlighted | UIControlStateDisabledUIControlStateSelected | UIControlStateHighlightedFollowUIControlStateSelected | UIControlStateHighlighted | UIControlStateDisabled
The effect is the same , Cover each other .
In fact, it's easy to understand , because UIControlStateDisabled And UIControlStateHighlighted Semantically, they should not coexist , So there are six available state combinations . in addition , It is found in practice that , When a state is not styled , It will be to Normal The style of the state covers the bottom , So in daily development , We'd better set the corresponding style for all the States used .
Custom state
With the above combination , We can basically cover 90% Daily development of , But what if you need to use more States ?
We are developing Yinjie I encountered the problem of insufficient status when I was on my personal homepage , For a follow button , It has the following different states ( Here's the picture ):
- The currently logged in user is not following this user
- The currently logged in user is following this user
- The currently logged in user has paid attention to this user
- The current login user and this user pay attention to each other

In this way, there are three states that users can operate , And each operable state has a corresponding highlight style , So we can't just use selected Status to indicate whether you have paid attention . For this need , An easy way to think of is under different data , Modify the style in the same state :
[button setTitle:@" Focus on " forState:UIControlStateNormal];
[button setTitle:@" Followed " forState:UIControlStateSelected];
// Pay attention to state changes
button.selected = YES;
if (/* The other party also paid attention to me */) {
[button setTitle:@" Pay attention to each other " forState:UIControlStateSelected];
}
The demand is realized , But the use of controls is no longer simple , We can't set all the States during initialization , Then in a data-driven state , State driven style , And add other logic , And this increase is easy to produce Bug.
Is there a better way to define the state , In order to realize the The style is set only once ?
Look back UIControlState The definition of , There is one UIControlStateApplication It seems that it has never been used , Can it be customized ?
We reuse selected Status as our concern followed state , And add loading Attention status , and mutual Pay attention to each other's state .
enum {
NKControlStateFollowed = UIControlStateSelected,
NKControlStateMutual = 1 << 16 | UIControlStateSelected,
NKControlStateLoading = 1 << 17 | UIControlStateDisabled,
};
@interface NKLoadingButton : UIButton
@property (nonatomic, getter=isLoading) BOOL loading;
@property (nonatomic) UIActivityIndicatorView *spinnerView;
@end
@interface NKFollowButton : NKLoadingButton
@property (nonatomic, getter=isMutual) BOOL mutual;
@end
The definition here needs to be explained as follows :
First , Why shift 16 The operation of ?
because UIControlStateApplication The value of is 0x00FF0000, displacement 16 (16 To 23 All are legal values ) Just let the state bit fall within its range .
So customization should start from 16 Start .
secondly ,loading Users should not click to operate , So it's going to or On disabled state ,mutual It must have been followed Of course. ( namely selected), So it's going to or On selected.
Last ,loading State should be reusable elsewhere , Therefore, there is a separate layer in the inheritance relationship NKLoadingButton.NKLoadingButton The implementation of is relatively simple , It should be noted that , We're going to rewrite -setEnabled: Method let it in loading At the same time, it is in a non clickable state .
@implementation NKLoadingButton
- (UIControlState)state
{
UIControlState state = [super state];
if (self.isLoading) {
state |= NKControlStateLoading;
}
return state;
}
- (void)setEnabled:(BOOL)enabled
{
super.enabled = !_loading && enabled;
}
- (void)setLoading:(BOOL)loading
{
if (_loading != loading) {
_loading = loading;
super.enabled = !loading;
if (loading) {
[self.spinnerView startAnimating];
} else {
[self.spinnerView stopAnimating];
}
[self setNeedsLayout];
[self invalidateIntrinsicContentSize];
}
}
@end
NKFollowButton The implementation is as follows :
@implementation NKFollowButton
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self setTitle:@" Focus on " forState:UIControlStateNormal];
[self setTitle:@" Followed " forState:UIControlStateSelected];
[self setTitle:@" Followed " forState:UIControlStateSelected | UIControlStateHighlighted];
[self setTitle:@" Pay attention to each other " forState:NKControlStateMutual];
[self setTitle:@" Pay attention to each other " forState:NKControlStateMutual | UIControlStateHighlighted];
[self setTitle:@"" forState:NKControlStateLoading];
[self setTitle:@"" forState:NKControlStateLoading | UIControlStateSelected];
[self setTitle:@"" forState:NKControlStateMutual | NKControlStateLoading];
// Color related settings are omitted below
}
return self;
}
- (UIControlState)state
{
UIControlState state = [super state];
if (self.isMutual) {
state |= NKControlStateMutual;
}
return state;
}
- (void)setSelected:(BOOL)selected
{
super.selected = selected;
if (!selected) {
self.mutual = NO;
}
}
- (void)setMutual:(BOOL)mutual
{
if (_mutual != mutual) {
_mutual = mutual;
if (mutual) {
self.selected = YES;
}
[self setNeedsLayout];
[self invalidateIntrinsicContentSize];
}
}
@end
We need to rewrite -state Methods let the outside world get complete 、 The right value , rewrite -setSelected: Methods and -setMutual: Method , Let them be mutually exclusive under certain conditions , Unified under certain conditions .
such , We achieved only in -init Set a style in , The subsequent modification is only based on the data returned by the server .selected``.loading.mutual The value of the can !
summary
This article starts from a single state , To the combined state , To customize the status of layers of in-depth introduction UIButton The application of the state of in daily development , Only state drives UI It has always been a good idea in programmer development , This article gives the implementation reference from a basic control . in addition , We are looking at some systems that provide API when , Be sure to think more about what Apple's intention is ? How they want us to use , And how to use it correctly ?
边栏推荐
猜你喜欢
随机推荐
7-3 construction hash table (PTA program design)
Poker game program - man machine confrontation
记一次api接口SQL注入实战
7-4 散列表查找(PTA程序设计)
Chain team implementation (C language)
Windows platform mongodb database installation
记一次,修改密码逻辑漏洞实战
【MySQL-表结构与完整性约束的修改(ALTER)】
Xray and Burp linked Mining
Strengthen basic learning records
The most popular colloquial system explains the base of numbers
. How to upload XMIND files to Jinshan document sharing online editing?
Hackmyvm target series (5) -warez
链队实现(C语言)
实验七 常用类的使用
[data processing of numpy and pytoch]
实验六 继承和多态
Record once, modify password logic vulnerability actual combat
xray與burp聯動 挖掘
Low income from doing we media? 90% of people make mistakes in these three points




![[VMware abnormal problems] problem analysis & Solutions](/img/64/f44864da600b61a1a646a5865a2083.jpg)



