Set the position of Image View - ios

I want to change the position of image view that is based on different devices.
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier0, forIndexPath: indexPath) as! CelebrityHeaderCell
let CelebrityTopObj = self.mCelebrityTop[indexPath.item]
if CelebrityTopObj.video_pic != nil
{
SDWebImageManager.sharedManager().downloadImageWithURL(NSURL(string: CelebrityTopObj.video_pic), options: .LowPriority, progress: { (min:Int, max:Int) -> Void in
}) { (vimage:UIImage!, error:NSError!, cacheType:SDImageCacheType, finished:Bool, url:NSURL!) -> Void in
if vimage != nil && finished
{
if getScreenHeight()<=568 {
cell.VideoImg.image = imageResize(vimage, sizeChange: CGSize(width: self.screenWidth/2.5, height: self.screenWidth/3))
cell.PrevIcon.image = imageResize(UIImage(named: "icon_prev")!, sizeChange: CGSize(width: 25, height: 25))
cell.NextIcon.image = imageResize(UIImage(named: "icon_next")!, sizeChange: CGSize(width: 25, height: 25))
cell.TopName.font = cell.TopName.font.fontWithSize(15)
cell.PrevIcon.frame.origin.x = 10
cell.PrevIcon.frame.origin.y = 30
cell.PrevIcon.frame = CGRect(x: 10, y: 30, width: 25, height: 25)
} else {
cell.VideoImg.image = imageResize(vimage, sizeChange: CGSize(width: self.screenWidth/2, height: 100))
cell.PrevIcon.image = imageResize(UIImage(named: "icon_prev")!, sizeChange: CGSize(width: 55, height: 55))
cell.NextIcon.image = imageResize(UIImage(named: "icon_next")!, sizeChange: CGSize(width: 55, height: 55))
}
}
}
}
return cell
}
I want to set the position of PrevIcon by using frame.origin.x and frame.origin.y but it doesn't work. How do I do to set the position?
http://gfamily.cwgv.com.tw/public/images/iphone5.png

To set the new position try something like that:
cell.PrevIcon.frame = CGRect(x: 10, y: 50, width: cell.PrevIcon.frame.bounds.width, height: cell.PrevIcon.frame.bounds.width)
To change a parameter of the "frame" you have to set it with CGRect(). You cant edit just a single value.

Also have a look at size classes in storyboard. Size classes enables you to have different layout constraints for different device types and orientations. Here is a link to a quick tutorial.

Related

object value doesn't change after didset

