ios 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

  1. 现在需要将一个触摸事件的点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.

  1. 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值