UI学习笔记(一)
UI学习
- 一:UIView基础
- frame属性
- 隐藏视图对象:
- UIView的层级关系
- 二:UIWindow对象
- 三:UIViewController基础
- UIViewController使用
- 四:定时器与视图移动
- 五:UISwitch控件
- 六:滑动条和进度条
- 七:步进器和分栏控件
- 八:警告对话框和等待提示器
- 九:UITextField
- 滚动视图
- 滚动视图基础
- 滚动视图高级
- 总结
一:UIView基础
我们先来介绍一下frame属性
frame属性
frame框架可以理解为视图在父视图中的位置和大小的描述。具体来说,frame框架包括视图的原点坐标和宽高两个属性。
- 原点坐标(origin):原点坐标表示视图在父视图坐标系统中的位置,通常是相对于父视图左上角的距离。原点坐标是一个CGPoint对象,包括x和y两个属性。
- 宽高(size):宽高表示视图在父视图中的大小,通常是视图的宽度和高度。宽高是一个CGSize对象,包括width和height两个属性
而CGRectMake是一个用来创建CGRect结构体的函数,该函数传入四个参数,分别为原点坐标的x和y,宽高的width和height。
简而言之,我们对frame属性初始化,传入前两个参数确定开始位置,传入后两个参数作为视图的大小。这也是其他控件的基本属性。
UIview是iOS的视图对象,是显示在屏幕上的所有对象的基础类,
也就是说,所有显示在屏幕上的对象一定都继承与UIView,屏幕上所有能看到的对象都是UIView的子类
- UIView是一个矩形对象,有背景颜色,可以显示,有层级关系
- frame属性是UIView的基本属性,而UiView是其他对象的父类,因此所有对象都有该属性。
下面使用代码来展示UIView的基础内容:
- (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view.//初始化一个UIview对象UIView *view = [[UIView alloc] init];//设置UIview的位置view.frame = CGRectMake(100, 100, 100, 200);view.backgroundColor = [UIColor orangeColor];//将新建的视图添加到父亲视图上//1:将新建的视图显示到屏幕上//2:将视图作为父亲视图的子视图管理起来[self.view addSubview:view];//将自己从父亲视图删除掉//1.从父亲视图的管理中删除//2.不会显示在屏幕。//[view removeFromSuperview] ;
}
效果:
隐藏视图对象:
分别有三种方法:
- 设置hidde属性:是否隐藏
- 设置alpha属性:设置透明度
- 设置opaque属性:是否显示不透明
//是否隐藏视图对象//YES:不显示//NO:显示,默认值为NOview.hidden = YES;//设置视图的透明度//alpha= 1:不透明//a = 0 :透明//a = 0.5: 半透明view.alpha = 1;//设置是否显示不透明view.opaque = YES;
UIView的层级关系
UIview是在父视图中可以用self.view.subviews[]的数组下标来查看,而这个数组是有顺序的,即层级关系。
- 先加入的视图,在数组的开始,即在屏幕的最底层。
- 重复加入,不会开辟新的数组位置,而是移动数组的排序方式。
- 可以使用bringSubviewToFront、sendSubviewToBack等方法来改变视图的顺序。
- removeFromSuperview方法可以删除子视图。
- (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view.UIView *view1 = [[UIView alloc] init];view1.frame = CGRectMake(100, 100, 150, 150);view1.backgroundColor = [UIColor orangeColor];UIView *view2 = [[UIView alloc] init];view2.frame = CGRectMake(125, 125, 150, 150);view2.backgroundColor = [UIColor blueColor];UIView *view3 =[[UIView alloc] init];view3.frame = CGRectMake(150, 150, 150, 150);view3.backgroundColor = [UIColor blackColor];//将三个视图对象显示到屏幕上并且添加到父亲视图上。//重复加入已有元素,不会扩大数组,而是移动数组[self.view addSubview:view1];[self.view addSubview:view2];[self.view addSubview:view3];[self.view addSubview:view1];//[self.view addSubview:view2];//将某一个视图调整到最前面显示//参数:UIView对象,调整到一个视图到最前方//实际上也移动了数组的位置。// [self.view bringSubviewToFront:view1];//将某一个视图调整到最后显示//参数:UIView对象,调整哪一个视图到最后//实际上也移动了数组的位置// [self.view sendSubviewToBack:view3];UIView *viewFront = self.view.subviews[0];// [view1 removeFromSuperview];UIView *viewBack = self.view.subviews[2];if (viewFront == view2) {NSLog(@"等于");}if (viewBack == view1) {NSLog(@"等于");}
}
效果:
同时,我们可以验证重复添加视图,是移动数组位置而不是创建新的数组。
二:UIWindow对象
注意:在XCode13之后我们使用代码来创建初始化一个UIWindow对象不在AppDelegate类中进行,而是在SceneDelegate类进行,并且不需要创建UIWindow对象,只需要为其初始化视图管理器后即可进行使用。
UIWindow对象是UIView最顶层的容器,包含应用并显示所有的UIView对象。同时,也可以反映传递事件给UIView。
下面是UIWindow的一些基本使用。
SceneDelegate.m文件
#import "SceneDelegate.h"@interface SceneDelegate ()@end@implementation SceneDelegate- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {//对UIWindow对象创建视图控制器self.window.rootViewController = [[UIViewController alloc] init] ;//设置背景颜色self.window.backgroundColor = [UIColor blackColor];//直接给window上添加视图UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 50, 200)];view1.backgroundColor = [UIColor blueColor];UIView *view2 = [[UIView alloc] initWithFrame:CGRectMake(150, 0, 50, 200)];view2.backgroundColor = [UIColor redColor];//当创建一个新的背景视图,然后将这个视图作为window的子视图,再让view1作为背景视图的子视图,就会有一个层级关系//当移动背景视图的时候,view1视图也会随着移动,子视图是参照父视图的坐标系UIView *backview = [[UIView alloc] initWithFrame:CGRectMake(100, 400, 200, 200)];backview.backgroundColor = [UIColor whiteColor];//将子视图添加到爸爸视图上[backview addSubview:view1];[backview addSubview:view2];[self.window addSubview:backview];NSLog(@"%@", view1.window);NSLog(@"%@", backview.window);NSLog(@"%@", self.window);//使window有效并显示到屏幕上[self.window makeKeyAndVisible];}
效果:
同时,通过对三个window对象的打印,我们可以印证整个程序仅有一个UIWindow对象。
三:UIViewController基础
UIViewController是视图控制器的意思。整个UIKit框架中只能有一个根视图控制器,属于window属性,但是可以有多个视图控制器,视图控制器用来管理界面和处理界面的逻辑类对象,程序启动前必须对根视图控制器赋值。
我们在SceneDelegate.m文件中实现对根视图控制器的初始化。
#import "SceneDelegate.h"
#import "ViewController.h"
@interface SceneDelegate ()@end@implementation SceneDelegate- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {ViewController *vcRoot = [[ViewController alloc] init];self.window.rootViewController = vcRoot;self.window.backgroundColor = [UIColor redColor];}
UIViewController使用
通过对UIViewController的学习,我们可以实现视图控制界面的切换。下面我们实操来加深学习。
首先,我们需要创建视图控制器,并为其初始化不同的颜色。
之后我们可以调用presentViewController方法,实现显示一个新的视图控制器界面到屏幕上。再在新的view文件中使用dismissViewControllerAnimated方法(关闭当前视图控制器界面),回到原来的视图控制器界面。
具体实现代码:
ViewController.m文件
#import "ViewController.h"
#import "ViewC02.h"
@interface ViewController ()@end@implementation ViewController-(void) touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{//创建视图控制器二ViewC02* vc = [[ViewC02 alloc] init];//整个屏幕vc.modalPresentationStyle = UIModalPresentationFullScreen;//显示一个新的视图控制器到屏幕上//P1:新的视图控制器对象//P2:使用动画切换动画效果//P3:切换结束后功能调用,不需要则穿nil[self presentViewController:vc animated:YES completion:nil];
}
//第一次程序加载视图时调用
//只调用一次
- (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view.self.view.backgroundColor = [UIColor blueColor];NSLog(@"viewDidLoad 第一次加载!");
}//当视图控制器的视图即将显示时,调用次函数
//视图分为:1.显示前 2.正在处于显示状态 3.已经被隐藏
//参数:是否用动画切换后显示
- (void) viewWillAppear:(BOOL)animated
{NSLog(@"viewWillAppear,视图即将显示!");
}
//视图即将消失,调用次函数
//参数:表示是否用动画切换后消失
//当前的状态:视图还显示在屏幕上
-(void) viewWillDisAppear:(BOOL)animated
{NSLog(@"视图即将消失!");
}//当视图已经显示到屏幕后到瞬间调用次函数
//参数:表示是否用动画切换显示的
//当前状态:已经显示到屏幕上
-(void) viewDidAppear:(BOOL)animated
{NSLog(@"视图已经显示");
}//当前视图已经从屏幕上消失
//参数:表示是否用动画切换显示的
//当前状态:当前视图控制器视图已经消失
-(void) viewDidDisappear:(BOOL)animated
{NSLog(@"视图已经消失!");
}
@end
ViewC02.m文件:
#import "ViewC02.h"@interface ViewC02 ()@end@implementation ViewC02- (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view.self.view.backgroundColor = [UIColor orangeColor];
}-(void) touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{ //点击屏幕后使当前视图控制器界面消失。[self dismissViewControllerAnimated:YES completion:nil];
}
效果:点击前:
点击后:
上图代码中,我们还加入了一些操作函数,来显示屏幕的调用。
注意:添加下述代码后,才会使整个屏幕切换,从而显示viewDidDisappear操作函数。
vc.modalPresentationStyle = UIModalPresentationFullScreen;
代码运行结果:
四:定时器与视图移动
创建一个定时器,先要在接口文件中创建NSTimer属性。
@property (retain, nonatomic) NSTimer *timerVier;
之后,采用scheduledTimerWithTimeInterval:的类方法来创建定时器。并启动该定时器。
该方法有五个参数:
P1:每隔多长时间调用定时器函数,以秒为单位
P2:表示实现定时器函数的对象(指针)
P3:定时器函数对象
P4:可以传入定时器函数中一个参数,无参数可以传nil
P5:定时器是否重复操作,YES为重复,NO只完成一次函数调用
而我们要实现使指定view对象移动,需要先为view对象设置一个标签值,在定时器的事件函数中进行使用。
下列代码中的view.frame =CGRectMake(view.frame.origin.x+1, view.frame.origin.y+1, 80, 80);即实现这一功能,使view视图的x,y轴随时间移动。
ViewController.m文件
#import "ViewController.h"@interface ViewController ()@end@implementation ViewController@synthesize timerVier = _timerVier;- (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view.UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];btn.frame = CGRectMake(100, 100, 80, 40);[btn setTitle:@"启动定时器" forState:UIControlStateNormal];[btn addTarget:self action:@selector((pressStart)) forControlEvents:UIControlEventTouchUpInside];[self.view addSubview:btn];UIButton *btnStop = [UIButton buttonWithType:UIButtonTypeRoundedRect];btnStop.frame = CGRectMake(100, 200, 80, 40);[btnStop setTitle:@"停止定时器" forState:UIControlStateNormal];[btnStop addTarget:self action:@selector(pressStop) forControlEvents:UIControlEventTouchUpInside];[self.view addSubview:btnStop];UIView *view = [[UIView alloc] init];view.frame = CGRectMake(0, 0, 80, 80);view.backgroundColor = [UIColor blueColor];[self.view addSubview:view];//设置view对标签值//通过爸爸视图对象以及view的标签值可以获得相应的对象view.tag = 101 ;
}//按下开始按钮函数
- (void) pressStart
{//NSTimer的类方法创建一个定时器并启动这个定时器//P1:每隔多长时间调用定时器函数,以秒为单位//P2:表示实现定时器函数的对象(指针)//P3:定时器函数对象//P4:可以传入定时器函数中一个参数,无参数可以传nil//P5:定时器是否重复操作,YES为重复,NO只完成一次函数调用//返回值为一个新建好的定时器对象_timerVier = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(updateTimer:) userInfo:@"lyf" repeats:YES];
}//定时器函数
//可以将定时器本身作为参数传入
-(void) updateTimer:(NSTimer*) timer
{ //userInfo为id类型NSLog(@"test!! name = %@", timer.userInfo);//tag最好从100开始UIView *view = [self.view viewWithTag:101];view.frame =CGRectMake(view.frame.origin.x+1, view.frame.origin.y+1, 80, 80);
}
//按下停止按钮时调用
-(void) pressStop
{if (_timerVier != nil) {//停止定时器[_timerVier invalidate];}
}
@end
效果:
还有一点需要注意:如果对上述代码连续点击两次启动定时器,此时再按停止定时器将无法停止视图移动。
原因:每次点击都创造出一个定时器对象,从而使第一次点击的定时器对象无法覆盖。即无法再停止第一个定时器对象,只能停止新建立的定时器对象。
解决办法:将该属性变成单例模式,或者每次进入pressStart时,调用一遍结束方法。即:
- (void) pressStart
{[self pressStop];//每次调用前先关闭前一个定时器。_timerVier = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(updateTimer:) userInfo:@"lyf" repeats:YES];
}
五:UISwitch控件
UISwitch控件是苹果官方库提供的一个控件,与定时器相同,需要先在接口部分声明一个属性,在实现部分实现其具体功能。
但是,作为苹果官方的控件,苹果对其作出了一定的限制:如无法改变宽度高度值和设计样式。
下例代码详细展示了该控件的使用:
#import "ViewController.h"@interface ViewController ()@end@implementation ViewController@synthesize mySwitch = _mySwitch;- (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view.//创建一个开关对象_mySwitch = [[UISwitch alloc] init];//苹果官方的控件的位置设置//位置X,Y的值可以改变//宽度高度值是无法改变。系统默认设置了_mySwitch.frame = CGRectMake(100, 100, 0, 0);//开关状态设置属性//YES:开启状态//NO:关闭状态//_mySwitch.on = YES;//[_mySwitch setOn:YES];//设置开关状态//P1:状态设置//P2:是否开启动画效果[_mySwitch setOn:YES animated:YES];[self.view addSubview:_mySwitch];//设置开启状态的风格颜色[_mySwitch setOnTintColor:[UIColor orangeColor]];//设置开关圆按钮的风格颜色[_mySwitch setThumbTintColor:[UIColor blueColor]];//设置整体风格颜色 没作用原因已截图[_mySwitch setTintColor:[UIColor redColor]];//向开关控件添加事件函数//P1:函数实现对象//P2:函数对象//P3:事件响应时的事件类型UIControlEventValueChanged:状态发生变化[_mySwitch addTarget:self action:@selector(swChange:) forControlEvents:UIControlEventValueChanged];
}
- (void) swChange:(UISwitch*) sw
{if (sw.on == YES) {NSLog(@"哈哈,打开咯");}else {NSLog(@"哈哈,关闭咯");}NSLog(@"我变质了");
}@end
代码结果:
六:滑动条和进度条
滑动条与进度条也需要在接口部分定义属性,在实现部分实现功能。
除了对这两个的基本使用,我们还可以实现用滑动条来控制进度条的长短,当滑动条与进度条不是相同长度时,我们可以使用下面的代码来实现等比例控制。
pView.progress = (_slider.value - _slider.minimumValue) / (_slider.maximumValue - _slider.minimumValue);
ViewController.h
#import <UIKit/UIKit.h>@interface ViewController : UIViewController
{//进度条对象//一般用来表示下载或者视频播放的进度UIProgressView * pView;//滑动条定义//一般用来进行调整音频音乐的音量等UISlider *_slider;
}
//定义一个进度条属性
@property (retain, nonatomic) UIProgressView *pView;
//定义一个滑动条属性
@property (retain, nonatomic) UISlider *slider;
@end
ViewController.m
#import "ViewController.h"@interface ViewController ()@end@implementation ViewController@synthesize slider = _slider;
@synthesize pView = _pView;- (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view.//进度条的创建pView = [[UIProgressView alloc] init];//进度条的位置大小设置//进度条的高度是不可以变化的.P4不可变pView.frame = CGRectMake(50, 100, 300, 40);pView.progressTintColor = [UIColor greenColor];pView.trackTintColor = [UIColor blackColor];//设置进度条的进度值//范围从0-1//最小值为0,最大值为1pView.progress = 0;//设置进度条的风格特征pView.progressViewStyle = UIProgressViewStyleBar;[self.view addSubview: pView];//创建滑动条对象_slider = [[UISlider alloc] init];//位置设置,高度不可变更_slider.frame = CGRectMake(10, 200, 300, 40);//设置滑动条的最大值_slider.maximumValue = 100;//设置滑动条的最小值,可以为负_slider.minimumValue = -100;//设置滑动条的滑块位置_slider.value = 0;//左侧滑条背景颜色// _slider.minimumTrackTintColor = [UIColor blueColor];//右侧滑动条背景颜色_slider.maximumTrackTintColor = [UIColor greenColor];//设置滑块颜色_slider.thumbTintColor = [UIColor orangeColor];[_slider addTarget:self action:@selector(pressSlider) forControlEvents:UIControlEventValueChanged];[self.view addSubview:_slider];
}-(void) pressSlider
{pView.progress = (_slider.value - _slider.minimumValue) / (_slider.maximumValue - _slider.minimumValue);NSLog(@"value = %f", _slider.value);
}@end
效果:
七:步进器和分栏控件
先要在接口文件中定义步进器对象和分栏控制器对象。
ViewController.h
#import <UIKit/UIKit.h>@interface ViewController : UIViewController
{//定义步进器对象//按照一定的数字来调整某个数据UIStepper *_stepper;//分栏控制器定义UISegmentedControl *_segControl;
}@property (retain, nonatomic) UIStepper *stepper;
@property (retain, nonatomic) UISegmentedControl *segControl;@end
在.m文件中,我们不仅可以以文本来初始化分拦控件,还可以以照片来初始化分拦控件。
ViewController.m
#import "ViewController.h"@interface ViewController ()@end@implementation ViewController@synthesize stepper = _stepper;
@synthesize segControl = _segControl;- (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view._stepper = [[UIStepper alloc] init];//只能设置位置,宽高不能改变_stepper.frame = CGRectMake(100, 100, 80, 40);//设置步进器的最小值_stepper.minimumValue = 0;//设置步进器的最大值_stepper.maximumValue = 100;//设置步进器的当前值,默认值为0_stepper.value = 10;//设置步进器每次向前或者向后步进的步伐值_stepper.stepValue = 5;//是否可以重复响应事件操作_stepper.autorepeat = YES;//是否将步进结果通过事件函数响应出来//不显示中间过程,长按直接显示结果。_stepper.continuous = NO;//添加事件函数[_stepper addTarget:self action:@selector(stepChange) forControlEvents:UIControlEventValueChanged];[self.view addSubview:_stepper];_segControl = [[UISegmentedControl alloc] init];//宽度可变,高度不可变_segControl.frame = CGRectMake(10, 200, 300, 40);//添加一个按钮元素[_segControl insertSegmentWithTitle:@"0元" atIndex:0 animated:NO];//参数一:按钮选项文字//参数二:按钮索引位置//参数三:是否有插入的动画效果[_segControl insertSegmentWithTitle:@"5元" atIndex:1 animated:NO];[_segControl insertSegmentWithTitle:@"10元" atIndex:2 animated:NO];// [_segControl insertSegmentWithTitle:@"30元" atIndex:0 animated:NO];//以照片作为分拦控件的图像。//注意要将照片放入当前视图内。UIImage *image = [UIImage imageNamed:@"WechatIMG26890.jpg"];image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];[_segControl setImage:image forSegmentAtIndex:2];//当前默认按钮索引设置_segControl.selectedSegmentIndex = 0;[_segControl addTarget:self action:@selector(segChange) forControlEvents:UIControlEventValueChanged];[self.view addSubview:_segControl];
}-(void) segChange
{NSLog(@"%d", _segControl.selectedSegmentIndex);
}-(void) stepChange
{NSLog(@"step press! value = %f", _stepper.value);
}@end
效果
代码结果:
八:警告对话框和等待提示器
在遇到电量不足等特殊情况时,可以弹出警告对话框提示用户。
在下载或加载比较大的文件时,可以显示等待提示器提示用户。
我们在ViewController 的接口文件中定义这两个对象。
@interface ViewController : UIViewController
{//定义一个警告对话框视图对象UIAlertController *_alertView;//等待提示对象//当下载,或加载比较大的文件时,可以显示此控件,处于提示等待状态UIActivityIndicatorView *_activityIndicator;
}@property (retain, nonatomic) UIAlertController *alertVier;
@property (retain, nonatomic) UIActivityIndicatorView *act;@end
在实现部分,我们先建立两个按钮,用来弹出提示器。
随后开始实现这两个提示器。
- 警告对话框
[UIAlertController alertControllerWithTitle:@"警告" message:@"你的手机已经被劫持!!!" preferredStyle:UIAlertControllerStyleAlert];
使用如上代码,设置样式为弹出警告式的对话框。参一为标题,参二为警告内容。
UIAlertAction* action01 = [UIAlertAction actionWithTitle:@"打钱" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action){/* 在这里编写执行该选项的代码*/}];
随后创建三个不同的action对象,如上所示参一为提示,参二为样式,参三为需要执行的代码块
样式为以下四种:
- UIAlertActionStyleDefault:默认样式,用于表示用户可以选择的主要操作。
- UIAlertActionStyleCancel:取消样式,通常用于取消操作,只能有一个取消按钮。
- UIAlertActionStyleDestructive:破坏性样式,用于表示执行此操作可能有破坏性后果。
- UIAlertActionStyleTextInput:输入样式,允许用户在弹出的警告框中输入文本。
最后将操作对象加入到警告框中,再使该警告框显示。
- 等待提示器
等待提示器的高度和宽度由苹果官方设定,不可改变。可以设置四种不同风格的等待指示器。
- UIActivityIndicatorViewStyleWhiteLarge:表示一个白色的大号等待提示器。
- UIActivityIndicatorViewStyleWhite:表示一个白色的普通大小等待提示器。
- UIActivityIndicatorViewStyleGray:表示一个灰色的普通大小等待提示器。
- UIActivityIndicatorViewStyleMedium:表示一个中等大小的等待提示器,通常是灰色的。
#import "ViewController.h"@interface ViewController ()@end@implementation ViewController@synthesize alertVier = _alertVier;
@synthesize act = _act;- (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view.for (int i = 0; i < 2; i++){UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];btn.frame = CGRectMake(100, 100 + 100 * i, 100, 40);if (i == 0){[btn setTitle:@"警告对话框" forState:UIControlStateNormal];} else if (i == 1) {[btn setTitle:@"等待指示器" forState:UIControlStateNormal];}btn.tag = 101 + i;[btn addTarget:self action:@selector(pressBtn:) forControlEvents:UIControlEventTouchUpInside];[self.view addSubview:btn];}}- (void)pressBtn:(UIButton*) btn {//警告对话框创建if (btn.tag == 101) {_alertView = [UIAlertController alertControllerWithTitle:@"警告" message:@"你的手机已经被劫持!!!" preferredStyle:UIAlertControllerStyleAlert];UIAlertAction* action01 = [UIAlertAction actionWithTitle:@"打钱" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action){/* 在这里编写执行该选项的代码*/}];UIAlertAction* action02 = [UIAlertAction actionWithTitle:@"打钱" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action){/* 在这里编写执行该选项的代码*/}];UIAlertAction* action03 = [UIAlertAction actionWithTitle:@"投降" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action){/* 在这里编写执行该选项的代码*/}];[_alertView addAction:action01];[_alertView addAction:action02];[_alertView addAction:action03];[self presentViewController:_alertView animated:YES completion:nil];} else if (btn.tag == 102){//宽度和高度不可改变_activityIndicator = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(100, 300, 80, 80)];//设定提示的风格_activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyleMedium;_activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyleLarge;[self.view addSubview:_activityIndicator];//启动动画并显示[_activityIndicator startAnimating];//停止动画并隐藏//[_activityIndicator stopAnimating];}
}@end
效果:
(点击警告对话框)
(点击等待指示器):
九:UITextField
先要在ViewController的接口部分中定义一个UITextField属性,在接口部分实现。
作为一个文本控件,该控件只能输入一行文本,不能输入或显示多行,常用来做登录界面。
我们可以设置文本的大小,位置,边框风格和键盘风格,字体的大小和颜色。此处主要介绍边框风格和键盘风格
边框风格:
- UITextBorderStyleRoundedRect圆角风格
- UITextBorderStyleLine线框风格
- UITextBorderStyleBezel:bezel风格
- UITextBorderStyleNone:无边框风格
键盘风格(常用):
- UIKeyboardTypeDefault:默认风格
- UIKeyboardTypeNamePhonePad:字母和数字组合风格
- UIKeyboardTypeNumberPad:纯数字风格
#import "ViewController.h"@interface ViewController ()@end@implementation ViewController@synthesize textField = _textField;- (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view.//设定一个文本输入区对象self.textField = [[UITextField alloc] init];//设定文字输入区的位置self.textField.frame = CGRectMake(100, 100, 180, 40);//设置textField的内容文字self.textField.text = @"用户名";//设置文字的字体大小self.textField.font = [UIFont systemFontOfSize:15];//设置字体的颜色self.textField.textColor = [UIColor blueColor];//设置边框风格//UITextBorderStyleRoundedRect圆角风格//UITextBorderStyleLine线框风格//UITextBorderStyleBezel:bezel风格//UITextBorderStyleNone:无边框风格self.textField.borderStyle = UITextBorderStyleLine;//设置虚拟键盘风格//UIKeyboardTypeDefault:默认风格//UIKeyboardTypeNamePhonePad:字母和数字组合风格//UIKeyboardTypeNumberPad:纯数字风格self.textField.keyboardType = UIKeyboardTypeNumberPad;//提示文字信息//当text属性为空self.textField.placeholder = @"请输入用户名....";//是否作为密码输入//YES作为密码加密,NO正常显示self.textField.secureTextEntry = NO;[self.view addSubview:self.textField];
}- (void) textFieldDidBeginEditing:(UITextField *)textField
{NSLog(@"开始编辑了!");
}
-(void) textFieldDidEndEditing:(UITextField *)textField
{self.textField.text = @"";NSLog(@"编辑输入结束了");
}//是否可以进行输入
//如果返回值为YES:可以进行输入,默认为YES
//NO:不能输入文字,无权限的时候
-(BOOL) textFieldShouldBeginEditing:(UITextField *)textField
{return YES;
}//是否可以结束输入
//如果返回值为YES:可以结束输入,默认为YES
//NO:不能结束文字,输入密码位数不够
-(BOOL) textFieldShouldEndEditing:(UITextField *)textField
{if (self.textField.text.length < 9) {return NO;} else {return YES;}
}//点击屏幕空白处调用此函数
- (void) touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{//使虚拟键盘回收,不再做为第一消息响应者[self.textField resignFirstResponder];
}@end
UITextField控件的四个协议:
开始编辑协议:手机键盘弹出瞬间调用
- (void) textFieldDidBeginEditing:(UITextField *)textField
结束编辑协议:手机键盘收回瞬间调用
-(void) textFieldDidEndEditing:(UITextField *)textField
是否可以进行输入
如果返回值为YES:可以进行输入,默认为YES
NO:不能输入文字
使用场景:无权限的时候使用
-(BOOL) textFieldShouldBeginEditing:(UITextField *)textField
是否可以结束输入
如果返回值为YES:可以结束输入,默认为YES
NO:不能结束文字
使用场景:输入密码位数不够
-(BOOL) textFieldShouldEndEditing:(UITextField *)textField
滚动视图
手机屏幕较小,通常情况下无法完全展示内容,此时我们可以通过手势来滚动屏幕,达到移动视图的效果,而这个应用就是滚动视图。
像我们常用的QQ聊天页面,微信聊天页面等,就是滚动视图的实际应用。
滚动视图基础
我们可以设置上下滚动的视图,也可以设置左右滚动的视图,对应的画布大小需要跟着改变。
滚动视图的创建在视图控制器中进行,即ViewController文件中进行。
图片的添加我们采用循环的方式简略。
#import "ViewController.h"@interface ViewController ()@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view.UIScrollView *sv = [[UIScrollView alloc] init];//设置滚动视图的位置,使用矩形来定位视图位置sv.frame = CGRectMake(0, 0, 394, 852);//是否按照整页来滚动视图sv.pagingEnabled = YES;//是否可以开启滚动效果sv.scrollEnabled = YES;//设置画布的大小,画布显示在滚动视图内部,一般大于Frame的大小sv.contentSize = CGSizeMake(394*6, 852*2);//是否可以边缘弹动效果sv.bounces = YES;//开启横向弹动效果sv.alwaysBounceHorizontal = YES;//开启纵向弹动效果sv.alwaysBounceVertical = YES;//显示横向滚动效果sv.showsHorizontalScrollIndicator = YES;//显示纵向滚动条sv.showsVerticalScrollIndicator = YES;//设置背景颜色sv.backgroundColor = [UIColor whiteColor];//使用循环创建5张图片视图for (int i = 0; i < 5; i++){NSString *strName = [NSString stringWithFormat:@"%d.jpg", i+1];UIImage *image = [UIImage imageNamed:strName];UIImageView *iView = [[UIImageView alloc] initWithImage:image];iView.frame = CGRectMake(394*i, 0, 394, 952);[sv addSubview:iView];}[self.view addSubview:sv];
}@end
滚动视图高级
滚动视图中还有一个协议叫UIScrollViewDelegate,这个协议可以让我们实现更多控制效果。我们新建一个竖屏滚动效果来学习这个协议的方法。
#import "ViewController.h"@interface ViewController ()@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view.scrollView = [[UIScrollView alloc] init];scrollView.frame = CGRectMake(10, 50, 384, 802);//取消弹动效果scrollView.bounces = NO;//是否允许通过点击屏幕让滚动视图响应事件//YES:滚动视图可以接受触碰事件//NO:不接受触屏事件//scrollView.userInteractionEnabled = NO;//设置画布大小,纵向效果scrollView.contentSize = CGSizeMake(384, 802*9);for (int i = 0; i < 9; i++){//生成图片名称NSString *strName = [NSString stringWithFormat:@"%d.jpg", i+1];UIImage *image = [UIImage imageNamed:strName];UIImageView *iView = [[UIImageView alloc] init];iView.image = image;iView.frame = CGRectMake(0, 802 * i, 384, 802);[scrollView addSubview:iView];}[self.view addSubview:scrollView];//取消按页滚动效果scrollView.pagingEnabled = NO;//滚动视图画布的移动位置,偏移位置//功能:决定画笔显示的最终图像结果scrollView.contentOffset = CGPointMake(0, 0);//将当前视图控制器作为代理对象scrollView.delegate = self;
}//当滚动视图移动时,只要offset坐标发生变化,都会调用此函数
//参数:调用次协议的滚动视图对象
//可以使用此函数来监控滚动视图的位置
//- (void) scrollViewDidScroll:(UIScrollView *)scrollView
//{
// NSLog(@"y = %f", scrollView.contentOffset.y);
//}- (void) touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{//scrollView.contentOffset = CGPointMake(0, 0);//让滚动视图移动到指定位置,动画移动[scrollView scrollRectToVisible:CGRectMake(0, 0, 384, 802) animated:YES];
}//结束滑动时调用
-(void) scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{NSLog(@"Did End Drag!");
}
//将要开始滑动时调用
-(void) scrollViewWillBeginDragging:(UIScrollView *)scrollView
{NSLog(@"will Begin Drag");
}
//结束滑动视图后,准备结束滑行调用该函数
-(void) scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
{NSLog(@"Will End Drag!");
}
//准备开始滑动时调用该方法
-(void) scrollViewWillBeginDecelerating:(UIScrollView *)scrollView
{NSLog(@"Will Begin Deceleratege!");
}
//停止滑动时调用该方法
-(void) scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{NSLog(@"视图停止移动");
}
@end
注意:当结束滑动后,会有一个类似于惯性的滑动效果,此时会调用不同的方法。
效果:
总结
多多学习,多多思考。这篇博客的总结让我加深了对UI控件的认识,并且熟练了很多UI控件的使用
相关文章:

