set collectionviewcell's UIImage shadow returns nil - swift

I've collectionview inside collectionview I've UIImage, what I want to do is to set shadow to that image and also rounded corners, I tried adding UIview with clipsToBounds true after that setting to my imageview, but UIImage returns nil any solutions?
let recommendedCell = collectionView.dequeueReusableCell(withReuseIdentifier: "recommendedCell", for: indexPath) as! RecommendedCollectionViewCell
recommendedCell.config(data: ttest[indexPath.row])
let outerView = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
outerView.clipsToBounds = false
outerView.layer.shadowColor = UIColor.black.cgColor
outerView.layer.shadowOpacity = 1
outerView.layer.shadowOffset = CGSize.zero
outerView.layer.shadowRadius = 10
outerView.layer.shadowPath = UIBezierPath(roundedRect: outerView.bounds, cornerRadius: 10).cgPath
recommendedCell.countryImage = UIImageView(frame: outerView.bounds)
recommendedCell.countryImage.clipsToBounds = true
recommendedCell.layer.cornerRadius = 22
return recommendedCell

Related

Background Color to imageView

I am trying to add a circle background to an image view. But I only see the image without background.
lazy var circle: UIImageView = {
let view = UIImageView()
view.contentMode = .scaleAspectFit
view.image = UIImage(named: "iconsCancelThin")
view.frame = CGRect(x: 0, y: 0, width: 32, height: 32)
view.tintColor = KSColor.neutral700.getColor()
view.backgroundColor = KSColor.neutral700.getColor()
view.clipsToBounds = true
view.layer.cornerRadius = 16
return view
}()
guard let image = circle.image else { return }
self.cancelButton.setBackgroundImage(image, for: .normal, barMetrics: .default)

Views misplaced when setting frames

I am trying to make a view programatically, making a card with an image and some text and overlaying it with some color. I have turned off clip to bounds and added some colors to make it more visual.
So when I set
overlay.frame = self.frame
or
overlay.frame = CGRect(x: 0, y: 0, width: frame.width, height: frame.height)
the overlay should cover the entire view but it does not, why is this?
This is what is showing
This is what I want to see, but with each card having a blue layer on top
private var leftImage: UIImageView = {
let i = UIImageView(frame: .zero)
i.contentMode = .scaleAspectFill
i.image = UIImage()
return i
}()
private var topLabel: UILabel = {
let label = UILabel(frame: .zero)
label.isUserInteractionEnabled = false
label.font = UIFont.boldSystemFont(ofSize: 16.0)
label.lineBreakMode = .byWordWrapping
label.adjustsFontSizeToFitWidth = true
label.numberOfLines = 2
return label
}()
var bottomLabel: UILabel = {
let label = UILabel(frame: .zero)
label.isUserInteractionEnabled = false
label.lineBreakMode = .byWordWrapping
label.font = UIFont.systemFont(ofSize: 12.0)
label.numberOfLines = 1
label.text = "60 seconds"
return label
}()
private var stackView: UIStackView = {
let stack = UIStackView(frame: .zero)
stack.axis = .vertical
stack.isUserInteractionEnabled = false
stack.distribution = .fillEqually
stack.layoutMargins = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
stack.isLayoutMarginsRelativeArrangement = true
return stack
}()
private var overlay: UIView = {
let view = UIView(frame: .zero)
view.backgroundColor = .blue
view.alpha = 0.8
//view.isHidden = true
return view
}()
override init(frame: CGRect) {
super.init(frame: frame)
create()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
create()
}
private func create() {
self.translatesAutoresizingMaskIntoConstraints = false
//leftview
leftImage.frame = CGRect(x: 0, y: 0, width: frame.width / 2, height: frame.height)
addSubview(leftImage)
//rightVIew
stackView.frame = CGRect(x: frame.midX, y: 0, width: frame.width / 2, height: frame.height)
clipsToBounds = false
//add views to stack
stackView.addArrangedSubview(topLabel)
stackView.addArrangedSubview(bottomLabel)
addSubview(stackView)
overlay.frame = CGRect(x: 0, y: 0, width: frame.width, height: frame.height)
addSubview(overlay)
//card styling
layer.cornerRadius = 10
}
overlay.frame = self.frame
That can never be right, except by accident, because the frame of overlay and the frame of self are in two different coordinate systems. At the very least you want to say
overlay.frame = self.bounds // bounds, not frame
However, that isn't going to work either unless you say it in the right place. The right place is when layout occurs:
override func layoutSubviews() {
super.layoutSubviews()
self.overlay.frame = self.bounds
}
Simply adding that to your existing code should solve the problem.
The issue is that you're setting your overlay's dimensions like so:
overlay.frame = CGRect(x: 0, y: 0, width: frame.width, height: frame.height)
before the superview has determined its final width and height. You'll need to do one of the following:
Call create() after the superview class has determined its final size
Continuously set the overlay's frame as the superview's width and height changes (see https://developer.apple.com/documentation/uikit/uiview/1622482-layoutsubviews)
Use AutoLayout constraints via a xib/storyboard file

How do I add a background to a scroll view and have it repeat to the end?

I am making a roster on a scroll view with every slide being someone different. I was wondering if there is a way to set a background and have it repeat to the end as it cuts off at a certain person
Currently, I am copy and pasting the background and dragging it to match
for i in 0..
let label = UILabel(frame: CGRect(x:xPosition+110, y: 350, width: 200, height: 200))
label.text = names[i]
label.font = UIFont.systemFont(ofSize: 35, weight: UIFont.Weight.bold)
label.adjustsFontSizeToFitWidth = true
label.textColor = UIColor.black
let imageView = UIImageView()
imageView.image = UIImage(named: names[i])
imageView.contentMode = .scaleAspectFit
imageView.frame = CGRect(x: xPosition-110, y: 150, width: 650, height: 250)
let descriptionM = UITextView(frame: CGRect(x: xPosition+65, y: 525, width: 300, height: 250))
descriptionM.text = desc[i]
descriptionM.textColor = UIColor.black
descriptionM.backgroundColor = UIColor.clear
descriptionM.contentMode = .scaleAspectFill
descriptionM.font = UIFont.systemFont(ofSize: 20)
scrollView.contentSize.width = scrollView.frame.width * CGFloat(i + 1)
scrollView.addSubview(label)
scrollView.addSubview(imageView)
scrollView.addSubview(descriptionM)
}
Results would be the photo to repeat to the end and past.
One way is to turn the background image into a resizable image with zero edge insets and the default (tiling) resizing mode. Set your image view's contentMode to .scaleToFill.
let image = UIImage(named: "background")!.resizableImage(withCapInsets: .zero)
imageView.contentMode = .scaleToFill
imageView.image = image
Then make sure your imageView is at least as big as your scroll view's contentSize.