I am using some cocoa pods frame to make UICollectionView. I am able to get the right data for each cell and setup views.
I want to have different ani
The animation end point should be related to the value of dataSource.The problem is that I can't use the didSet value as I wish. The frame of subviews I added are (0,0,0,0), the values of objects keep the same as initial value outside the didSet. I am not able to access the dataSource Value in setupView function.
Expected effect is that the red bar will move from left side to the right position:
class CereCell : DatasourceCell {
override var datasourceItem: Any?{
didSet {
guard let cere = datasourceItem as? CeremonyDay else { return }
nameLabel.text = cere.name
nameLabel.frame = CGRect(x: 0, y: 0, width: 10, height: 10)
currentBar.frame = CGRect(x: 100, y: 100, width: cere.percentage*100 , height: 10)
position.x = cere.percentage
}
}
let currentBar: UIView = {
let currentBar = UIView(frame: CGRect(x: 290, y: 100, width: 300, height: 10))
currentBar.backgroundColor = .red
return currentBar
}()
override func setupViews() {
super.setupViews()
contentView.addSubview(currentBar)
let frame = currentBar.frame
print(frame)
It just print the (290, 100, 300, 10), which is not the value in didSet.

Custom image and switch not showing in collection view controller at right place

My requirement is, I need to populate 10 cell's in collection view controller and I need to display in 6Th cell battery status and in 7th need to switch. The remaining cell is not required to show the battery status and switch. I am adding these two (battery status & switch) through programmatically.
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
if indexPath.row == 6 {
let percentage: CGFloat = 0.4
let imageview:UIImageView=UIImageView(frame: CGRect(x: 10, y: 50, width: 30, height: 18))
let img : UIImage = UIImage(named:"batteryIcon")!
imageview.image = img
let batteryView = UIView.init(frame: CGRect(x: 10, y: 50, width: 30, height: 18))
cell.addSubview(batteryView)
let colorRect = CGRect(x: batteryView.bounds.origin.x, y: batteryView.bounds.origin.y, width: batteryView.bounds.width * percentage, height: batteryView.bounds.height)
let coloredView = UIView(frame: colorRect)
coloredView.backgroundColor = UIColor.green
batteryView.addSubview(coloredView)
cell.contentView.addSubview(imageview)
} else if indexPath.row == 7 {
let switchDemo = UISwitch(frame: CGRect(x: 10, y: 40, width: 37, height: 18))
switchDemo.isOn = true
switchDemo.setOn(true, animated: false)
switchDemo.transform = CGAffineTransform(scaleX: 0.70, y: 0.70)
switchDemo.addTarget(self, action: #selector(switchValueDidChange), for: .valueChanged)
cell.contentView.addSubview(switchDemo)
}
return cell
}
Here it is Working fine. But the problem is when I call "collectionView.reloadData()" Instead of showing battery status and switch 6Th and 7Th cells, Those two appearing in other cells also.
I am not getting, What mistake I am done.
For a better understanding of my requirement, I am sharing an image.

Setting up UIContextualAction size

I would like to know if it's possible to set the UIContextualAction size (width and height).
I didn't find any member in UIContextualAction that allow me to do that so I wonder if there is a walk-around to do this?
action.image = UIGraphicsImageRenderer(size:CGSize(width: 35, height: 35 )).image { _ in
UIImage(named:"Delete")?.draw(in: CGRect(x: 0, y: 0, width: 35, height: 35))
}
action.backgroundColor = UIColor.red
return action
Update
I found this post, the idea behind is to use custom button and use UIGesture
https://www.raywenderlich.com/62435/make-swipeable-table-view-cell-actions-without-going-nuts-scroll-views
You might use this syntax to set width and height for UIContextualAction:
let contextAction = UIContextualAction(style: .normal, title: "", handler: {
(param: (Bool) -> Void) in param(true)
})
contextAction.image = UIGraphicsImageRenderer(size: CGSize(160, 90)).image {
_ in UIImage(named: "someObject")!.draw(in: CGRect(40, 10, 200, 100))
}
contextAction.backgroundColor = .green

sizeToFit not working on a programmatic tableview cell

I have a basic custom cell with a name label on the left and a price label on the right both set inside another view to customise the spacing. I want the price to change width to whatever the price is and not have it set but when i use sizetofit on the price in the cells init or the cellForRow at function nothing happens. I have looked around but cant see how to get it to work. I cant get the text size when in the init of a cell but it doesnt seem right to be setting the label size within cellForRowAt.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: SplitterCarouselItemTableViewCell = tableView.dequeueReusableCell(withIdentifier: "splitterCarouselItemTableViewCell") as! SplitterCarouselItemTableViewCell
var item = ((allBillSplitters[tableView.tag].items)?.allObjects as! [Item])[indexPath.row]
if allBillSplitters[tableView.tag].isMainBillSplitter {
getMainBillSplitterItems(splitter: allBillSplitters[tableView.tag])
item = mainBillSplitterItems[indexPath.row]
}
let count = item.billSplitters?.count
if count! > 1 {
cell.name!.text = "\(item.name!)\nsplit \(count!) ways"
cell.price!.text = "£\(Double(item.price)/Double(count!))"
} else {
cell.name!.text = item.name!
cell.price!.text = "£\(item.price)"
}
return cell
}
and heres my cell:
import UIKit
class SplitterCarouselItemTableViewCell: UITableViewCell {
var name: UILabel!
var price: UILabel!
var view: UIView!
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:)")
}
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: "splitterCarouselItemTableViewCell")
self.setupViews()
}
func setupViews() {
let width = Int(UIScreen.main.bounds.width * 0.88)
let height = Int(self.bounds.height)
self.backgroundColor = .clear
self.frame = CGRect(x: 0, y: 0, width: width, height: 45)
view = UIView(frame: CGRect(x: 0, y: 2, width: width, height: height - 4 ))
view.backgroundColor = UIColor.white.withAlphaComponent(0.5)
price = UILabel(frame: CGRect(x: width - 80, y: 0, width: 75, height: height))
price.font = UIFont.systemFont(ofSize: 15.0)
price.backgroundColor = .yellow
price.textAlignment = .right
name = UILabel(frame: CGRect(x: 5, y: 0, width: Int(price.frame.width), height: height))
name.backgroundColor = .red
name.font = UIFont.systemFont(ofSize: 15.0)
name.numberOfLines = 0
view.addSubview(name)
view.addSubview(price)
contentView.addSubview(view)
}
}
Any help would be great, im sure im missing something basic.
Ive added the yellow and red backgrounds for visibility in the screen shot.
You need to calculate the width of the price label based on text. Below code will help you to find the width
extension String {
func widthWithConstrainedHeight(height: CGFloat, font: UIFont) -> CGFloat {
let constraintRect = CGSize(width: .greatestFiniteMagnitude, height: height )
let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)
return boundingBox.width
}
}
Use above function to find string width and use that width to create frame of price label.
I'm unclear if you want the frame size to adjust or the font size. This answer assumes the latter, i.e. that you want a fixed frame width and a font that shrinks as needed to fit....
Try enabling adjustsFontSizeToFitWidth,
price = UILabel(frame: CGRect(x: width - 80, y: 0, width: 75, height: height))
price.font = UIFont.systemFont(ofSize: 15.0)
price.backgroundColor = .yellow
price.textAlignment = .right
price.adjustsFontSizeToFitWidth = true
this should shrink the font to fit the width of the label.

