2011-09-20 33 views
13

Tôi muốn thêm bóng đổ bằng cách sử dụng CALayer vào giao diện người dùng (Hình ảnh). Các mã sau đây làm việc nói chung là tốtBóng UIView và InterfaceBuilder

previewImage.layer.shadowColor = [[UIColor blackColor] CGColor]; 
previewImage.layer.shadowOffset = CGSizeMake(1.0f, 1.0f); 
previewImage.layer.shadowOpacity = 1.0f; 
previewImage.layer.shadowRadius = 8.0f; 

Tuy nhiên, điều này chỉ hoạt động nếu tôi có thể tạo điểm cho rằng lập trình và thêm nó như là một subview để giao diện chính của tôi. Khi khung nhìn đó được thiết lập trong InterfaceBuilder và được định nghĩa là một IBOutlet UIImageView thì nó không hoạt động. Không có bóng xuất hiện. Vì vậy, tôi thiếu gì ở đây?

+1

Khá ngẫu nhiên, tôi phát hiện ra vấn đề thực sự dường như không phải là InterfaceBuilder, nhưng thực tế là tôi đặt clipToBounds của giao diện ViewerBuilder của tôi = YES. Có NO ở đây là ổn. Vì vậy, tôi đoán sau đó tôi sẽ phải quấn xem trong một lần xem thứ hai với clipToBound = NO và bóng tối. Có cách nào khác không? – Dennis

+0

Tôi có cùng một vấn đề, nhưng đó là vì "Clip Subviews" đã được kiểm tra cho khung nhìn trong Interface Builder. Bỏ chọn làm cho bóng của CALayer hiển thị. – azdev

Trả lời

2

Tôi không chắc chắn vấn đề là gì - đảm bảo tài sản UIImageView 's clipsToBounds được đặt thành NO. Bạn có thể làm điều này trong viewDidLoad sau khi tải từ tệp nib bằng cách tham khảo IBOutlet của bạn. Bạn không cần phải quấn nó trong một cái nhìn khác.

Sửa

Trong ánh sáng của bạn cần hình ảnh của bạn để được thu nhỏ sử dụng khía cạnh đầy, bạn có thể sử dụng contentsRect tài sản của UIImageView 'lớp cơ bản s để 'mô phỏng' ảnh hưởng của các nội dung cắt. contentsRect là hình chữ nhật trong không gian tọa độ đơn vị của nội dung của lớp (trong trường hợp này là hình ảnh của bạn) xác định một hình chữ nhật phụ của nội dung cần được vẽ.

Với một chút toán học, chúng ta có thể tìm thấy hình chữ nhật này bằng cách so sánh kích thước xem hình ảnh với kích thước hình ảnh (chiếm tỉ lệ khía cạnh fill):

CGSize imageViewSize = previewImage.size; 
CGSize imageSize = previewImage.image.size; 

// Find the scaling required for the image to fit the image view (as for aspect fill). 
CGFloat imageWidthScale = fabsf(imageViewSize.width/imageSize.width); 
CGFloat imageHeightScale = fabsf(imageViewSize.height/imageSize.height); 
CGFloat imageScale = (imageWidthScale > imageHeightScale) ? imageWidthScale : imageHeightScale; 

// Determine the new image size, after scaling. 
CGSize scaledImageSize = CGSizeApplyAffineTransform(imageSize, CGAffineTransformMakeScale(imageScale, imageScale)); 

// Set the layer's contentsRect property in order to 'clip' the image to the image view's bounds. 
previewImage.layer.contentsRect = CGRectMake(((scaledImageSize.width - imageViewSize.width)/2.0f)/scaledImageSize.width, 
              ((scaledImageSize.height - imageViewSize.height)/2.0f)/scaledImageSize.height, 
              imageViewSize.width/scaledImageSize.width, 
              imageViewSize.height/scaledImageSize.height); 

Việc làm này, bạn có thể để clipsToBounds bộ đến NO cho chế độ xem hình ảnh của bạn nhưng hình ảnh vẫn sẽ bị cắt bớt. Nếu bạn cần thay đổi kích thước chế độ xem hình ảnh, có thể sẽ thuận tiện để bao bọc mã này thành một phương thức có tham số UIImageView.

Tôi hy vọng điều này sẽ hữu ích.

+0

Tôi đồng ý. Không cần gói. Chỉ cần không clipToBounds - như bóng tối bên ngoài giới hạn. – bandejapaisa

+0

Lý do tôi cần clipToBounds là, hình ảnh đó quá lớn để vừa với chế độ xem và tôi cần phải sử dụng "Aspect Fill" để làm cho nó trông đẹp mắt. Tôi có thể, tất nhiên, cắt hình ảnh chính nó bằng cách vẽ nó hoàn toàn mới và sau đó nhận được một phù hợp thông qua UIGraphicsGetImageFromCurrentImageContext(). Nhưng điều đó không phải là rất nhiều chi phí? – Dennis

+0