Change UIBarButton image from gallery

I have UIBarButton and user can change image just chose photo or gallery image with image picker. My problem is bad scale image.
If I use AspectFit my UIBarButton look like this:
If I use AspectFill my UIBarButton look like this:
and if I try first change size image and after set it, image all time scratched:
This is my code:
func createPhotoBarButton(image: Data) {
let barbtn = UIBarButtonItem()
var image = UIImage(data:image)
if image == nil {
image = UIImage(named: "photoIcon")
}
let imageView = UIImageView(frame: CGRect(x: 0.0, y: 0.0, width: 35.0, height: 35.0))
imageView.image = image?.resizedImage(newSize: CGSize(width: 35, height: 35))?.withRenderingMode(.alwaysOriginal)
// imageView.image = cropToBounds(image: image!, width: 35, height: 35)
// imageView.image = image
imageView.contentMode = .scaleAspectFill
imageView.layer.cornerRadius = imageView.frame.size.height / 2
imageView.layer.masksToBounds = true
imageView.clipsToBounds = true
self.navigationItem.rightBarButtonItem = barbtn
barbtn.customView = imageView
barbtn.customView?.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(photoTapped(_:))))
}
And here func for resize image:
func resizedImage(newSize: CGSize) -> UIImage? {
guard size != newSize else { return self }
let hasAlpha = false
let scale: CGFloat = 0.0
UIGraphicsBeginImageContextWithOptions(newSize, !hasAlpha, scale)
UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)
draw(in: CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height))
let newImage: UIImage? = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage
}
Help me plz find the right way to resolving my problem.
As I understand your question. I found a solution.
Try this
func createPhotoBarButton(image: Data) {
let barbtn = UIBarButtonItem()
let imageView = UIImageView(frame: CGRect(x: 0.0, y: 0.0, width: 35.0, height: 35.0))
var image = UIImage(data:image)
if image == nil {
image = UIImage(named: "photoIcon")?.resize(maxWidthHeight: Double(imageView.frame.size.width))
}
imageView.image = image
imageView.contentMode = .scaleAspectFill
imageView.layer.cornerRadius = imageView.frame.size.height / 2
imageView.layer.masksToBounds = true
imageView.clipsToBounds = true
self.navigationItem.rightBarButtonItem = barbtn
barbtn.customView = imageView
barbtn.customView?.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(photoTapped(_:))))
}
Resize method
extension UIImage {
func resize(maxWidthHeight : Double)-> UIImage? {
let actualHeight = Double(size.height)
let actualWidth = Double(size.width)
var maxWidth = 0.0
var maxHeight = 0.0
if actualWidth > actualHeight {
maxWidth = maxWidthHeight
let per = (100.0 * maxWidthHeight / actualWidth)
maxHeight = (actualHeight * per) / 100.0
}else{
maxHeight = maxWidthHeight
let per = (100.0 * maxWidthHeight / actualHeight)
maxWidth = (actualWidth * per) / 100.0
}
let hasAlpha = true
let scale: CGFloat = 0.0
UIGraphicsBeginImageContextWithOptions(CGSize(width: maxWidth, height: maxHeight), !hasAlpha, scale)
self.draw(in: CGRect(origin: .zero, size: CGSize(width: maxWidth, height: maxHeight)))
let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
return scaledImage
}
}
Output
Try to create a custom button with the code below:
func createPhotoBarButton(image: Data) {
let imageBtnContainer = UIButton()
let imageBtn = UIButton(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
var image = UIImage(data:image)
if image == nil {
image = UIImage(named: "photoIcon")
}
imageBtn.setImage(image, forState: UIControlState.Normal)
imageBtn.frame = CGRectMake(0, 0, 53, 31)
imageBtn.imageView?.contentMode = .scaleAspectFit
imageBtnContainer.addSubview(imageBtn)
self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: imageBtnContainer)
...
}
You don't need anymore resizedImage(..) function
Here is working code (swift 4)
override func viewDidLoad() {
let containView = UIView(frame: CGRect(x: 0, y: 0, width: 35, height: 35))
let Button : UIButton = UIButton.init(type: .custom)
Button.frame = CGRect(x: 0, y: 0, width: 35, height: 35)
Button.Round = true
Button.setImage(UIImage(named: "photoIcon"), for: .normal)
Button.addTarget(self, action: #selector(btnTapped), for: .touchUpInside)
containView.addSubview(Button)
let rightBarButton = UIBarButtonItem(customView: containView)
self.navigationItem.rightBarButtonItem = rightBarButton
}
Button Action Here
#objc func btnTapped(_ sender: Any) {
print("Click Event")
}
Extension to Round
extension UIView{
#IBInspectable var Round:Bool{
get{
return false
}
set{
if newValue == true {
self.layer.cornerRadius = self.frame.size.height/2;
self.layer.masksToBounds = true;
}
}
}
}
Output:

