当前位置:网站首页>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 ?
边栏推荐
- Canvas foundation 2 - arc - draw arc
- 小程序web抓包-fiddler
- Experiment 9 input and output stream (excerpt)
- The most popular colloquial system explains the base of numbers
- 7-5 staircase upgrade (PTA program design)
- 强化学习基础记录
- MSF generate payload Encyclopedia
- 网络基础之路由详解
- Chain team implementation (C language)
- xray與burp聯動 挖掘
猜你喜欢

Package bedding of components

Internet Management (Information Collection)

Only 40% of the articles are original? Here comes the modification method

JDBC看这篇就够了

WEB漏洞-文件操作之文件包含漏洞

Hackmyvm target series (4) -vulny
![[paper reproduction] cyclegan (based on pytorch framework) {unfinished}](/img/16/43d8929d1a37c1c68e959d5854e18c.jpg)
[paper reproduction] cyclegan (based on pytorch framework) {unfinished}

Record once, modify password logic vulnerability actual combat

Hackmyvm target series (2) -warrior

网络基础之路由详解
随机推荐
Build domain environment (win)
Applet Web Capture -fiddler
7-4 散列表查找(PTA程序设计)
[err] 1055 - expression 1 of order by clause is not in group by clause MySQL
Experiment 7 use of common classes
How to turn wechat applet into uniapp
The difference between layer 3 switch and router
内网渗透之内网信息收集(一)
Detailed explanation of three ways of HTTP caching
Meituan dynamic thread pool practice ideas, open source
Experiment 9 input and output stream (excerpt)
7-5 走楼梯升级版(PTA程序设计)
7-14 error ticket (PTA program design)
Callback function ----------- callback
安全面试之XSS(跨站脚本攻击)
【MySQL数据库的学习】
JDBC事务、批处理以及连接池(超详细)
Spot gold prices rose amid volatility, and the rise in U.S. prices is likely to become the key to the future
记一次,修改密码逻辑漏洞实战
JS several ways to judge whether an object is an array