Multiple UILabel in Page Control - swift

I am trying to do a scrollView + pageControl for multiple UILabel i.e. each view should have 2 UILabel - one for title and one for descriptions.
I am familiar with adding a single UILabel into scrollView + pageControl. The question is how do I add more than one UILabel into the scrollView's subview? I have the following code which works fine for a single UILabel:
#IBOutlet weak var bloggerReviewScrollView: UIScrollView!
#IBOutlet weak var bloggerReviewPageControl: UIPageControl!
var frame = CGRect(x: 0, y: 0, width: 0, height: 0)
var reviews: [Reviews] = [Reviews(name: "NameA", description: "DescriptionA", date: Date.init(), url: nil), Reviews(name: "NameB", description: "DescriptionB", date: Date.init(), url: nil)]
func updateReview() {
reviewPageControl.numberOfPages = reviews.count
for index in 0..<reviews.count {
frame.origin.x = reviewScrollView.frame.size.width * CGFloat(index)
frame.size = reviewScrollView.frame.size
let reviewContent = UILabel(frame: frame)
reviewContent.text = reviews[index].description
reviewContent.numberOfLines = 0
reviewScrollView.addSubview(reviewContent)
}
reviewScrollView.contentSize = CGSize(width: reviewScrollView.frame.size.width * CGFloat(reviews.count), height: reviewScrollView.frame.size.height)
reviewScrollView.delegate = self
}
However, other than reviews[index].description, I also want to display reviews[index].name in a different label so that the style for that label is independent of the style of the description label in the view. Are there any ways for me to do so?
Thanks a bunch!

What you need is to decide where and how you want to display your both labels, meaning label frames, I have divided into two parts you can change the frame based on your requirement and create new Label instance and add that to your reviewScrollView
func updateReview() {
reviewPageControl.numberOfPages = reviews.count
for index in 0..<reviews.count {
frame.origin.x = reviewScrollView.frame.size.width * CGFloat(index)
frame.size = reviewScrollView.frame.size
//title lable
////set title frame based on your requirment
let reviewLabelFrame = CGRect(x: frame.origin.x, y: 0, width: frame.width, height: frame.height/2)
let titleLabel = UILabel(frame: reviewLabelFrame)
titleLabel.text = reviews[index]. name // get name and set the title
titleLabel.numberOfLines = 0
reviewScrollView.addSubview(titleLabel)
//descriptions Label
//set descriptions frame based on your requirment
let desLableFram = CGRect(x: frame.origin.x, y: frame.height/2, width: frame.width, height: frame.height/2)
let desLable = UILabel(frame: desLableFram)
desLable.text = reviews[index].description //get description and set
desLable.numberOfLines = 0
reviewScrollView.addSubview(desLable) //add your descriptions
}
you need to calculate the frames for both the label based on your requirement

Related

Simple function for a customised label

I'm trying to write a most basic function that will set the parameters of a label.
First I set the position where I want to put a label:
var xCircularPos = UIScrollView.frame.width / 2
var yCircularPos = UIScrollView.frame.height * 0.15
And than write a function:
func textParameters(labelName: UILabel, text: String, xPosition: CGFloat, yPosition: CGFloat) {
labelName.textAlignment = .center
labelName.text = text
labelName.sizeToFit()
labelName.layer.position.x = CGFloat(0)
labelName.layer.position.y = CGFloat(0)
UIScrollView.addSubview(labelName)
}
Than I create a label and use a function:
let scoreLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 0, height: 21))
textParameters(labelName: scoreLabel, text: "Счет", xPosition: xCIrcularPos, yPosition: yCIrcularPos)
But nothing happens. When I set the same parameters for the label without a function - everything works fine. In both cases everything happens in viewDidLoad.
Can you please give a tip what I am missing?

How can I insert image to end of the string and insert more than one image in UITextView with swift?