UI学习笔记(一)
UI学习 一:UIView基础frame属性隐藏视图对象:UIView的层级关系 二:UIWindow对象三:UIViewController基础UIViewController使用 四:定时器与视图移动五:UISwitch控件六:滑动条和进度条七…...

【C语言训练题库】扫雷->简单小游戏!
🔥博客主页🔥:【 坊钰_CSDN博客 】 欢迎各位点赞👍评论✍收藏⭐ 目录 1. 题目 2. 解析 3. 代码 4. 小结 1. 题目 小sun上课的时候非常喜欢玩扫雷。他现小sun有一个初始的雷矩阵,他希望你帮他生成一个扫雷矩阵。 扫雷…...

WMS仓储管理系统高效驱动制造企业物料管理
在现代制造业的快速发展中,仓储管理作为供应链的核心环节,其效率直接影响到企业的生产力和市场竞争力。随着科技的进步,实施WMS仓储管理系统逐渐成为推动仓储管理向智能化转型的关键力量。本文将深入探讨WMS仓储管理系统如何以创新的方式驱动…...
python使用appium打开程序后,为什么没有操作后程序就自动退出了
当使用Appium打开应用程序并在没有执行任何操作后它自动退出,这可能是由于几个不同的原因。以下是一些可能的原因和相应的解决方案: 应用程序的默认行为: 有些应用程序在启动后如果没有用户交互,可能会因为超时或其他逻辑而自动关…...
MacBook M系列芯片安装php8.2
适用于M1\M2\M3等系列的MacBook,记录下安装过程 安装brew 打开终端,执行如下命令: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"安装zsh(非必须) …...

