I have made a draggable button
let buttonGesture = UIPanGestureRecognizer(target: self, action: #selector(draggedButton(_:)))
menuButton.isUserInteractionEnabled = true
menuButton.addGestureRecognizer(buttonGesture)
When the button drag to certain position, image will be changed.
#objc func draggedButton(_ sender:UIPanGestureRecognizer){
self.view.bringSubview(toFront: menuButton)
let translation = sender.translation(in: self.view)
menuButton.center = CGPoint(x: menuButton.center.x + translation.x, y: menuButton.center.y + translation.y)
sender.setTranslation(CGPoint.zero, in: self.view)
if(menuButton.center.x < 100){
menuButton.setImage(UIImage(named: "newimage"), for: UIControlState.normal)
}
}
But after setImage, button will reset position, how to prevent this?
Try setting button background image instead of button image. Since setting image will rescale its position.
I had same problem and heres my solution:
unset the image, make button blank with no graphics in it
create new UIImageView including your UIImages, for initial and second state
in viewDidLoad() in UIViewController set UIImageView.bounds = UIButton.bounds set the initial image
call UIButton.addSubview(UIImageView)
in your method where you are using UIButton.setImage() call UIImageView.image = UIImage
Heres an example:
class VC : UIViewController{
let image_initial : UIImage = UIImage("img_1")
let image_second : UIImage = UIImage("img_2")
let imageview_menu : UIImageView = UIImageView()
#IBOutlet weak var button_menu: UIButton!
override func viewDidLoad(){
super.viewDidLoad()
//...
self.imageview_menu.bounds = button_menu.bounds
self.imageview_menu.image = image_initial
self.button_menu.addSubview(imageview_menu)
//...
}
#objc func draggedButton(_ sender:UIPanGestureRecognizer){
//...your code
if(menuButton.center.x < 100){
imageview_menu.image = image_second
}
}
}
Hope this helps if you haven't found solution. :)
Related
Hi i'm making an app where you can decorate a Christmas tree with baubles i have wrote code to be able to drag it around the view but i run out of baubles how do i make it so i can have lots of baubles to put on the christmas tree. I have tried duplicating one bauble lots of times but then added them all to the code and it doesn't work it drags them all at the same time. If you look in the picture it has the bauble in it but i want it to drag one but one to still be there to put on
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var red_bauble_1: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
let gesture = UIPanGestureRecognizer(target: self, action: #selector(ViewController.wasDragged(_ :)))
red_bauble_1.addGestureRecognizer(gesture)
red_bauble_1.isUserInteractionEnabled = true
}
#objc func wasDragged (_ gesture: UIPanGestureRecognizer) {
let translation = gesture.translation(in: self.view)
let red_bauble_1 = gesture.view
red_bauble_1?.center = CGPoint(x: red_bauble_1!.center.x + translation.x, y: (red_bauble_1?.center.y)! + translation.y)
gesture.setTranslation(CGPoint.zero, in: self.view)
}
}
If you are adding a variable number of ornaments as subviews and want to keep a reference to them, just have an array for them, e.g.
var ornaments = [UIView]() // or, if they're image views, `[UIImageView]()`
then you can add your ornaments to that array as you add them to your tree and you have an array to keep track of all of them.
For example:
class ViewController: UIViewController {
#IBOutlet weak var treeImageView: UIImageView!
#IBOutlet weak var ornamentToolImageView: UIImageView!
private var currentOrnament: UIView!
private var ornaments = [UIView]()
override func viewDidLoad() {
super.viewDidLoad()
let pan = UIPanGestureRecognizer(target: self, action: #selector(dragOrnamentFromToolbar(_:)))
ornamentToolImageView.addGestureRecognizer(pan)
}
/// Gesture for dragging ornament from toolbar on to the tree
///
/// This creates new ornament and adds it to view hierarchy as well as to our array of `ornaments`
#IBAction func dragOrnamentFromToolbar(_ gesture: UIPanGestureRecognizer) {
let location = gesture.location(in: treeImageView)
switch gesture.state {
case .began:
gesture.view?.isHidden = true // temporarily hide toolbar view so it feels like we're dragging it
let image = UIImage(named: "ornament")!
currentOrnament = UIImageView(image: image)
ornaments.append(currentOrnament)
treeImageView.addSubview(currentOrnament)
fallthrough
case .changed:
currentOrnament.center = location
case .ended, .cancelled:
// when done, add new pan gesture for dragging around new ornament
gesture.view?.isHidden = false // restore toolbar view
currentOrnament.isUserInteractionEnabled = true
let pan = UIPanGestureRecognizer(target: self, action: #selector(dragExistingOrnament(_:)))
currentOrnament.addGestureRecognizer(pan)
currentOrnament = nil
default:
break
}
}
/// Gesture for dragging existing ornament
///
/// This grabs existing and allows you to drag it around
#IBAction func dragExistingOrnament(_ gesture: UIPanGestureRecognizer) {
let location = gesture.location(in: treeImageView)
switch gesture.state {
case .began:
currentOrnament = gesture.view
fallthrough
case .changed:
currentOrnament.center = location
default:
break
}
}
}
That yields:
I have an array of images if I pressed the button the image will randomly appear. and there is an image down also called from the array but it appears randomly just once I opened the game. I want to do a conditions statement for button pressed. like I have 5 conditions once the button clicked: 1- if pressed and the image appeared is not same as the UIIMage view down score will be added
2- if button did not press for 2 seconds will appear down.
3- if button pressed and it is same as the UIimage so game over.
4- If he calculated 4 images down because he didn't hit the image in 2 seconds he will lose.
var array:[UIImage] = [UIImage(named: "1.png")!,
UIImage(named: "2.png")!,
UIImage(named: "3.png")!,
UIImage(named: "4.png")!,
UIImage(named: "5.png")!,
UIImage(named: "6.png")!,
UIImage(named: "7.png")!,
UIImage(named: "8.png")!,
UIImage(named: "9.png")!,
UIImage(named: "10.png")!]
var random = arc4random_uniform(10)
#IBAction func myButtonPressed(button: UIButton) {
var randomNum: UInt32 = 10
randomNum = arc4random_uniform(UInt32(array.count))
myButton.setImage(UIImage(named: "bird\(randomNum).png"), for: UIControlState.normal)
// myButton.setImage(UIImage(named: "\(randomNum).png"), for: UI)
self.myImage.animationImages = array
let buttonWidth = myButton.frame.width
let buttonHeight = myButton.frame.height
// Find the width and height of the enclosing view
let viewWidth = myButton.superview!.bounds.width
let viewHeight = myButton.superview!.bounds.height
// Compute width and height of the area to contain the button's center
let xwidth = viewWidth - buttonWidth
let yheight = viewHeight - buttonHeight
// Generate a random x and y offset
let xoffset = CGFloat(arc4random_uniform(UInt32(xwidth)))
let yoffset = CGFloat(arc4random_uniform(UInt32(yheight)))
// Offset the button's center by the random offsets.
myButton.center.x = xoffset + buttonWidth / 2
myButton.center.y = yoffset + buttonHeight / 2
/* for i in array{
if myButton != myImage{
randomNum = arc4random_uniform(UInt32(array.count))
}
if else
} */
}
Perhaps you could try something like this. As for your first condition, what is your UIImage View Variable. Is it another UIImage View that is being displayed on the storyboard?
import UIKit
class ViewController: UIViewController {
var array: [UIImage] = [UIImage(named: "1.png")!,
UIImage(named: "2.png")!,
UIImage(named: "3.png")!,
UIImage(named: "4.png")!,
UIImage(named: "5.png")!]
#IBOutlet weak var myButton: UIButton!
var pressed: Bool = false;
var score: Int = 0;
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//2nd Condition: if button did not press for 2 seconds will appear down
if(pressed == false){
Timer.scheduledTimer(timeInterval: 0.2, target: self, selector: #selector(ViewController.doSomething), userInfo: nil, repeats: true)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func isPressed(_ sender: UIButton) {
pressed = true;
var randomNum: UInt32 = 10
randomNum = arc4random_uniform(UInt32(array.count));
myButton.setImage(UIImage(named: "\(randomNum).png"), for: .normal)
// 1st Condition: if pressed and the image appeared is not same as the UIIMage view down score will be added
if( UIImage(named: "\(randomNum).png") != myButton.currentImage){
//Add View Down Score
score += 1;
}
// 3rd Condition: if button pressed and it is same as the UIimage so game over
else{
// Game Over
}
}
func doSomething() {
// Not sure what you mean by will appear down
print("Action")
}
}
I am not quite sure what your 4th condition does. Please clarify
I am very new to swift. I am implementing the functionality for click event for UIIMageview. My Code is below.
override func viewDidLoad() {
super.viewDidLoad()
initialize()
let logout = UIImage(named: "logout.png")
let location = UIImage(named:"location.png")
let appIcon = UIImage(named: "logo.png")
imgLogout.image = logout
imgLocation.image = location
appicon.image = appIcon
// Do any additional setup after loading the view, typically from a nib.
imgLogout.isUserInteractionEnabled = true
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(ProductListController.profileImageHasBeenTapped(gesture:)))
//this is where we add the target, since our method to track the taps is in this class
//we can just type "self", and then put our method name in quotes for the action parameter
//finally, this is where we add the gesture recognizer, so it actually functions correctly
imgLogout.addGestureRecognizer(tapGestureRecognizer)
}
func profileImageHasBeenTapped(gesture: UIGestureRecognizer){
print("Triggered")
}
my click event is not triggered. Any body can help me from this.
Any will be appreciated.
XCode version is 8.3.3
Swift version is 3.1
Why not using a UIButton, that is designed for that kind of usage ?
let logout = UIButton(type: .custom)
logout.setImage(UIImage(named: "logout.png"), forState: .normal)
logout.addTarget(self, action: #selector(self.performLogout), for: .touchUpInside)
#objc
func performLogout() {
// Do something
}
It seems like yourchildview not in the front so try it:
yourparentview.bringSubview(toFront: imgLogout)
imageLogOut frame may be out of super view's bounds, please check it.use
self.profileImageHasBeenTapped(gesture:)
instead of
ProductListController.profileImageHasBeenTapped(gesture:)
set user interaction enabled for the image.
// for creating tap gesture recognizer
#IBOutlet weak var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
// create tap gesture recognizer
let tapGesture = UITapGestureRecognizer(target: self, action: "imageTapped:")
// add it to the image view;
imageView.addGestureRecognizer(tapGesture)
// make sure imageView can be interacted with by user
imageView.userInteractionEnabled = true
//if tap is not working bring image to front view
self.view.bringSubview(imageView)
}
func imageTapped(gesture: UIGestureRecognizer) {
// if the tapped view is a UIImageView then set it to imageview
if let imageView = gesture.view as? UIImageView {
println("Image Tapped")
//Here you can initiate your new ViewController
}
}
}
I am new to Swift and I am looking for a way to move my image to other view controller with double tap.
I made my image into scroll view, so I can slide to view it.
Here is my code.
class Quotes: UIViewController, UIScrollViewDelegate {
#IBOutlet weak var scroll: UIScrollView!
let imageview = ["quotes1","quotes2","quotes3","quotes4"]
var imagine = UIImageView()
override func viewDidLoad() {
let tap = UITapGestureRecognizer(target: self, action: #selector(doubletap))
tap.numberOfTapsRequired = 2
view.addGestureRecognizer(tap)
self.navigationController?.setNavigationBarHidden(true, animated: true)
quotesimageload()
}
func quotesimageload() {
for index in 0 ... imageview.count - 1
{
imagine = UIImageView (frame:CGRect(x: self.scroll.frame.width * CGFloat(index), y: 0 , width: self.scroll.frame.width, height: self.scroll.frame.height))
imagine.image = UIImage(named : imageview[index])
imagine.tag = index
imagine.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.scroll.addSubview(imagine)
}
self.scroll.contentSize = CGSize(width: self.scroll.frame.width * CGFloat(imageview.count), height: self.scroll.frame.height)
}
func doubletap(){
let view = self.storyboard?.instantiateViewController(withIdentifier: "pinch")
self.navigationController?.pushViewController(view!, animated: true)
}
}
You don't exactly move the image to another view controller - you pass a copy of it to the target VC.
Set up a "var" UIImage in the secondVC (let's say you called it image) and before you push that VC into view, populate it from the first VC.
One more word of caution - naming a UIViewController as "view" can be very confusing, as many would think it's a UIView. So assuming you rename that to be pinchViewController, the full syntax would be:
Second VC:
var image:UIView!
First VC:
func doubletap(){
let pinchViewController = self.storyboard?.instantiateViewController(withIdentifier: "pinch")
pinchViewController.image = imagine.image
self.navigationController?.pushViewController(view!, animated: true)
}
And if you have things properly coded and/or wired up in IB, you should have you UIImageView in the second VC displaying the image.
i have a test project that takes text from a file, adds it to a textview and displays it.
i want to add some gestures but cannot seem to make it work...
here is the relevant code:
class ViewController2: UIViewController, UIGestureRecognizerDelegate {
#IBOutlet var textview1: UITextView!
var pinchGesture = UIPinchGestureRecognizer()
override func viewDidLoad() {
super.viewDidLoad()
self.textview1.userInteractionEnabled = true
self.textview1.multipleTouchEnabled = true
self.pinchGesture.delegate = self
self.pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(ViewController2.pinchRecognized(_:)))
self.view.addGestureRecognizer(self.pinchGesture)
}
#IBAction func pinchRecognized(pinch: UIPinchGestureRecognizer) {
self.textview1.addGestureRecognizer(pinchGesture)
self.textview1.transform = CGAffineTransformScale(self.textview1.transform, pinch.scale, pinch.scale)
pinch.scale = 1.0
}
any ideas? followed several tutorials but none seem to help. code is tested on actual iPhone...
thanks a lot
Edit for Solution:
#IBAction func pinchRecognized(pinch: UIPinchGestureRecognizer) {
var pinchScale = pinchGesture.scale
pinchScale = round(pinchScale * 1000) / 1000.0
if (pinchScale < 1) {
self.textview1.font = UIFont(name: self.textview1.font!.fontName, size: self.textview1.font!.pointSize - pinchScale)
pinchScale = pinchGesture.scale
} else {
self.textview1.font = UIFont(name: self.textview1.font!.fontName, size: self.textview1.font!.pointSize + pinchScale)
pinchScale = pinchGesture.scale
}
}
thanks to nishith Singh
Try adding the gesture recogniser to your textview in viewDidLoad instead of adding it in pinchRecognized. Currently you are adding the pinchGesture to your view which is behind your text view and hence will not receive the touch
var pinchGesture = UIPinchGestureRecognizer()
Use this code:
override func viewDidLoad() {
super.viewDidLoad()
self.textview1.userInteractionEnabled = true
self.textview1.multipleTouchEnabled = true
self.pinchGesture = UIPinchGestureRecognizer(target: self, action:#selector(pinchRecognized(_:)))
self.textview1.addGestureRecognizer(self.pinchGesture)
// Do any additional setup after loading the view.
}
#IBAction func pinchRecognized(_ pinch: UIPinchGestureRecognizer) {
let fontSize = self.textview1.font!.pointSize*(pinch.scale)/2
if fontSize > 12 && fontSize < 32{
textview1.font = UIFont(name: self.textview1.font!.fontName, size:fontSize)
}
}
You might have to hit and trial with the minimum and maximum font sizes as you want, right now the minimum font size is 12 and the maximum font size is 32.
let pinchGesture = UIPinchGestureRecognizer(target: self, action:#selector(self.pinchGesture))
func pinchGesture(sender: UIPinchGestureRecognizer){
sender.view?.transform = (sender.view?.transform)!.scaledBy(x: sender.scale, y: sender.scale)
sender.scale = 1
print("pinch gesture")
}
class ViewController2: UIViewController, UIGestureRecognizerDelegate {
#IBOutlet var textview1: UITextView!
var pinchGesture = UIPinchGestureRecognizer()
override func viewDidLoad() {
super.viewDidLoad()
self.textview1.userInteractionEnabled = true
self.textview1.multipleTouchEnabled = true
self.pinchGesture.delegate = self
self.pinchGesture = UIPinchGestureRecognizer(target: self, action: "pinchRecognized:")
self.view.addGestureRecognizer(self.pinchGesture)
}
func pinchRecognized(pinch: UIPinchGestureRecognizer) {
self.textview1.addGestureRecognizer(pinchGesture)
self.textview1.transform = CGAffineTransformScale(self.textview1.transform, pinch.scale, pinch.scale)
pinch.scale = 1.0
}
Your code is actually working. But not the way you want probably.
Initially you assigned the gesture recogniser to the view of view controller.
But then inside the method you added same gesture recogniser to the UITextView.
So it should be working on UITextView. And the gesture recogniser is removed from the view controller's view. Gesture recogniser can only have one target. Pick view controller's view or textview.
You set the delegate of self.pinchGesture before initialising.
Initialise the self.pinchGesture first.
Set the delegate.
Add self.pinchGesture to self.view
self.pinchGesture.delegate = self
self.pinchGesture = UIPinchGestureRecognizer(target: self, action:#selector(ViewController2.pinchRecognized(_:)))
self.view.addGestureRecognizer(self.pinchGesture)