I created an UITextView and I can add image with image picker into text view. But I have some problem about replacement image. I want add this image end of the text. And I want to add images more than one. (like: text + image + text...). How can I solve this problem ? Can anyone help me ?
let pickImage = UIImageView() // this is for imagepickercontroller
lazy var writePost: UITextView = {
let wpost = UITextView()
let images = pickImage
let attachment = NSTextAttachment()
let attString = NSAttributedString(attachment: attachment)
attachment.image = images.image
images.frame = CGRect(x: 0, y: 0, width: 220, height: 220)
images.contentMode = .scaleAspectFill
wpost.textStorage.insert(attString, at: wpost.selectedRange.location)
wpost.addSubview(images)
wpost.textAlignment = .center
wpost.textColor = UIColor.lightGray
wpost.font = UIFont(name: "AvenirNext-DemiBoldItalic", size: 16)
wpost.isEditable = true
wpost.isScrollEnabled = true
wpost.layer.borderWidth = 1.5
wpost.layer.cornerRadius = 7.0
wpost.layer.borderColor = UIColor.orange.cgColor
wpost.delegate = self
return wpost
}()
What you should do is use UITextView's textContainer's exclusionPaths property. The exclusionPaths property lets you assign an array of UIBezierPaths to your textContainer. When exclusionPaths are set, none of the UITextView's text will appear within these paths. You could then add a UIImageView as a subview of the UITextView's super view placed above the UITextView that has a frame equal to said exclusion path.
The end result will be a UITextView with a UIImageView placed above it. None of the UITextView's text will be blocked by the UIImageView as the UITextView's textContainer's exclusionPaths have instructed the text not to populate there.
Here is an example of some code I've done to do something similar, with variable names changed to match your code a bit:
let imageView: UIImageView!
func addImageView() {
imageView = UIImageView(frame: CGRect(x: textView.frame.maxX - 200, y: textView.frame.maxY - 150, width: 200, height: 150))
textView.superView.addSubview(imageView)
}
func setExclusionPath(for imageView: UIImageView) {
let imageViewPath = UIBezierPath(rect: CGRect(x: textView.frame.maxX - imageView.frame.width, y: textView.frame.maxY - imageView.frame.height, width: imageView.frame.width, height: imageView.frame.height))
textView.textContainer.exclusionPaths.append(imageViewPath)
}
func someMethod() {
addImageView()
setExclusionPath(for: self.imageView)
}
Resources:
exclusionPaths reference from Apple

How to fix UITextView text content position in Swift

I have UIView class and in this class have UITextView for use as inputText
In textViewDidChange from row 2 through 5 with any inter, or adding text, I add the UITextView bounds.size.height as much as need.
The problem is, in rows 3 and 5, first line text does not appear.
To be roughly a row above its own space.
And is created from the bottom of the empty space, without scrolling.
But the text in the 4th row have exact position
class QuestionCell: UIView, UITextViewDelegate{
var paragraph = UITextView()
func setParagraph(){
let frame = CGRect(x: 50,
y: 0,
width: forground.width-55,
height: forground.height)
paragraph.frame = frame
paragraph.isEditable = true
paragraph.delegate = self
// forground is some UIView in this View
forground.addSubview(paragraph)
}
func textViewDidChange(_ textView: UITextView) {
paragraph.bounds.size.height = paragraph.paragraphHeight
}
}
extension UITextView{
var paragraphHeight: CGFloat{
let fixedWidth = self.width
let newSize = self.sizeThatFits(CGSize.init(width: fixedWidth,
height: CGFloat(MAXFLOAT)))
var newFrame = self.frame
newFrame.size = CGSize.init(width: CGFloat(fmaxf(Float(newSize.width),
Float(fixedWidth))),
height: newSize.height)
return newSize.height
}
}
During Creating you need to specify :
paragraph.isScrollEnabled = false
After creating, you may set it back.

Swift ImageCropper returns an image outside of the specified "window"