OlSoul系统调校程序v2024.06.05
软件介绍 OlSoul是一款能够适配用于Win各个系统的系统调校软件,OlSoul内置有众多调校功能可以直接使用,如有启用无线网络功能、启用打印机功能、系统快速休眠与休眠开关、快捷方式小箭头去除功能等,具体的调校功能多达几十项,可自…...
图像特征提取 python
1. 边缘检测 (Edge Detection) 1.1 Sobel 算子 Sobel 算子是一种边缘检测算子,通过计算图像梯度来检测边缘。 import cv2 import numpy as np# 读取图像 image cv2.imread(image.jpg, 0)# 应用 Sobel 算子 sobel_x cv2.Sobel(image, cv2.CV_64F, 1, 0, ksize5)…...

width: 100%和 width: 100vw这两种写法有什么区别
width: 100%; 和 width: 100vw; 是两种不同的 CSS 写法,它们在实际应用中会有不同的效果。以下是这两种写法的主要区别: width: 100%; 定义:将元素的宽度设置为其包含块(通常是父元素)宽度的 100%。效果:元…...
如何在另一台电脑上使用相同的Python环境和依赖包
如果您想在另一台电脑上使用相同的Python环境和依赖包,有几种方法可以实现: 使用requirements.txt: 在您当前的虚拟环境中,您可以使用pip freeze > requirements.txt命令生成一个包含所有已安装包及其版本的文件。然后&#x…...
Vue3 响应式 API:工具函数(一)
isRef() isRef 是一个简单的工具函数,它接受一个参数并返回一个布尔值,指示该参数是否是一个由 ref 创建的响应式引用。 在某些情况下,你可能需要编写一些通用逻辑或函数,这些逻辑或函数需要处理不同类型的响应式数据(…...
开发常用软件
开发相关 代码编译 Visual Studio 2019 Visual Studio 2022 代码测试工具 LINQPad Premium 5 LINQPad 7 打包工具 Advanced Installer 反编译工具 ILSpy dnSpy spy 数据库相关 SQLite Expert Professional 5 DLL扫描工具 depends 界面设计 SvgToXaml Materi…...

conntrack如何限制您的k8s网关
1.1 conntrack 介绍 对于那些不熟悉的人来说,conntrack简单来说是Linux内核的一个子系统,它跟踪所有进入、出去或通过系统的网络连接,允许它监控和管理每个连接的状态,这对于诸如NAT(网络地址转换)、防火墙和保持会话连续性等任务至关重要。它作为Netfilter的一部分运行,…...

SwiftUI六组合复杂用户界面
代码下载 应用的首页是一个纵向滚动的地标类别列表,每一个类别内部是一个横向滑动列表。随后将构建应用的页面导航,这个过程中可以学习到如果组合各种视图,并让它们适配不同的设备尺寸和设备方向。 下载起步项目并跟着本篇教程一步步实践&a…...

高考分数查询结果自动推送至微信
又是一年高考时,祝各位学子金榜题名,天遂人愿! 在您阅读以下内容时,请注意:各省查分API接口可能不相同,本人仅就技术层面谈谈, 纯属无聊,因为实用意义不大,毕竟一年一次,…...

flask_sqlalchemy时间缓存导致datetime.now()时间不变问题
问题是这样的,项目在本地没什么问题,但是部署到服务器过一阵子发现,这个时间会在某一刻定死不变。 重启uwsgi后,发现第一条数据更新到了目前最新时间,过了一会儿再次发送也变了时间,但是再过几分钟再发就会…...

使用 PAI-DSW x Free Prompt Editing图像编辑算法,开发个人AIGC绘图小助理
教程简述 在本教程中,您将学习在阿里云交互式建模平台PAI-DSW x Free Prompt Editing(CVPR2024中选论文算法)图像编辑算法,开发个人AIGC绘图小助理,实现文本驱动的图像编辑功能单卡即可完成AIGC图片风格变化、背景变化…...

Nginx03-动态资源和LNMP介绍与实验、自动索引模块、基础认证模块、状态模块
目录 写在前面Nginx03案例1 模拟视频下载网站自动索引autoindex基础认证auth_basic模块状态stub_status模块模块小结 案例2 动态网站(部署php代码)概述常见的动态网站的架构LNMP架构流程数据库Mariadb安装安全配置基本操作 PHP安装php修改配置文件 Nginx…...
山东大学软件学院项目实训-创新实训-基于大模型的旅游平台(二十九)- 微服务(9)
目录 12. ElastisSearch 12.1 安装es 12.2 部署kibana 12.2.1 部署 12.2. 2 DevTools 12.3 索引库操作 12.3.1 mapping映射 12.3.2 创建索引库 12.3.3 查询索引库 12.3.4 删除索引库 12.3.5 修改索引库 12.4 文档操作 12.4.1 新增文档 12.4.2 查询文档 12.4.3 删…...

Matplotlib常见图汇总
Matplotlib是python的一个画图库,便于数据可视化。 安装命令 pip install matplotlib 常用命令: 绘制直线,连接两个点 import matplotlib.pyplot as plt plt.plot([0,5],[2,4]) plt.show() 运行结果如下: 多条线:…...

MTK联发科MT6897(天玑8300)5G智能移动处理器规格参数
天玑 8300 采用台积电第二代 4nm 制程,基于 Armv9 CPU 架构,八核 CPU 包含 4 个 Cortex-A715 性能核心和 4 个 Cortex-A510 能效核心,CPU 峰值性能较上一代提升 20%,功耗节省 30%。 此外,天玑 8300 搭载 6 核 GPU Mal…...

YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...

P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...
JDK 17 新特性
#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持,不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的ÿ…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...
React---day11
14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store: 我们在使用异步的时候理应是要使用中间件的,但是configureStore 已经自动集成了 redux-thunk,注意action里面要返回函数 import { configureS…...
代码随想录刷题day30
1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...

DeepSeek源码深度解析 × 华为仓颉语言编程精粹——从MoE架构到全场景开发生态
前言 在人工智能技术飞速发展的今天,深度学习与大模型技术已成为推动行业变革的核心驱动力,而高效、灵活的开发工具与编程语言则为技术创新提供了重要支撑。本书以两大前沿技术领域为核心,系统性地呈现了两部深度技术著作的精华:…...

使用SSE解决获取状态不一致问题
使用SSE解决获取状态不一致问题 1. 问题描述2. SSE介绍2.1 SSE 的工作原理2.2 SSE 的事件格式规范2.3 SSE与其他技术对比2.4 SSE 的优缺点 3. 实战代码 1. 问题描述 目前做的一个功能是上传多个文件,这个上传文件是整体功能的一部分,文件在上传的过程中…...