当前位置:网站首页>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 ,
UIControlStateHighlighted
FollowUIControlStateHighlighted | UIControlStateDisabled
UIControlStateSelected | UIControlStateHighlighted
FollowUIControlStateSelected | 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 ?
边栏推荐
- Intensive literature reading series (I): Courier routing and assignment for food delivery service using reinforcement learning
- Load balancing ribbon of microservices
- 强化学习基础记录
- Experiment 6 inheritance and polymorphism
- 7-14 error ticket (PTA program design)
- How to turn wechat applet into uniapp
- 攻防世界MISC练习区(gif 掀桌子 ext3 )
- A complete collection of papers on text recognition
- Hcip -- MPLS experiment
- Strengthen basic learning records
猜你喜欢
内网渗透之内网信息收集(四)
How to turn wechat applet into uniapp
Hackmyvm target series (6) -videoclub
xray與burp聯動 挖掘
Intranet information collection of Intranet penetration (I)
HackMyvm靶机系列(6)-videoclub
Attach the simplified sample database to the SQLSERVER database instance
xray与burp联动 挖掘
实验六 继承和多态
HackMyvm靶机系列(3)-visions
随机推荐
Simply understand the promise of ES6
7-4 hash table search (PTA program design)
7-11 mechanic mustadio (PTA program design)
Callback function ----------- callback
网络基础详解
力扣152题乘数最大子数组
Ucos-iii learning records (11) - task management
Nuxtjs quick start (nuxt2)
7-4 散列表查找(PTA程序设计)
Tencent map circle
图书管理系统
7-3 构造散列表(PTA程序设计)
xray與burp聯動 挖掘
HackMyvm靶机系列(2)-warrior
7-5 走楼梯升级版(PTA程序设计)
Attack and defense world misc practice area (simplerar, base64stego, no matter how high your Kung Fu is, you are afraid of kitchen knives)
How to turn wechat applet into uniapp
[experiment index of educator database]
强化学习基础记录
Attack and defense world misc practice area (GIF lift table ext3)