I am making an app that has a UIWebView along with a button on a single view controller. When the button is clicked, an image (of the UIWebView) is captured using UIGraphicsContext.
This part works great! But when the button is clicked, after capturing the image, it displays the image as a subview on the same view, and I have been trying to use an ImageCropper Library that draws a CGRect in another subview over the UIImageView on the screen with a submit button. The rectangle itself can be resized (dragging the corners/edges) and moved around the view.
When the submit button is clicked, another subview is displayed in the top left hand portion of screen and display the image that was cropped (after clicking submit button) The idea is to only capture what is inside the rectangle. I am able to get the code working but the image captured is of the same image but not a section that is inside the CGRect.
I have 3 images that show how it works and shows the image that is cropped incorrectly.enter image description here . Shot 1 . Shot 2
Shot 3. I believe my problems lies within the size of image captured and the size of the image with the crop rect are not equal and that is why it is distorting it.
Does anyone know what might be the cause? Sorry for the long winded question but any help would be greatly appreciated!
Here is my code below:
ViewController.swift:
class ViewController: UIViewController {
#IBOutlet var webView: UIWebView!
#IBOutlet var imageView: UIImageView!
override func viewDidLoad() {
imageView.isHidden = true
let aString = URL(string: "https://www.kshuntfishcamp.com/home.page")
webView.loadRequest(URLRequest(url: aString!))
super.viewDidLoad()
}
#IBAction func takePhotoPressed(_ sender: UIButton) {
UIGraphicsBeginImageContextWithOptions(webView.bounds.size, false, 0.0)
if let aContext = UIGraphicsGetCurrentContext(){
webView.layer.render(in: aContext)
}
let capturedImage:UIImage? = UIGraphicsGetImageFromCurrentImageContext()
imageView = UIImageView(frame: CGRect(x: 22, y: 123, width: 330, height: 330))
let image = capturedImage
imageView.image = image
imageView.contentMode = UIViewContentMode.scaleAspectFill
imageView.clipsToBounds = true
imageView.isHidden = true
webView.isHidden = true
let editView = EditImageView(frame: self.view.frame)
let image2 = capturedImage!
editView.initWithImage(image: image2)
let croppedImage = editView.getCroppedImage()
self.view.addSubview(editView)
self.view.backgroundColor = UIColor.clear
UIImageWriteToSavedPhotosAlbum(croppedImage, nil, nil, nil)
}
EditImageView.swift - source (https://github.com/Thanatos-L/LyEditImageView)-only including parts that seem relevant to solving the problem
func initWithImage(image:UIImage){
imageView = UIImageView(frame: CGRect(x: 22, y: 123, width: 330, height: 330))
imageView.tag = IMAGE_VIEW_TAG;
self.addSubview(self.imageView)
imageView.isUserInteractionEnabled = true;
imageView.image = image
imageView.frame = CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)
let frame = AVMakeRect(aspectRatio: imageView.frame.size, insideRect: self.frame);
imageView.frame = frame
originImageViewFrame = frame
NSLog("initWithImage %#", NSStringFromCGRect(originImageViewFrame))
imageZoomScale = 1.0
commitInit()
}
private func cropImage() {
let rect = self.convert(cropView.frame, to: imageView)
let imageSize = imageView.image?.size
let ratio = originImageViewFrame.size.width / (imageSize?.width)!
let zoomedRect = CGRect(x: rect.origin.x / ratio, y: rect.origin.y / ratio, width: rect.size.width / ratio, height: rect.size.height / ratio)
let croppedImage = cropImage(image: imageView.image!, toRect: zoomedRect)
var view: UIImageView? = self.viewWithTag(1301) as? UIImageView
if view == nil {
view = UIImageView()
}
view?.frame = CGRect(x: 0, y: 0, width: croppedImage.size.width , height: croppedImage.size.height)
view?.image = croppedImage
view?.tag = 1301
self.addSubview(view!)
}

unable to find view with tag

In my viewWillAppear() I create a label and give it a tag. When another condition is met, I try to remove the label, but for some reason, that is not working and the label is still in the view. I must be doing something wrong...
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
var label: UILabel?
// Add label if there are no recipes
if (recipeBook.recipesArr.count == 0) {
label = self.view.viewWithTag(123) as? UILabel
//label?.tag = 123 // arbitrary num
label = UILabel(frame: CGRect(x: 0, y: self.view.frame.height/3, width: self.view.frame.width, height: 100))
label?.text = "Add A Recipe"
label?.textColor = UIColor(red:0.93, green:0.92, blue:0.92, alpha:1.0)
label?.font = label?.font.withSize(36)
label?.textAlignment = .center
self.view.addSubview(label!)
}
else {
// remove it
if let foundLabel = self.view.viewWithTag(123) {
foundLabel.removeFromSuperview()
} else {
print("Couldn't find label with tag in view")
}
}
}
I didn't realize in this line label = UILabel(frame: CGRect(x: 0, y: self.view.frame.height/3, width: self.view.frame.width, height: 100)) I was creating a new label which has a default tag of 0. Changed it to label?.frame = CGRect(x: 0, y: self.view.frame.height/3, width: self.view.frame.width, height: 100) so that I'm not creating a new label and everything is working fine. Silly mistake.
Your code is not doing what you think it is. If your recipesArr is empty (or more accurately the count is zero) you are trying to find a label/view with the tag 123. That is then ignored and you create a new label but don't give it a tag.
What you need to do is assign the label you create the tag 123 after you create it like this:
label?.tag = 123
Then you will have created the label and set it's tag so it can then subsequently be found.
you are recreating the label after the line label = UILabel(frame: CGRect
you can create the label programmatically like so without optionals:
lazy var recipeLabel: UILabel = {
let label = UILabel(frame: CGRect(x: 0, y: self.view.frame.height/3, width: self.view.frame.width, height: 100))
label.tag = 123
label.text = "Add A Recipe"
label.font = UIFont.systemFont(ofSize: 17.0)
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
then add it to your subview with iOS 9+ constraints if needed:
self.view.addSubview(recipeLabel)
then you can access the view anywhere by simply referencing the view recipeLabel or by the .tag property if you desire.