@Dennis: Nếu hình ảnh tĩnh và sẽ chỉ được sử dụng ở kích thước đó, thì đề xuất đầu tiên của tôi là tạo lại hình ảnh trong phần mềm chỉnh sửa hình ảnh của bạn trước và sau đó sử dụng nó trong chế độ xem hình ảnh của dự án mà không cần thay đổi hình dạng của nó. Tuy nhiên, nếu đây không phải là một tùy chọn, thì hãy xem chỉnh sửa của tôi ở trên. – Stuart

14

Tôi biết câu hỏi này đã lâu, nhưng gần đây tôi đã ở trong một tình huống tương tự vì vậy tôi quyết định đưa câu trả lời của tôi cho những người đang ở trong một tình huống như thế này.

tôi muốn để có thể thiết lập các borderColorshadowColor trên một UIView thông qua giao diện Builder, nhưng loại tài sản borderColor của một lớp là CGColor (giống như shadowColor) mà không phải là một trong những loại được phép thay đổi trong tính năng thuộc tính thời gian chạy do người dùng xác định.

Vì vậy, tôi đã làm một phần mở rộng cho CALayer và tôi bổ sung thêm hai tính chất gọi là borderColorIB và shadowColorIB có kiểu UIColor:

RuntimeAttributes.h

@import QuartzCore; 

@interface CALayer (IBConfiguration) 

@property(nonatomic, assign) UIColor* borderColorIB; 
@property(nonatomic, assign) UIColor* shadowColorIB; 

@end 

RuntimeAttributes.m

#import <UIKit/UIKit.h> 
#import "RuntimeAttributes.h" 

@implementation CALayer (IBConfiguration) 

-(void)setBorderColorIB:(UIColor*)color 
{ 
    self.borderColor = color.CGColor; 
} 

-(UIColor*)borderColorIB 
{ 
    return [UIColor colorWithCGColor:self.borderColor]; 
} 

-(void)setShadowColorIB:(UIColor*)color 
{ 
    self.shadowColor = color.CGColor; 
} 

-(UIColor*)shadowColorIB 
{ 
    return [UIColor colorWithCGColor:self.shadowColor]; 
} 

@end 

Bây giờ tôi alredy có thể thiết lập hai thuộc tính này thông qua giao diện Builder như thế này:

  1. Trong phần 'người dùng định nghĩa runtime thuộc tính' (Identity Thanh tra)
  2. Hãy chắc chắn rằng UIView được chọn và thêm các thuộc tính thời gian chạy sau:

    • lớp.borderWidth, Số, 1
    • layer.borderColorIB, Màu, someColor <- my custom property to set the borderColor
    • layer.shadowColorIB, Màu, someColor <- my custom property to set the shadowColor
    • layer.shadowOpacity, Số, 0,8
    • layer.shadowOffset, kích thước, {5,5}
    • lớp. cornerRadius, Số, 5

đây là một hình ảnh để cho bạn thấy làm thế nào tôi đã làm:

enter image description here

... và kết quả sẽ được rõ ràng trong thời gian chạy, không phải trong Xcode:

enter image description here

tôi hy vọng điều này có thể giúp một số người ngoài kia!

16

Thêm một file có tên UIView.swift trong dự án của bạn (hoặc chỉ cần dán này trong bất kỳ tập tin):

import UIKit 

@IBDesignable extension UIView { 

    /* The color of the shadow. Defaults to opaque black. Colors created 
    * from patterns are currently NOT supported. Animatable. */ 
    @IBInspectable var shadowColor: UIColor? { 
     set { 
      layer.shadowColor = newValue!.CGColor 
     } 
     get { 
      if let color = layer.shadowColor { 
       return UIColor(CGColor:color) 
      } 
      else { 
       return nil 
      } 
     } 
    } 

    /* The opacity of the shadow. Defaults to 0. Specifying a value outside the 
    * [0,1] range will give undefined results. Animatable. */ 
    @IBInspectable var shadowOpacity: Float { 
     set { 
      layer.shadowOpacity = newValue 
     } 
     get { 
      return layer.shadowOpacity 
     } 
    } 

    /* The shadow offset. Defaults to (0, -3). Animatable. */ 
    @IBInspectable var shadowOffset: CGPoint { 
     set { 
      layer.shadowOffset = CGSize(width: newValue.x, height: newValue.y) 
     } 
     get { 
      return CGPoint(x: layer.shadowOffset.width, y:layer.shadowOffset.height) 
     } 
    } 

    /* The blur radius used to create the shadow. Defaults to 3. Animatable. */ 
    @IBInspectable var shadowRadius: CGFloat { 
     set { 
      layer.shadowRadius = newValue 
     } 
     get { 
      return layer.shadowRadius 
     } 
    } 
} 

Sau đó, điều này sẽ có sẵn trong giao diện Builder cho mỗi điểm trong Utilities Panel> Attributes Inspector:

Utilities Panel

Bạn có thể dễ dàng thiết lập các bóng bây giờ.

Ghi chú:
- Bóng sẽ chỉ xuất hiện khi chạy.
- clipsToBounds phải là false (theo mặc định là)

Các vấn đề liên quan