文章目录
- IOS UIView常用设置
- 1.UIView设置背景图片的方式
- 2. 设置圆角的三种方式
- 2.1 通过设置layer的属性 设置圆角
- 2.2 使用贝塞尔曲线UIBezierPath和Core Graphics框架画出一个圆角
- 2.3 使用CAShapeLayer和UIBezierPath设置圆角
- 2.4 Swift3.0异步设置高性能圆角图片
- 2.UIView 坐标转换
- UIView坐标转换列子
- 3.UIView 手势
- 3.1 手势种类
- 3.遍历UIView子视图,找出按钮控件,如果点击在范围内则返回当前控件
IOS UIView常用设置
1.UIView设置背景图片的方式
一 . 设置UIView的背景图片
1.将图片作为UIView的背景色,该方法过于占内存,不建议使用。
//1.imageNamed方式 self.view.backgroundColor = [UIColorcolorWithPatternImage:[UIImageimageNamed:@“image.jpg”]];
//2.方式
NSString *path = [[NSBundlemainBundle]pathForResource:@"image"ofType:@"jpg"];
self.view.backgroundColor = [UIColorcolorWithPatternImage:[UIImageimageWithContentsOfFile:path]];
//这两种方式都会在生成color时占用大量的内存。如果图片大小不够,就会平铺多张图片,不会去拉伸图片以适应View的大小。
//在View释放后,1中的color不会跟着释放,而是一直存在内存中;2中的color会跟着释放掉,当然再次生成color时就会再次申请内存
2.在UIView上再添加一个UIImageView显示图片作为UIView的背景图片
注意:如果有点击事件的话, userInteractionEnabled用户交互设置为YES。
3.iOS视图都是一个图层,最先放置的图层就会在最底层,如此最先给UIView添加一个UIImageView就可以作为UIView的背景图片使用啦。
4.其他方式(推荐)
NSString *path = [[NSBundlemainBundle]pathForResource:@"image"ofType:@“jpg”];
UIImage *image = [UIImageimageWithContentsOfFile:path];
self.view.layer.contents = (id)image.CGImage;
//注意: 要写清楚后缀,即使是”.png”。
2. 设置圆角的三种方式
2.1 通过设置layer的属性 设置圆角
最简单的一种,但是很影响性能,一般在正常的开发中使用很少.
UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(100, 100, 100, 100)];
//只需要设置layer层的两个属性
//设置圆角
imageView.layer.cornerRadius = imageView.frame.size.width / 2;
//将多余的部分切掉
imageView.layer.masksToBounds = YES;
[self.view addSubview:imageView];
2.2 使用贝塞尔曲线UIBezierPath和Core Graphics框架画出一个圆角
UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(100, 100, 100, 100)];
imageView.image = [UIImage imageNamed:@"1"];
//开始对imageView进行画图
UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, NO, 1.0);
//使用贝塞尔曲线画出一个圆形图
[[UIBezierPath bezierPathWithRoundedRect:imageView.bounds cornerRadius:imageView.frame.size.width] addClip];
[imageView drawRect:imageView.bounds];
imageView.image = UIGraphicsGetImageFromCurrentImageContext();
//结束画图
UIGraphicsEndImageContext();
[self.view addSubview:imageView];
2.3 使用CAShapeLayer和UIBezierPath设置圆角
首先需要导入<AVFoundation/AVFoundation.h>
- (void)viewDidLoad {
[super viewDidLoad];
UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(100, 100, 100, 100)];
imageView.image = [UIImage imageNamed:@"1"];
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:imageView.bounds byRoundingCorners:UIRectCornerAllCorners cornerRadii:imageView.bounds.size];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc]init];
//设置大小
maskLayer.frame = imageView.bounds;
//设置图形样子
maskLayer.path = maskPath.CGPath;
imageView.layer.mask = maskLayer;
[self.view addSubview:imageView];
}
let corner = UIRectCorner(rawValue: UIRectCorner.bottomLeft.rawValue | UIRectCorner.bottomRight.rawValue)
let maskPath = UIBezierPath(roundedRect: label.bounds, byRoundingCorners: corner, cornerRadii: CGSize(width: 4, height: 4))
let maskLayer = CAShapeLayer()
maskLayer.frame = label.bounds
maskLayer.path = maskPath.cgPath
label.layer.mask = maskLayer
//其中,corner是设置具体哪个角为圆角 :UIRectCorner.bottomLeft, UIRectCorner.bottomRight, UIRectCorner.topLeft,UIRectCorner.topRight
let corner = UIRectCorner(rawValue: UIRectCorner.bottomLeft.rawValue | UIRectCorner.bottomRight.rawValue)
在开发中我们经常会遇到对一个UIView 设置四个圆角的情况,这种情况是很好处理的。但是如果遇到只设置其中的某几个圆角的情况怎么办呢?有一种方法是通过UIBezierPath的方法来做,代码如下:
//设置uiview 的任意圆角
func SetMutiBorderRoundingCorners(_ view:UIView,corner:CGFloat)
{
let maskPath = UIBezierPath.init(roundedRect: view.bounds,
byRoundingCorners: [UIRectCorner.bottomLeft, UIRectCorner.topRight],
cornerRadii: CGSize(width: corner, height: corner))
let maskLayer = CAShapeLayer()
maskLayer.frame = view.bounds
maskLayer.path = maskPath.cgPath
view.layer.mask = maskLayer
}
此外,我们还会遇到给一个UIView设置某几条边框而不是全部边框的情况,解决办法如下:
func SetBorderWithView(_ view:UIView,top:Bool,left:Bool,bottom:Bool,right:Bool,width:CGFloat,color:UIColor)
{
if top
{
let layer = CALayer()
layer.frame = CGRect(x: 0, y: 0, width: view.frame.size.width, height: width)
layer.backgroundColor = color.cgColor
view.layer.addSublayer(layer)
}
if left
{
let layer = CALayer()
layer.frame = CGRect(x: 0, y: 0, width: width, height: view.frame.size.height)
layer.backgroundColor = color.cgColor
view.layer.addSublayer(layer)
}
if bottom
{
let layer = CALayer()
layer.frame = CGRect(x: 0, y: view.frame.size.height - width, width: width, height: width)
layer.backgroundColor = color.cgColor
view.layer.addSublayer(layer)
}
if right
{
let layer = CALayer()
layer.frame = CGRect(x: view.frame.size.width - width, y: 0, width: width, height: view.frame.size.height)
layer.backgroundColor = color.cgColor
view.layer.addSublayer(layer)
}
}
2.4 Swift3.0异步设置高性能圆角图片
写一个UIImage的分类,方便调用extensionUIImage{///异步设置圆角图片//-Parameters:///-size:图片大小///-fillColor:裁切区域填充颜色///-completion:回调裁切结果图片funccornerImage(size:CGSize,fillColor:UIColor,completion:@escaping((_image:UIImage)->()))->Void{//异步绘制裁切Dispatch
//写一个UIImage的分类,方便调用
extension UIImage {
/// 异步设置圆角图片 ///
/// - Parameters:
/// - size: 图片大小
/// - fillColor: 裁切区域填充颜色
/// - completion: 回调裁切结果图片
func cornerImage(size:CGSize, fillColor: UIColor, completion:@escaping ((_ image: UIImage)->())) -> Void { //异步绘制裁切
DispatchQueue.global().async {
//利用绘图建立上下文
UIGraphicsBeginImageContextWithOptions(size, true, 0) let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
//设置填充颜色
fillColor.setFill() UIRectFill(rect)
//利用贝塞尔路径裁切
let path = UIBezierPath.init(ovalIn: rect) path.addClip() self.draw(in: rect)
//获取结果
let resultImage = UIGraphicsGetImageFromCurrentImageContext()
//关闭上下文
UIGraphicsEndImageContext()
//主队列回调
DispatchQueue.main.async { completion(resultImage!) }
}
}
}
//调用绘制方法
let image = UIImage(named: "imageName")image?.cornerImage(size: CGSize(width: 200, height: 200), fillColor: UIColor.white)
{
(resultImage: UIImage) in self.imageView.image = resultImage
}
2.UIView 坐标转换
iOS中,常用的坐标转换和frame转换如下:
// 将像素point由point所在视图转换到目标视图view中,返回在目标视图view中的像素值
- (CGPoint)convertPoint:(CGPoint)point toView:(UIView *)view;
// 将像素point从view中转换到当前视图中,返回在当前视图中的像素值
- (CGPoint)convertPoint:(CGPoint)point fromView:(UIView *)view;
// 将rect由rect所在视图转换到目标视图view中,返回在目标视图view中的rect
- (CGRect)convertRect:(CGRect)rect toView:(UIView *)view;
// 将rect从view中转换到当前视图中,返回在当前视图中的rect
- (CGRect)convertRect:(CGRect)rect fromView:(UIView *)view;
UIView坐标转换列子
Controller的view中有一个tableView,tableView的cell上有一个button,现在需要将button的frame转为在Controller的view中的frame,怎么实现呢?
CGRect rect = [self.view convertRect:_button.frame fromView:_button.superview];
CGRect rect = [_button.superview convertRect:_button.frame toView:self.view];
button的frame是相对于其superview来确定的,frame确定了button在其superview的位置和大小
现在转换后,我们肉眼观察到的,所有屏幕上的控件的布局并不会改变,但是此时以上两个方法返回的frame代表着,button在self.view上的大小和位置
这里应该使用的是_button.frame而不能是_button.bounds
这里2个方法是可逆的,2个方法的区别就是消息的接收者和view参数颠倒
这里_button虽然是在tableView上的,但是不能写toView的消息接收者不能是tableView,因为_button的superview并不是tableView
注意理解消息的接收者,即第一行代码的self.view和第二行代码的_button.superview
一般来说,toView方法中,消息的接收者为被转换的frame所在的控件的superview;fromView方法中,消息的接收者为即将转到的目标view
- 现在需要将一个触摸事件的点screenPoint(触摸事件的点的坐标系是相对于当前的屏幕——UIWindow),转化为屏幕里某个tableView上的点。即我想知道,我现在触摸的屏幕位置,是在这个tableView的什么位置上
CGPoint tablePT = [_tableView convertPoint:screenPoint fromView:nil];
注意1.
当参数view为nil的时候,系统会自动帮你转换为当前窗口的基本坐标系(即view参数为整个屏幕,原点为(0,0),宽高是屏幕的宽高)
注意2.
当view不为nil的时候,消息的接收者和参数view都必须是在同一个UIWindow对象里
If view is nil, this method instead converts to window base coordinates. Otherwise, both view and the receiver must belong to the same UIWindow object.
- responseDragbackAtScreenPoint方法用于判断是否响应横滑返回消息,screenPoint是触摸事件的点
现在tableView上的cell中有一个横滑列表(UIScrollView),现在需要判断触摸点是否在UIScrollView的区域上,再根据其他条件判断是否需要横滑返回
- (BOOL)responseDragbackAtScreenPoint:(CGPoint)screenPoint
{
//将当前触摸点转化为tableView上的点
CGPoint tablePT = [tableView convertPoint:screenPoint fromView:nil];
//根据tableView上的点定位到当前点的IndexPath
NSIndexPath *pathIndex = [tableView indexPathForRowAtPoint:tablePT];
//根据IndexPath找到当前触摸位置的cell
UITableViewCell *cell = [tableView cellForRowAtIndexPath:pathIndex];
//遍历该cell上的所有subView
NSArray *subViews = [cell.contentView subviews];
for (UIView *itemView in subViews)
{
//找打当前cell上的UIScrollView,目前业务上只有1个
if ([itemView isKindOfClass:[UIScrollView class]])
{
UIScrollView *itemScrollView = (UIScrollView *)itemView;
//将当前的scrollView的frame转为相对于整个屏幕上的frame
CGRect rc = [itemScrollView.superview convertRect:itemScrollView.frame toView:nil];
//因为screenPoint和rc是同一个坐标系下的,所以可以用来判断screenPoint是否在rc的区域内
//1.当scrollView的cell超过屏幕的时候 2.当触摸点在scrollView的区域上的时候 3.当不是以下情况:scrollView还未被滑动的时候手指在上面向右滑 1.2.3都满足的情况下才不响应横滑返回
if (itemScrollView.contentSize.width > itemScrollView.width &&
CGRectContainsPoint(rc, screenPoint) &&
!(itemScrollView.contentOffset.x == -itemScrollView.contentInset.left))
return NO;
}
}
return YES;
}
3.UIView 手势
3.1 手势种类
1、拍击UITapGestureRecognizer (任意次数的拍击)
2、向里或向外捏UIPinchGestureRecognizer (用于缩放)
3、摇动或者拖拽UIPanGestureRecognizer
4、擦碰UISwipeGestureRecognizer (一般用以左右切换滑动)
5、旋转UIRotationGestureRecognizer (手指朝相反方向移动)
6、长按UILongPressGestureRecognizer
override func viewDidLoad() {
super.viewDidLoad()
var v = UIView(frame: CGRect(x: 0, y: 0, width: screenWidth, height: screenHeight));
//点击事件
let handTap = UITapGestureRecognizer(target: self, action: #selector(funTap))
v.addGestureRecognizer(handTap)
//拖动事件, 任意方向
let handDrag = UIPanGestureRecognizer(target: self, action: #selector(funDrag))
//v.addGestureRecognizer(handDrag)
//左右滑动,不可与拖动事件UIPanGestureRecognizer并存 , 默认只支持向右
let handLeftRight = UISwipeGestureRecognizer(target: self, action: #selector(funLeftRight))
handLeftRight.direction = .left //支持向左
v.addGestureRecognizer(handLeftRight)
self.view.addSubview(v)
}
func funTap(sender: UIPanGestureRecognizer){
print("funTap_"+String(arc4random()));
}
func funDrag(sender: UIPanGestureRecognizer){
var Point = sender.translation(in: self.view);//现对于起始点的移动位置
Point = sender.location(in: self.view);//在整个self.view 中的位置
print("funDrag_"+String(describing: Point.x)+","+String(describing:Point.y))
if(sender.state == .began){
print("begin: "+String(describing: Point.x)+","+String(describing:Point.y))
}else if(sender.state == .ended){
print("ended: "+String(describing: Point.x)+","+String(describing:Point.y))
}else{
print("ing: "+String(describing: Point.x)+","+String(describing:Point.y))
}
}
func funLeftRight(sender: UIPanGestureRecognizer){
print("funLeftRight_"+String(arc4random()));
}
如果想获取 参数 sender:UIxxxGestureRecognizer 中的视图 信息
//如果想获取 参数 sender:UIxxxGestureRecognizer 中的视图 信息
func showLongPress(sender:UILongPressGestureRecognizer){
print((sender.view as! XXX).url.text);
}
//传递 和 获取 UIButton 信息
func xxx(sender: UILongPressGestureRecognizer){
let btn:UIButton = sender.view as! UIButton
print(btn.tag)
}
//UILongPressGestureRecogizer
class xxx: aaa, UIGestureRecognizerDelegate{
//让 添加 的 长按事件 与 控件本身 的长按事件 并存,不添加不会触发 addGestureRecognizer 的长按
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true;
}
func longPressWeb(sender:UILongPressGestureRecognizer){
if(sender.state == .began){
print("long preses began")
}else if(sender.state == .ended){
print(" long press end")
}
print("you do long press");
}
override func viewDidLoad() {
let long = UILongPressGestureRecognizer(target: self, action: #selector(longPressWeb));
long.delegate = self
self.view.addGestureRecognizer(long)
}
}
3.遍历UIView子视图,找出按钮控件,如果点击在范围内则返回当前控件
如果视图是从nib中加载的,我们应该首先实现initWithCode:因为nib中的对象实例将存储为归档对象。(某一个view设置为自定义的子view)
hitTest代码范例:
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
for (UIView *tmpView in self.subviews )
{
if(tmpView.userInteractionEnabled && [tmpView isMemberOfClass:[UIButton class]])
{
if (CGRectContainsPoint(tmpView.frame,point)) {
return tmpView;
}
}
}
return nil;
}