I want to setup my scrollView like this video (I know in video use collectionview bu for some reason I want convert this effect to scrollView)
https://www.dropbox.com/s/kj6xgj68gz6258p/ScreenRecording_06-26-2018%2019-15-43.MP4
3 important thing:
scroll must snap to center when scrolling
resize current item (forward item is bigger than backward item)
swift
UPDATE:
var ScrollView = UIScrollView()
var arr : Array<UIColor> = [.red,.blue,.green]
override func viewDidLoad() {
super.viewDidLoad()
ScrollView.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(ScrollView)
ScrollView.widthAnchor.constraint(equalToConstant: self.view.frame.size.width).isActive = true
ScrollView.heightAnchor.constraint(equalToConstant: 320).isActive = true
ScrollView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor, constant: 0).isActive = true
ScrollView.alwaysBounceVertical = false
ScrollView.isPagingEnabled = true
ScrollView.contentSize = CGSize(width: 3.0 * self.view.frame.size.width, height: 320)
ScrollView.contentOffset = CGPoint(x: view.frame.size.width, y: 0)
ScrollView.center = self.view.center
for i in 0..<3 {
let viewBG = UIView()
viewBG.backgroundColor = arr[i]
if (i == 0) {
viewBG.frame = CGRect(x: view.frame.size.width * CGFloat(i) + 125, y: 0, width: view.frame.size.width - 100, height: 320)
} else if(i == 1) {
viewBG.frame = CGRect(x: view.frame.size.width * CGFloat(i) + 50, y: 0, width: view.frame.size.width - 100, height: 320)
} else {
viewBG.frame = CGRect(x: view.frame.size.width * CGFloat(i) - 25, y: 0, width: view.frame.size.width - 100, height: 320)
}
ScrollView.addSubview(viewBG)
}
}
thanks guys
Use iCarousal. It is easy to implement and Swift example is also available.
Following is link -
https://github.com/nicklockwood/iCarousel
Related
I'm setting header padding for my tableview in iOS older than 15 explicitly. This works for the top first header (section 1 of tableview), but doesn't work for second header (section 2 of tableview). How could I set it for the second also?
Is there something like tableView.tableHeaderView[2] or tableView.tableHeaderView.second ?
In code its the place with commented-out places.
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
if tableView.tag == 2 {
if section == 0 {
if self.tableView(tableView, numberOfRowsInSection: section) > 0 {
let view = UIView()
let imageView = UIImageView(image: UIImage(named: "Logo_face"))
if #unavailable(iOS 15.0) {
imageView.frame = CGRect(x: 10, y: 20, width: 25, height: 25)
} else {
imageView.frame = CGRect(x: 10, y: 0, width: 25, height: 25)
}
view.addSubview(imageView)
let label = UILabel()
label.text = "店舗"
label.frame = CGRect(x: 40, y: 0, width: 200, height: 25)
view.addSubview(label)
if #unavailable(iOS 15.0) { //setting here; works
let padding: CGFloat = 20
view.frame = CGRect(x: view.frame.origin.x - padding,
y: view.frame.origin.y - padding,
width: view.frame.width + 2 * padding,
height: view.frame.height + 2 * padding)
tableView.tableHeaderView = view // this is good
label.frame = CGRect(x: 40, y: 20, width: 200, height: 25)
}
return view
}
} else {
if self.tableView(tableView, numberOfRowsInSection: section) > 0 {
let view = UIView()
let imageView = UIImageView(image: UIImage(named: "pinIconForSearch"))
if #unavailable(iOS 15.0) {
imageView.frame = CGRect(x: 10, y: 20, width: 25, height: 25)
} else {
imageView.frame = CGRect(x: 10, y: 0, width: 25, height: 25)
}
view.addSubview(imageView)
let label = UILabel()
label.text = "検索候補"
label.frame = CGRect(x: 40, y: 0, width: 200, height: 25)
view.addSubview(label)
if #unavailable(iOS 15.0) { //setting here doesnt work
let padding: CGFloat = 20
view.frame = CGRect(x: view.frame.origin.x - padding,
y: view.frame.origin.y - padding,
width: view.frame.width + 2 * padding,
height: view.frame.height + 2 * padding)
tableView.tableHeaderView = view // this is not good
label.frame = CGRect(x: 40, y: 20, width: 200, height: 25)
}
return view
}
}
}
if #available(iOS 15.0, *) {
tableView.sectionHeaderTopPadding = 0.0
} else {}
return nil
}
I am trying to add few views to see if the NSScrollView will scroll vertically but it is not doing anything.
private func configure2() {
var yOffset = 0
let scrollView = NSScrollView(frame: NSRect(x: 0, y: 0, width: 400, height: 900))
scrollView.hasVerticalScroller = true
for _ in 1...20 {
let v = NSView(frame: NSRect(x: 0, y: 0 + yOffset, width: 50, height: 20))
v.wantsLayer = true
v.layer?.backgroundColor = NSColor.red.cgColor
scrollView.addSubview(v)
yOffset += 40
}
scrollView.backgroundColor = NSColor.green
self.addSubview(scrollView)
}
I remember in UIKit I can set the contentSize property of UIScrollView but in macOS I cannot set contentSize.
You need to set either the documentView or contentView of your NSScrollView. Then, you'll add your subviews to that view.
private func configure2() {
var yOffset = 0
let scrollView = NSScrollView(frame: NSRect(x: 0, y: 0, width: 400, height: 900))
let documentView = NSView(frame: .zero)
scrollView.hasVerticalScroller = true
for _ in 1...20 {
let v = NSView(frame: NSRect(x: 0, y: 0 + yOffset, width: 50, height: 20))
v.wantsLayer = true
v.layer?.backgroundColor = NSColor.red.cgColor
documentView.addSubview(v)
yOffset += 40
}
print(yOffset)
documentView.frame = .init(x: 0, y: 0, width: 400, height: yOffset)
scrollView.documentView = documentView
scrollView.backgroundColor = NSColor.green
self.addSubview(scrollView)
}
After editing my UIScrollView size, page control stopped working.
You can see there are only 3 slides. But (1) Page Control isn't reflecting which slide I'm on and (2) I can only scroll from slide 1 to slide 3.
Here's my code:
func setupSlideScrollView(slides : [Slide]) {
scrollView.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: 154)
scrollView.contentSize = CGSize(width: 188 * CGFloat(slides.count) + CGFloat((slides.count - 1) * 10), height: 153)
scrollView.isPagingEnabled = true
var lastCellMaxX: CGFloat = 0
let constantSpacingBetweenCell: CGFloat = 10
for i in 0 ..< slides.count {
slides[i].frame = CGRect(x: lastCellMaxX, y: 0, width: 220, height: 153)
scrollView.addSubview(slides[i])
lastCellMaxX += 188 + constantSpacingBetweenCell
}
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let pageIndex = round(scrollView.contentOffset.x/scrollView.frame.size.width)
pageControl.currentPage = Int(pageIndex)
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
// This will always round down to zero
// since the contentOffset.x will always be smaller than the frame width...
let pageIndex = round(scrollView.contentOffset.x/scrollView.frame.size.width)
// Possible logic to correct this?
let pageIndex = scrollView.contentOffset.x / (width of a slide)
pageControl.currentPage = Int(pageIndex)
}
-- Updated due to chat --
Your scrollview's frame is fine. However, you need to add a stackview to hold all your slides in order to scroll through it. Scrollviews are a bit tricky since you can't just add views and expect it to be scrollable.
Here is test code I used to create a scrollView that contains stackviews.
func createSlideshow() {
scrollView.translatesAutoresizingMaskIntoConstraints = false
let slide1 = UIView(frame: CGRect(x: 0, y: 0, width: 220, height: 375))
slide1.backgroundColor = UIColor.red
let slide2 = UIView(frame: CGRect(x: 0, y: 0, width: 220, height: 375))
slide2.backgroundColor = UIColor.blue
let slide3 = UIView(frame: CGRect(x: 0, y: 0, width: 220, height: 375))
slide3.backgroundColor = UIColor.yellow
let slides: [UIView] = [slide1, slide2, slide3]
let stackView = UIStackView()
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.axis = .horizontal
stackView.alignment = .center
stackView.distribution = .equalCentering
stackView.spacing = 10
for slide in slides {
stackView.addArrangedSubview(slide)
slide.widthAnchor.constraint(equalToConstant: slide.frame.width).isActive = true
slide.heightAnchor.constraint(equalTo: stackView.heightAnchor).isActive = true
}
scrollView.addSubview(stackView)
stackView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
stackView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
stackView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
stackView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
stackView.widthAnchor.constraint(greaterThanOrEqualTo: scrollView.widthAnchor).isActive = true
stackView.heightAnchor.constraint(equalTo: scrollView.heightAnchor).isActive = true
}
I have specified the frame of a Card, why can't I add this card to a scrollView?
When I try to add it to a UIScrollView, it will just become a withe bar. Cannot display the content(which is a label), or the toolbar(with title and detail and an IconButton).
Code for scrollView
eventList = UIScrollView()
eventList?.frame = CGRect(x: 0, y: (calender?.frame.height)! + (calenderMenu?.frame.height)!, width: ScreenWidth, height: ScreenHeight - (calenderMenu?.frame.height)! - (calender?.frame.height)!)
eventList?.scrollsToTop = true
eventList?.isScrollEnabled = true
eventList?.bounces = true
eventList?.isPagingEnabled = true
eventList?.indicatorStyle = .default
eventList?.contentSize = CGSize(width: ScreenWidth - 20, height: 400)
eventList?.delegate = self
self.view.addSubview(eventList!)
Code for Card
signinCard = Card()
signinCard?.frame = view.bounds
signinCard?.toolbar = signinToolbar
signinCard?.toolbarEdgeInsetsPreset = .square3
signinCard?.toolbarEdgeInsets.bottom = 0
signinCard?.toolbarEdgeInsets.right = 8
signinCard?.contentView = contentView
signinCard?.contentViewEdgeInsetsPreset = .wideRectangle3
signinCard?.bottomBar = Bar()
signinCard?.frame = CGRect(x: 10, y: 10, width: ScreenWidth - 20, height: (eventList?.frame.height)! / 2 - 5)
eventList?.addSubview(signinCard!)
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
I would like to expand an view when I switch a switch to on, and to collapse when I switch the switch to off.
At the same time all the other elements I have in my design have to move down or up.
Here is how the layout looks like when the switches are OFF
And here is how the layout looks like when the switches are ON:
I hope you understand what I am trying to do.
And the question... How do I do that???
It's much easier to do with AutoLayout and inside InterfaceBuilder (with a xib or storyboard), so foremost familiarize yourself with them if needed.
Wrap a container UIView around the UISwitches and make sure to set it to Clip Subviews.
Add a constraint for the container view's height and set it to 0.
Drag that constraint into your class declaration to generate an IBOutlet property.
Drag a new outlet from your UISwitch 'Value Changed' event to the class to generate an IBAction method.
Make sure to implement that method so that when the value changes, based on the change you toggle-animate the height constraint (the IBOutlet)
self.firstHeightConstraint.constant = on ? 200.0 : 0.0
self.view.setNeedsUpdateConstraints()
UIView.animateWithDuration( ...
options:.BeginFromCurrentState,
animations: { self.view.layoutIfNeeded() } ...
)
Using UIView, it's not a good way. You should use UITableView instead of views.
Using TableView, you can add UISwitch with title according to the first image, in UITableView's header and return required number of rows in changed section in TableView on state ON and return the number of rows 0 on state OFF.
Still an issue, please let me know I'll help you.
I know my code isnt the cleanest, but it bothers me when answers tell the questioner its not a good way or do it this way instead. I am offering a solution NOT using table views or constraints:
In your example, you can use tags for each "level" that needs to be moved. So starting with switch 2 and all views below that, you would have a tag for that level (the second hidden collapsable view would have a tag of 2 as well), then switch 3 would have a tag of 3.
For the labels hidden, you are adding them to a subview i call insideView1 or insideView2. The frames of those inside views should have the proper minX, minY and width, but have a height of 0 to start. Also importantly they have layer.masksToBounds = false, so their subviews dont show when their height is 0. We then animate the height changing to the proper height (expanding), as well as all subviews under changing position.
Lastly i made a dictionary to keep track of when a section is expanded so you can use the same function to expand/collapse other areas while one is already expanded.
import UIKit
class ExpandViewController: UIViewController {
var insideView1 = UIView()
var insideView2 = UIView()
var expand = [1:true,2:true]
#objc func expandCollapse(_ sender : UIButton) {
var heightChange = CGFloat(0)
switch sender.tag {
case 1:
heightChange = 90
default:
heightChange = 90
}
var viewsToExpand = [UIView(),insideView1,insideView2]
UIView.animate(withDuration: 1.0) { [self] in
let expandMe = viewsToExpand[sender.tag]
if expand[sender.tag] == true {
expandMe.frame.size.height = heightChange
for v in view.subviews {
if v.tag > sender.tag {
v.center.y += heightChange
}
}
} else {
expandMe.frame.size.height = 0
for v in view.subviews {
if v.tag > sender.tag {
v.center.y -= heightChange
}
}
}
expand[sender.tag] = !expand[sender.tag]!
}
}
override func viewDidLoad() {
super.viewDidLoad()
let switcher1 = UISwitch()
switcher1.tag = 1
switcher1.isOn = false
switcher1.frame = CGRect(x: view.bounds.width - 150, y: 100, width: 40, height: 30)
switcher1.addTarget(self, action: #selector(expandCollapse(_:)), for: .allTouchEvents)
view.addSubview(switcher1)
let switchLabel1 = UILabel()
switchLabel1.tag = 1
switchLabel1.text = "Switch 1"
switchLabel1.frame = CGRect(x: 30, y: 0, width: view.bounds.width, height: 30)
switchLabel1.center.y = switcher1.center.y
view.addSubview(switchLabel1)
let switcher2 = UISwitch()
switcher2.tag = 2
switcher2.isOn = false
switcher2.frame = CGRect(x: view.bounds.width - 150, y: 140, width: 40, height: 30)
switcher2.addTarget(self, action: #selector(expandCollapse(_:)), for: .allTouchEvents)
view.addSubview(switcher2)
let switchLabel2 = UILabel()
switchLabel2.tag = 2
switchLabel2.text = "Switch 2"
switchLabel2.frame = CGRect(x: 30, y: 0, width: view.bounds.width, height: 30)
switchLabel2.center.y = switcher2.center.y
view.addSubview(switchLabel2)
let switcher3 = UISwitch()
switcher3.tag = 3
switcher3.isOn = false
switcher3.frame = CGRect(x: view.bounds.width - 150, y: 180, width: 40, height: 30)
// switcher3.addTarget(self, action: #selector(expandCollapse(_:)), for: .allTouchEvents)
view.addSubview(switcher3)
let switchLabel3 = UILabel()
switchLabel3.tag = 3
switchLabel3.text = "Switch 3"
switchLabel3.frame = CGRect(x: 30, y: 0, width: view.bounds.width, height: 30)
switchLabel3.center.y = switcher3.center.y
view.addSubview(switchLabel3)
insideView1.frame = CGRect(x: 0, y: switcher1.frame.maxY + 5, width: view.bounds.width, height: 0)
insideView1.layer.backgroundColor = UIColor.lightGray.cgColor
insideView1.layer.masksToBounds = true
insideView1.tag = 1
view.addSubview(insideView1)
insideView2.frame = CGRect(x: 0, y: switcher2.frame.maxY + 5, width: view.bounds.width, height: 0)
insideView2.layer.backgroundColor = UIColor.lightGray.cgColor
insideView2.layer.masksToBounds = true
insideView2.tag = 2
view.addSubview(insideView2)
let insideLabel1 = UILabel()
insideLabel1.text = "Label"
insideLabel1.frame = CGRect(x: 60, y: 10, width: view.bounds.width, height: 30)
insideView1.addSubview(insideLabel1)
let insideTextField1 = UITextField()
insideTextField1.frame = CGRect(x: 200, y: 0, width: view.bounds.width - 240, height: 30)
insideTextField1.center.y = insideLabel1.center.y
insideTextField1.layer.backgroundColor = UIColor.white.cgColor
insideView1.addSubview(insideTextField1)
let insideLabel2 = UILabel()
insideLabel2.text = "Label"
insideLabel2.frame = CGRect(x: 60, y: 50, width: view.bounds.width, height: 30)
insideView1.addSubview(insideLabel2)
let insideTextField2 = UITextField()
insideTextField2.frame = CGRect(x: 200, y: 0, width: view.bounds.width - 240, height: 30)
insideTextField2.center.y = insideLabel2.center.y
insideTextField2.layer.backgroundColor = UIColor.white.cgColor
insideView1.addSubview(insideTextField2)
let insideLabel3 = UILabel()
insideLabel3.text = "Label"
insideLabel3.frame = CGRect(x: 60, y: 10, width: view.bounds.width, height: 30)
insideView2.addSubview(insideLabel3)
let insideTextField3 = UITextField()
insideTextField3.frame = CGRect(x: 200, y: 0, width: view.bounds.width - 240, height: 30)
insideTextField3.center.y = insideLabel3.center.y
insideTextField3.layer.backgroundColor = UIColor.white.cgColor
insideView2.addSubview(insideTextField3)
let insideLabel4 = UILabel()
insideLabel4.text = "Label"
insideLabel4.frame = CGRect(x: 60, y: 50, width: view.bounds.width, height: 30)
insideView2.addSubview(insideLabel4)
let insideTextField4 = UITextField()
insideTextField4.frame = CGRect(x: 200, y: 0, width: view.bounds.width - 240, height: 30)
insideTextField4.center.y = insideLabel4.center.y
insideTextField4.layer.backgroundColor = UIColor.white.cgColor
insideView2.addSubview(insideTextField4)
}
}