Horizontal Scroll View/Page Control using Buttons - ios

I've made a scroll view with page control using images (so far, so good)... I would like to use (3)buttons instead of images, and store the images in the button. So I can later create functions for each individual button. Having a hard time trying.
heres my code:
import UIKit
class AddImovelVC: UIViewController, UIScrollViewDelegate {
#IBOutlet weak var scrollImageView: UIScrollView!
#IBOutlet weak var pageControl: UIPageControl!
var imageArray = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
scrollImageView.delegate = self
imageArray = [UIImage(named:"0.png"), UIImage(named:"1.png"), UIImage(named:"2.png")] as! [UIImage]
for i in 0..<imageArray.count{
let imageView = UIImageView()
imageView.image = imageArray[i]
imageView.contentMode = .scaleToFill
let xPosition = self.view.frame.width * CGFloat(i)
imageView.frame = CGRect(x:xPosition, y:0, width: self.scrollImageView.frame.width, height: self.scrollImageView.frame.width)
scrollImageView.contentSize.width = scrollImageView.frame.width * CGFloat(i+1)
scrollImageView.addSubview(imageView)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func scrollViewDidScroll(_ scrollImageView: UIScrollView) {
pageControl.currentPage = Int(scrollImageView.contentOffset.x / CGFloat(375))
}
}

Just change the UIImageView for UIButton inside the for loop, like this
let i = 0
let button = UIButton()
button.setImage(imageArray[i], for: [])
button.imageView?.contentMode = .scaleToFill
let xPosition = self.view.frame.width * CGFloat(i)
button.frame = CGRect(x:xPosition, y:0, width: self.scrollImageView.frame.width, height: self.scrollImageView.frame.width)
scrollImageView.contentSize.width = scrollImageView.frame.width * CGFloat(i+1)
scrollImageView.addSubview(button)
if you want to execute something when the user taps the button, just add button.addTarget(self, action: #selector(nameOfYourFunction), for: .touchUpInside) after creating the button.

You can use UIButton instead of UIImageView.
To set the image, use:
button.setImage(image, for: .normal)
button.setBackgroundImage(image, for: .normal)
To retrieve the image, use:
button.currentImage
button.currentBackgroundImage

Related

Change UIImage on UIButton with separate Swift file if loop

Goal of the code:
To change a UIButton's UIImage that was already set on viewDidLoad() using an outside function that is not in viewDidLoad(), that is in an entirely separate swift file in the project.
I am however able to successfully change the UIImage of the UIButton by linking the button to a function that does the standard exampleButton.setImage(exampleButtonimage, for: .normal).
Code below:
class ViewController: UIViewController {
static let vcShared = ViewController()
var exampleButton = UIButton(frame: CGRect(x: 146, y: 140, width: 100, height: 50))
let exampleButtonimage = UIImage(named: "ExampleImage")
...
override func viewDidLoad() {
super.viewDidLoad()
exampleButton.setImage(exampleButtonimage , for: .normal)
}
}
Attempting to set UIButton's UIImage in the Second file:
let otherButtonimage = UIImage(named: "OtherImage")
if someVariable > 55000 {
ViewController.vcShared.exampleButton.setImage(otherButtonimage , for: .normal)
}
When the if criteria is met, the UIButton in viewDidLoad() does not change its image (I know the if criteria is met as I have a separate print("Hello World") in the if loop that consistently works.) However, nothing happens with the UIButton when the criteria is met.
Best practice is cosntruct delegate or observer pattern for that situation but the code below is going to work your code.
class ViewController: UIViewController {
static var exampleButton = UIButton(frame: CGRect(x: 146, y: 140, width: 100, height: 50))
let exampleButtonimage = UIImage(named: "ExampleImage")
...
override func viewDidLoad() {
super.viewDidLoad()
exampleButton.setImage(exampleButtonimage , for: .normal)}}
And where change code;
let otherButtonimage = UIImage(named: "OtherImage")
if someVariable > 55000 {
ViewController.exampleButton.setImage(otherButtonimage , for: .normal)}

How to make Horizontal scrollView and some buttons in it (programming)

sorry,I have a problem.I don't use storyBoard.
I want to make a view like this.
photo by terenceLuffy/AppStoreStyleHorizontalScrollView
but I try to do this.
Finlly,scrollView just show last button like this.
This is code:
var scView:UIScrollView = UIScrollView()
var buttonPadding:CGFloat = 10
var xOffset:CGFloat = 10
scView.backgroundColor = UIColor.blue
scView.translatesAutoresizingMaskIntoConstraints = false
func viewDidLoad() {
for i in 0 ... 10 {
let button = UIButton()
button.tag = i
button.backgroundColor = UIColor.darkGray
button.setTitle("\(i)", for: .normal)
button.addTarget(self, action: #selector(btnTouch), for: UIControlEvents.touchUpInside)
button.frame = CGRect(x: xOffset, y: CGFloat(buttonPadding), width: 70, height: 30)
xOffset = xOffset + CGFloat(buttonPadding) + button.frame.size.width
scView.addSubview(button)
}
scView.contentSize = CGSize(width: xOffset, height: scView.frame.height)
}
please help me.
Thanks all!
There are two ways of achieving it :) One the hard way using scrollView and calculating offset and setting views programmatically on ScrollView as subView else use CollectionView
Step 1:
Add a UICollectionView to storyboard, set the height of collectionView to match your requirement :)
Step 2
Create a cell, size of which depends on your requirement. I have created a cell with background colour orange/pink. Added a label on it to show your number.
Step 3:
Set the reusable cell identifier to the cell and set its class as well :)
Step 4 :
Set collectionView scroll direction to horizontal :)
Step 5:
Now implement collectionView delegates and data source methods :)
extension ViewController : UICollectionViewDataSource,UICollectionViewDelegate {
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "myCell", for: indexPath) as! MyCollectionViewCell
cell.myLabel.text = "ABCD"
return cell;
}
}
Thats all :)
Final O/P
Look at collectionView with cell ABCD :D
Additional Info
If you are dragging a collectionView on UIViewController, you might see that the collectionView leaves a gap at the top which you can solve by unchecking Adjust ScrollView Insets of ViewController :)
I have tried your code and changed it a bit. It works as expected, unless you have something other going on:
var scView:UIScrollView!
let buttonPadding:CGFloat = 10
var xOffset:CGFloat = 10
override func viewDidLoad() {
super.viewDidLoad()
scView = UIScrollView(frame: CGRect(x: 0, y: 120, width: view.bounds.width, height: 50))
view.addSubview(scView)
scView.backgroundColor = UIColor.blue
scView.translatesAutoresizingMaskIntoConstraints = false
for i in 0 ... 10 {
let button = UIButton()
button.tag = i
button.backgroundColor = UIColor.darkGray
button.setTitle("\(i)", for: .normal)
//button.addTarget(self, action: #selector(btnTouch), for: UIControlEvents.touchUpInside)
button.frame = CGRect(x: xOffset, y: CGFloat(buttonPadding), width: 70, height: 30)
xOffset = xOffset + CGFloat(buttonPadding) + button.frame.size.width
scView.addSubview(button)
}
scView.contentSize = CGSize(width: xOffset, height: scView.frame.height)
}
import UIKit
class ViewController: UIViewController {
var imageStrings:[String] = []
var myScrollView:UIScrollView!
#IBOutlet weak var previewView: UIImageView!
var scrollWidth : CGFloat = 320
let scrollHeight : CGFloat = 100
let thumbNailWidth : CGFloat = 80
let thumbNailHeight : CGFloat = 80
let padding: CGFloat = 10
override func viewDidLoad() {
super.viewDidLoad()
imageStrings = ["image01","image02","image03","image04","image05","image06","image07","image08"]
scrollWidth = self.view.frame.width
//setup scrollView
myScrollView = UIScrollView(frame: CGRectMake(0, self.view.frame.height - scrollHeight, scrollWidth, scrollHeight))
//setup content size for scroll view
let contentSizeWidth:CGFloat = (thumbNailWidth + padding) * (CGFloat(imageStrings.count))
let contentSize = CGSize(width: contentSizeWidth ,height: thumbNailHeight)
myScrollView.contentSize = contentSize
myScrollView.autoresizingMask = UIViewAutoresizing.FlexibleWidth
for(index,value) in enumerate(imageStrings) {
var button:UIButton = UIButton.buttonWithType(.Custom) as! UIButton
//calculate x for uibutton
var xButton = CGFloat(padding * (CGFloat(index) + 1) + (CGFloat(index) * thumbNailWidth))
button.frame = CGRectMake(xButton,padding, thumbNailWidth, thumbNailHeight)
button.tag = index
let image = UIImage(named:value)
button.setBackgroundImage(image, forState: .Normal)
button.addTarget(self, action: Selector("changeImage:"), forControlEvents: .TouchUpInside)
myScrollView.addSubview(button)
}
previewView.image = UIImage(named: imageStrings[0])
self.view.addSubview(myScrollView)
}
// Do any additional setup after loading the view, typically from a nib.
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func changeImage(sender:UIButton){
let name = imageStrings[sender.tag]
previewView.image = UIImage(named: name)
}
}
Its easy with minimal use of storyboard. You can avoid that rather easily. All you need are:
Scroll view
Horizontal stack view
Set the constraints of the above as shown in the project
A number of buttons - as many view controllers that need to be displayed.
A container view - this will be the view that will hold the active view controller.
Please refer to this project for some sample code:
https://github.com/equitronix/horizontalScrollMenu
//make that variable gloabl
let button = UIButton.init(type: .custom)
var arrMmenu : NSMutableArray = []
var selectedIndex : Int = 0
#IBOutlet weak var btnScrollView: UIScrollView!
var lineArray : NSMutableArray = []
var buttonArray : NSMutableArray = []
//Call buttonCreated()
//MARK:- Create an Horizontral LayOut
func buttonCreated()
{
btnScrollView.contentSize.width = 0
namesOfMenu = ["GMC","GPA","GTL"]
var scrollwidth: CGFloat = 10.0
for j in 0..<namesOfMenu.count
{
let name = namesOfMenu[j] as! String
let size : CGSize? = name.size(withAttributes : [NSAttributedStringKey.font : UIFont.systemFont(ofSize: 10.0)])
let textsize = CGSize(width : CGFloat(ceilf(Float(size!.width))), height : CGFloat(ceilf(Float(size!.height))))
var strikwidth : CGFloat = textsize.width
strikwidth = textsize.width + 30
let frame = CGRect(x: scrollwidth , y : CGFloat(7),width :CGFloat(strikwidth + 20) , height :CGFloat(20))
let frameLine = CGRect(x: scrollwidth , y : CGFloat(30),width :CGFloat(strikwidth + 20) , height :CGFloat(2))
let button = UIButton(type: .custom)
let line = UIView()
line.frame = frameLine
button.tag = j
view.tag = j
button.frame = frame
line .backgroundColor = UIColor.red
button.backgroundColor = UIColor.red
button.setTitleColor(UIColor.white, for: UIControlState.normal)
button.layer.borderColor = UIColor.white.cgColor
button.titleLabel?.textAlignment = .center
button.addTarget(self, action: #selector(self.buttonEvent(_:)), for: .touchUpInside)
button.setTitle(name, for : .normal)
scrollwidth = scrollwidth + strikwidth + 30
let strofMenu = namesOfMenu[selectedIndex] as! String
if (j == selectedIndex)
{
if(strofMenu == "GMC")
{
// apicall()
}
line.backgroundColor = hexStringToUIColor(hex: "#3174C7")
button.backgroundColor = UIColor.clear
button.setTitleColor(hexStringToUIColor(hex: "#3174C7"), for: UIControlState.normal)
}else
{
line.backgroundColor = UIColor.clear
button.backgroundColor = UIColor.clear
button.setTitleColor(MyConstant.Color.dark_gray_shade, for: UIControlState.normal)
}
button.titleLabel?.font = MyConstant.fontApp.Regular
buttonArray.add(button)
lineArray.add(line)
btnScrollView.addSubview(button)
btnScrollView.addSubview(line)
}
btnScrollView.contentSize = CGSize(width : CGFloat(scrollwidth), height : CGFloat(40.0))
btnScrollView.isPagingEnabled = false
btnScrollView.showsHorizontalScrollIndicator = false
btnScrollView.showsVerticalScrollIndicator = false
}
//MARK:- Button Event
#objc func buttonEvent(_ sender : UIButton)
{
let index = sender.tag
selectedIndex = index
let getRepoName = namesOfMenu[index] as! String
print(getRepoName)
for i in 0..<buttonArray.count
{
let buttonone : UIButton = (buttonArray[i] as! UIButton)
let line : UIView = (lineArray[i]) as! UIView
if i == selectedIndex
{
buttonone.backgroundColor = UIColor.clear
line.backgroundColor = hexStringToUIColor(hex: "#3174C7")
buttonone.setTitleColor(hexStringToUIColor(hex: "#3174C7"), for: .normal)
//
// if(getRepoName == "GMC")
// {
// clickedCellIndexes.add(0)
//
// arrmutablefordata.removeAllObjects()
// tblhome.reloadData()
// apicall()
// }
//buttonone.titleLabel
}else
{
buttonone.backgroundColor = UIColor.clear
line.backgroundColor = UIColor.clear
buttonone.setTitleColor(MyConstant.Color.dark_gray_shade, for: .normal)
}
}
}
Doing it from the storyboard using scroll view and stack views makes this a very simple solution. Along with a bunch of sub view controllers and transitions. I have posted sample code on GitHub. Please take a look here:
https://github.com/equitronix/horizontalScrollMenu
Let me know if this works.

Why am I unable to interact with my Button? Swift

I have the code below. I added a button and want something to happen when I press it, but it doesn't seem to work. In this case I want the system to print out "hi" and "hey". I can't seem to figure out the problem. Any help would be appreciated.
import UIKit
class ViewController: UIViewController, UIScrollViewDelegate {
var scrollView: UIScrollView!
var containerView = UIView()
override func viewDidLoad() {
super.viewDidLoad()
var buttonOne: UIButton!
buttonOne = UIButton(type: UIButtonType.System)
buttonOne.setTitle("Level 1", forState: UIControlState.Normal)
buttonOne.frame = CGRectMake(10, 50, 100, 100)
buttonOne.backgroundColor = UIColor.blueColor()
buttonOne.titleLabel?.font = UIFont.systemFontOfSize(17)
buttonOne.setTitleColor(UIColor.whiteColor(), forState: UIControlState.Normal)
buttonOne.addTarget(self, action: Selector("clicked:"), forControlEvents: UIControlEvents.TouchUpInside)
self.scrollView = UIScrollView()
self.scrollView.delegate = self
self.scrollView.contentSize = CGSizeMake(0, 1000)
containerView = UIView()
scrollView.addSubview(containerView)
view.addSubview(scrollView)
containerView.addSubview(buttonOne)
}
func clicked(sender: AnyObject){
NSLog("Hey")
print("hi")
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
scrollView.frame = view.bounds
containerView.frame = CGRectMake(0, 0, scrollView.contentSize.width, scrollView.contentSize.height)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
You have put the button in a scrollview. Here, the scrollview is a superview of the button and the width of the scrollview and its content size width must be greater than or equal to the button width to take action.
You are setting the containerView's width to 0 by setting its bounds size to the contentSize of the scrollview
self.scrollView.contentSize = CGSizeMake(0, 1000)
then
containerView.frame = CGRectMake(0, 0, scrollView.contentSize.width,
scrollView.contentSize.height)

Button in view not clicking ios swift

I'm trying to implement a dropdown menu in Swift by adding a view below the navigation bar and initially setting it to hidden until a navigationBarItem button is pressed, which works. In the dropdown View I have added two buttons as seen in the code below but it doesn't seem to pick up the event.
var isAnimating: Bool = false
var dropDownViewIsDisplayed : Bool = false
var dropDownView : UIView!
var buttonOne : UIButton!
var buttonTwo : UIButton!
var screenWidth : CGFloat!
#IBOutlet weak var searchNavigationBar: UINavigationItem!
override func viewDidLoad() {
super.viewDidLoad()
screenWidth = self.view.bounds.size.width
self.navigationController?.navigationBar.translucent = false
dropDownView = UIView(frame: CGRectMake(0, -15, screenWidth, -80))
dropDownView.hidden = true
dropDownView.userInteractionEnabled = true
self.navigationController?.view.insertSubview(self.dropDownView, belowSubview: (self.navigationController?.navigationBar)!)
buttonOne = UIButton(frame: CGRectMake(0, 0, screenWidth, 40))
buttonOne.setTitle("Button One", forState: .Normal)
buttonOne.setTitleColor(UIColor.blackColor(), forState: .Normal)
buttonOne.backgroundColor = UIColor.whiteColor()
buttonOne.addTarget(self, action: Selector("buttonOnePressed"), forControlEvents: UIControlEvents.TouchUpInside)
buttonOne.userInteractionEnabled = true
dropDownView.addSubview(buttonOne)
buttonTwo = UIButton(frame: CGRectMake(0, buttonOne.bounds.size.height, screenWidth, 40))
buttonTwo.setTitle("Button Two", forState: .Normal)
buttonTwo.setTitleColor(UIColor.blackColor(), forState: .Normal)
buttonTwo.backgroundColor = UIColor.whiteColor()
buttonTwo.addTarget(self, action: Selector("buttonTwoPressed"), forControlEvents: UIControlEvents.TouchUpInside)
buttonTwo.userInteractionEnabled = true
dropDownView.addSubview(buttonTwo)
}
func buttonTwoPressed(){
self.performSegueWithIdentifier("showLocation", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "showLocation") {
var location: LocationTableViewController = (segue.destinationViewController as? LocationTableViewController)!
}
}
Button click functions are not being called.
Are you using Swift 2.0 with Xcode 7? Just by quickly tried playing with your code like this, I found that the event handlers are being called properly without any big changes. Are you sure that there is nothing wrong somewhere else?
var isAnimating: Bool = false
var dropDownViewIsDisplayed : Bool = false
var dropDownView : UIView!
var buttonOne : UIButton!
var buttonTwo : UIButton!
var screenWidth : CGFloat!
#IBOutlet weak var searchNavigationBar: UINavigationItem!
override func viewDidLoad() {
super.viewDidLoad()
screenWidth = self.view.bounds.size.width
self.navigationController?.navigationBar.translucent = false
// I modified these 2 lines to test your code immediately
dropDownView = UIView(frame: CGRectMake(0, 65, screenWidth, 80))
dropDownView.hidden = false
dropDownView.userInteractionEnabled = true
self.navigationController?.view.insertSubview(self.dropDownView, belowSubview: (self.navigationController?.navigationBar)!)
buttonOne = UIButton(frame: CGRectMake(0, 0, screenWidth, 40))
buttonOne.setTitle("Button One", forState: .Normal)
buttonOne.setTitleColor(UIColor.blackColor(), forState: .Normal)
buttonOne.backgroundColor = UIColor.whiteColor()
buttonOne.addTarget(self, action: Selector("buttonOnePressed"), forControlEvents: UIControlEvents.TouchUpInside)
buttonOne.userInteractionEnabled = true
dropDownView.addSubview(buttonOne)
buttonTwo = UIButton(frame: CGRectMake(0, buttonOne.bounds.size.height, screenWidth, 40))
buttonTwo.setTitle("Button Two", forState: .Normal)
buttonTwo.setTitleColor(UIColor.blackColor(), forState: .Normal)
buttonTwo.backgroundColor = UIColor.whiteColor()
// Here I just wanted to show you that calling Selector() is not necessary at all
buttonTwo.addTarget(self, action: "buttonTwoPressed", forControlEvents: UIControlEvents.TouchUpInside)
buttonTwo.userInteractionEnabled = true
dropDownView.addSubview(buttonTwo)
}
// I didn't see this method in your code above so I added to test and it works!
func buttonOnePressed() {
print("buttonOnePressed")
}
// This is also being called normally
func buttonTwoPressed() {
print("buttonTwoPressed")
}
Can you please try with:
buttonOne.addTarget(self, action: Selector("buttonOnePressed:"), forControlEvents: UIControlEvents.TouchUpInside)
buttonTwo.addTarget(self, action: Selector("buttonTwoPressed:"), forControlEvents: UIControlEvents.TouchUpInside)
It won't works because it outside self.navigationController?.navigationBar.frame. You should add buttons on self.view or transparent modal view/UIWindow.

How to change Send button image in JSQMessagesController

How can I change JSQMessagesController "Send" button from just String to UIImageView?
Now it looks like:
Can I change this "Send" to image?
I've tried:
let sendButton = JSQMessagesInputToolbar()
sendButton.contentView?.rightBarButtonItem?.imageView?.image = UIImage(named: "send.png")
but I thing it's wrong, because it did not work =/
Create an UIButton and set it as the right bar button item of input toolbar.
let rightButton = UIButton(frame: CGRectZero)
let sendImage = UIImage(named: "send_button.png")
rightButton.setImage(sendImage, forState: UIControlState.Normal)
self.inputToolbar.contentView.rightBarButtonItemWidth = CGFloat(34.0)
self.inputToolbar.contentView.rightBarButtonItem = rightButton
Hope that helps!
No need to create another button, you can reuse the existing one:
override func viewDidLoad() {
super.viewDidLoad()
let imageWidth: CGFloat = 21
let image = UIImage(named: "image-name")
inputToolbar.contentView.rightBarButtonItemWidth = imageWidth
inputToolbar.contentView.rightBarButtonItem.setImage(image, for: .normal)
}
But if you want to have more control of the button, you should create a custom one:
override func viewDidLoad() {
super.viewDidLoad()
let buttonWidth = CGFloat(40)
let buttonHeight = inputToolbar.contentView.leftBarButtonContainerView.frame.size.height
let customButton = UIButton(frame: CGRect(x: 0, y: 0, width: buttonWidth, height: buttonHeight))
customButton.backgroundColor = .red
customButton.setImage(UIImage(named: "send-message"), for: .normal)
customButton.imageView?.contentMode = .scaleAspectFit
inputToolbar.contentView.rightBarButtonItemWidth = buttonWidth
inputToolbar.contentView.rightBarButtonItem = customButton
}
It can be set directly using the rightBarButtonItem. Your code is not working cause you are not setting the state of the button.
self.inputToolbar?.contentView.rightBarButtonItem?.setImage(UIImage(named: "send"), for: .normal)

Resources