Aligning multiple runtime generated UILabels in a UITableView

I have a UITableView that needs to support content by listing style something like
But the tricky part is that the amount of "Label" will vary with each cell, some may have only 4 but also up to 12. Also the "Value" can be either a single word or short phrase up to two lines(like in the image above). So I decided to use UIStackView to help me pack and size my UILabels used to display this. I am currently stuck at a problem when the "Label" varies in length like:
I need the leading end of the "Values" to be aligned like the first image even though the "Label" vary in length. Is there a behaviour of UIStackView that allows so? Or is there another approach that can allow me to obtain the results I need?
Note: Each "Label" and "Value" is in one UIStackView, I did it to align them.
I tried using String Formatting too, but "Values" with more than one line will wrap under the label instead of wrapping by itself like I manage to do in the images.
I tried placing all "Labels" in one UIStackView and all "Values" in another, I could no get them to align like they do in the images once the "Value" is more than one line.
Or if it might be a mistake I made somewhere, this is how I created the UIStackViews:
var higherCount = 0
if labels.count<values.count {
higherCount = values.count
} else {
higherCount = labels.count
}
mainStackView = UIStackView(frame: CGRect(x: 0, y: 0, width: frame.width, height: frame.height))
for i in 0..<higherCount {
var height:CGFloat = 20
if (values[i] as NSString).size(attributes: [NSFontAttributeName:UIFont.systemFont(ofSize: UIFont.systemFontSize)]).width > frame.width {
height = 42
}
let stackViewToAdd = UIStackView(frame: CGRect(x: 0, y: 0, width: frame.width, height: height))
let label = UILabel(frame: CGRect(x: 0, y: 0, width: frame.width, height: height))
if labels.count<higherCount {
label.text = ""
} else {
label.text = labels[i]
}
label.setContentCompressionResistancePriority(1000, for: .horizontal)
label.setContentHuggingPriority(999, for: .horizontal)
stackViewToAdd.addArrangedSubview(label)
let value = UILabel(frame: CGRect(x: 0, y: 0, width: frame.width, height: height))
if values.count<higherCount {
value.text = ""
} else {
value.text = values[i]
}
value.lineBreakMode = .byWordWrapping
value.numberOfLines = 2
stackViewToAdd.addArrangedSubview(value)
mainStackView?.addArrangedSubview(stackViewToAdd)
}
mainStackView?.alignment = .fill
mainStackView?.axis = .vertical
mainStackView?.distribution = .fill
I you created your cell programmatically, then you can resize the cell programmatically depends on the size of UILabel Content.
In my case Label font is UIFont.systemFont(ofSize: 15), minimum TableViewCell height is 50, arrLabel1 and arrLabel2 will be the content of Labels.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrLable1.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .default, reuseIdentifier: "\(indexPath.row)")
let lable1 = UILabel(frame: CGRect(x: 10, y: 10, width: view.frame.size.width - 20, height: 0))
lable1.numberOfLines = 0
lable1.font = UIFont.systemFont(ofSize: 15)
lable1.text = arrLable1[indexPath.row]
lable1.sizeToFit()
cell.addSubview(lable1)
let lable2 = UILabel(frame: CGRect(x: 10, y: lable1.frame.origin.y + lable1.frame.size.height + 10 , width: view.frame.size.width - 20, height: 0))
lable2.numberOfLines = 0
lable2.font = UIFont.systemFont(ofSize: 15)
lable2.text = arrLable2[indexPath.row]
lable2.sizeToFit()
cell.addSubview(lable2)
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath)
-> CGFloat {
let boundingRect1 = arrLable1[indexPath.row].boundingRect(with: CGSize(width: view.frame.size.width - 40 , height: CGFloat(MAXFLOAT)), options: NSStringDrawingOptions.usesLineFragmentOrigin,attributes:[ NSFontAttributeName : UIFont.systemFont(ofSize: 15)] ,context: nil)
let boundingRect2 = arrLable2[indexPath.row].boundingRect(with: CGSize(width: view.frame.size.width - 40 , height: CGFloat(MAXFLOAT)), options: NSStringDrawingOptions.usesLineFragmentOrigin,attributes:[ NSFontAttributeName : UIFont.systemFont(ofSize: 15)] ,context: nil)
guard boundingRect1.height + boundingRect2.height + 30 > 50 else {
return 50
}
return boundingRect1.height + boundingRect2.height + 30
}
Set Label numberOfLines to 0

Resources