How center a Navigation Bar Image [Swift]

in my project I have a Navigation Bar with a Button to open a slide menu.
Now I am trying to set a title image instead of the title string. Unlikely the image is pushed slightly to the right instead of being centered. I thought its because of the slide menu button in the left corner of my navigation bar. If I set a title in main.storyboard everything look properly. Why is it so, that my image won't be centered.
Image function:
func addNavBarImage() {
let navController = navigationController!
let image = UIImage(named: "TransparentLogo")
let imageView = UIImageView(image: image)
let bannerWidth = navController.navigationBar.frame.size.width
let bannerHeight = navController.navigationBar.frame.size.height
let bannerX = bannerWidth - image!.size.width
let bannerY = bannerHeight - image!.size.height
imageView.frame = CGRect(x: bannerX, y: bannerY, width: bannerWidth, height: bannerHeight)
imageView.contentMode = .scaleAspectFit
navigationItem.titleView = imageView
}
Button function:
func addSlideMenuButton(){
let btnShowMenu = UIButton(type: UIButton.ButtonType.system)
btnShowMenu.setImage(self.defaultMenuImage(), for: UIControl.State())
btnShowMenu.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
btnShowMenu.addTarget(self, action: #selector(BaseViewController.onSlideMenuButtonPressed(_:)), for: UIControl.Event.touchUpInside)
btnShowMenu.tintColor = UIColor(red: 3, green: 49, blue: 79)
let customBarItem = UIBarButtonItem(customView: btnShowMenu)
self.navigationItem.leftBarButtonItem = customBarItem;
}
Change the frame of your titleView in func addNavBarImage() like this:-
func addNavBarImage() {
let navController = navigationController!
let image = UIImage(named: "TransparentLogo")
let imageView = UIImageView(image: image)
let bannerWidth = navController.navigationBar.frame.size.width
let bannerHeight = navController.navigationBar.frame.size.height
let bannerX = bannerWidth - image!.size.width
let bannerY = bannerHeight - image!.size.height
imageView.frame = CGRect(x: bannerX, y: bannerY, width: bannerWidth, height: bannerHeight)
imageView.contentMode = .scaleAspectFit
navigationItem.titleView = imageView
}
to this
func addNavBarImage() {
let imageView = UIImageView(image: #imageLiteral(resourceName: "TransparentLogo"))
imageView.frame = CGRect(x: 0, y: 0, width: 170, height: 30)
imageView.contentMode = .scaleAspectFit
let titleView = UIView(frame: CGRect(x: 0, y: 0, width: 170, height: 30))
titleView.addSubview(imageView)
titleView.backgroundColor = .clear
self.navigationItem.titleView = titleView
}
func centeredNavBarImageView() {
if let navcontroller = navigationController {
let image = #imageLiteral(resourceName: "logo")
let imageView = UIImageView(image: image)
let bannerWidth = navcontroller.navigationItem.accessibilityFrame.size.width
let bannerHeight = navcontroller.navigationBar.frame.size.height
let bannerX = bannerWidth / 2 - image.size.width / 2
let bannerY = bannerHeight / 2 - image.size.height / 2
imageView.frame = CGRect(x: bannerX, y: bannerY, width: bannerWidth, height: bannerHeight)
imageView.contentMode = .scaleAspectFit
self.navigationItem.titleView = imageView
}