import UIKit
class UpdateUsersManagmentViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func checkBoxTapped(_ sender:UIButton) {
UIView.animate(withDuration: 0.5, delay: 0.1, options: .curveLinear, animations: {
sender.transform = CGAffineTransform(scaleX: 0.1, y: 0.1)
}) { (success) in
sender.isSelected = !sender.isSelected
UIView.animate(withDuration: 0.5, delay: 0.1, options: .curveLinear, animations: {
sender.transform = .identity
}, completion: nil)
}
}
}
I would have a method that does that.
func toggleCheckmark(_ checkmark: UIButton) {
if checkmark == self.checkmark1 {
self.selectCheckmark1()
self.deselectCheckmark2()
} else if checkmark == self.checkmark2 {
self.selectCheckmark2()
self.deselectCheckmark1()
}
}
Another option is something like this:
func toggleCheckmark(_ checkmark: UIButton) {
self.selectCheckmark(self.checkmark1, on: checkmark == self.checkmark1)
self.selectCheckmark(self.checkmark2, on: checkmark == self.checkmark2)
}
If you want to select any of the one option from the group, it better to use radio buttons instead of check boxes.
If not, we should do it manually. I did it in swift and its working
#objc func selector(_ sender: NSButton)
{
if sender == checkBox1
{
if sender.state == .on && checkBox2.state == .on
{
checkBox2.state = .off
}
}
if sender == checkBox2
{
if sender.state == .on && checkBox1.state == .on
{
checkBox1.state = .off
}
}
}
Related
I want to make a 3d game on Xcode, SceneKit. To test it out, I started a simple project about a box, that if you tapped, moves in X direction. My question is how do you make the tap gesture work in a 3d game? I've been trying to add it but it just doesn't work. Here is all the code that I've written in case I'm doing something wrong:
import UIKit
import QuartzCore
import SceneKit
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let scene = SCNScene(named:"art.scnassets/Box.scn")
let newscene = self.view as! SCNView
newscene.scene = scene
let tap = UITapGestureRecognizer(target: self, action: #selector(taps(tap:)));newscene.addGestureRecognizer(tap)
tap.numberOfTapsRequired = 1
tap.numberOfTouchesRequired = 1
}
override var shouldAutorotate: Bool {
return true
}
override var prefersStatusBarHidden: Bool {
return true
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
if UIDevice.current.userInterfaceIdiom == .phone {
return .allButUpsideDown
} else {
return .all
}
}
#objc func taps(tap:UITapGestureRecognizer){
let newscene = self.view as! SCNView
let scene = SCNScene(named: "art.scnassets/Box.scn")
let box = scene?.rootNode.childNode(withName: "Box", recursively: true)
let place = tap.location(in: newscene)
let tapped = newscene.hitTest(place, options: [:])
if tapped.count > 0{
box?.runAction(SCNAction.repeatForever(SCNAction.moveBy(x: 5, y: 0, z: 0, duration: 1)))
}
}
}
Try this...
#objc func handleTap(recognizer: UITapGestureRecognizer)
{
if(data.isNavigationOff == true) { return } // No panel select if Add, Update, EndWave, or EndGame
if(gameMenuTableView.isHidden == false) { return } // No panel if game menu is showing
let location: CGPoint = recognizer.location(in: gameScene)
if(data.isAirStrikeModeOn == true)
{
let projectedPoint = gameScene.projectPoint(SCNVector3(0, 0, 0))
let scenePoint = gameScene.unprojectPoint(SCNVector3(location.x, location.y, CGFloat(projectedPoint.z)))
gameControl.airStrike(position: scenePoint)
}
else
{
let hitResults = gameScene.hitTest(location, options: hitTestOptions)
for vHit in hitResults
{
if(vHit.node.name?.prefix(5) == "Panel")
{
// May have selected an invalid panel or auto upgrade was on
if(gameControl.selectPanel(vPanel: vHit.node.name!) == false) { return }
return
}
}
}
}
If Airstrike - Tap drops a bomb on the screen where you touched, translating it to 3D
Else hittest looks for panels which may return multiple results
I am currently working on an animation project for an Apple Development class where we are moving and animating an ImageView. I can move the image, but I'm stumped on how to return it to the origin location, preferably using the same button.
Code for the move animation is as follows:
#IBAction func move(_ sender: Any) {
UIView.animate(withDuration: 1, animations: {self.imageView.frame.origin.y -= 200
}, completion: nil)
}
declare a variable that will hold the value of your y origin when the view loaded. and also declare a variable that will check if the imageview is currently animating or not.
var onLoadFrameYOrigin : CGFloat = 0.0
var isAnimating : Bool = false
override func viewDidLoad() {
super.viewDidLoad()
onLoadFrameYOrigin = self.searchView.frame.origin.y
}
#IBAction func move(_ sender: Any) {
if !isAnimating {
self.isAnimating = true
UIView.animate(withDuration: 1.0, animations: {
if self.onLoadFrameYOrigin == self.imageView.frame.origin.y {
self.imageView.frame.origin.y -= 200
} else {
self.imageView.frame.origin.y = onLoadFrameYOrigin
}
}) { _ in
self.isAnimating = false
}
}
}
Note : if you have make outlet of constraint of imageView then please
update constraint value during animation not frame.
1) make variable first
var isBack : Bool = false
Now in your button action :
#IBAction func move(_ sender: Any) {
if isBack == false
{
isBack = true
UIView.animate(withDuration: 1, animations: {self.imageView.frame.origin.y -= 200
}, completion: nil)
}
else
{
isBack = false
UIView.animate(withDuration: 1, animations: {self.imageView.frame.origin.y += 200
}, completion: nil)
}
}
What if the UILabel is in class A and the didTapRightutton that will animate it is in class B?
the percentDiscountLabel is in RandomizeDealsCollectionViewCell. This should animate into fade appear if I tap didTapRightutton which is in a different VC called RandomizeDealsViewController
How do I call the function that is inside RandomizeDealsCollectionViewCell to animate the percentDiscountLabel? Is there other way to do this?
class RandomizeDealsCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var percentDiscountLabel: UILabel!
func animatePercentDiscountLabel(deals: String) {
self.percentDiscountLabel.alpha = 0.6
self.percentDiscountLabel.isHidden = false
UIView.animate(withDuration: 0.6, delay: 0, options: .curveEaseInOut, animations: {
self.percentDiscountLabel.alpha = 1.0
}) { (isCompleted) in
}
percentDiscountLabel.text = deals
}
}
class RandomizeDealsViewController: UIViewController {
private var centeredCollectionViewFlowLayout: CenteredCollectionViewFlowLayout!
#IBAction func didTapRightButton(_ sender: Any) {
guard let indexCard = centeredCollectionViewFlowLayout.currentCenteredPage else { return }
if (indexCard > 0) {
centeredCollectionViewFlowLayout.scrollToPage(index: indexCard + 1, animated: true)
// should call the animation function here
}
}
}
If indexCard is indexPath of collectionViewCell which you want to animate,
You can call your cell like ->
in RandomizeDealsViewController
#IBAction func didTapRightButton(_ sender: Any) {
guard let indexCard = centeredCollectionViewFlowLayout.currentCenteredPage else { return }
if (indexCard > 0) {
centeredCollectionViewFlowLayout.scrollToPage(index: indexCard + 1, animated: true)
// should call the animation function here
let cell = collectionView!.cellForItemAtIndexPath(indexCard) as? RandomizeDealsCollectionViewCell
cell?.animatePercentDiscountLabel(deals: "deals")
}
}
Hi I want to give the PanGecture Swipe action for UIView on the top of UIViewControllers.for that one I write one common method in view controller extension but its make the entire viewcontroller is swipe.
I want to give the swipe action only for UIView please help to me any idea to change the following code to UIView Extension.
extension UIViewController{
#objc func pangectureRecognizerDismissoneScreen(_ sender: UIPanGestureRecognizer){
var initialTouchPoint: CGPoint = CGPoint(x: 0,y: 0)
let touchPoint = sender.location(in: self.view?.window)
if sender.state == UIGestureRecognizerState.began {
initialTouchPoint = touchPoint
} else if sender.state == UIGestureRecognizerState.changed {
if touchPoint.y - initialTouchPoint.y > 0 {
self.view.frame = CGRect(x: 0, y: touchPoint.y - initialTouchPoint.y, width: self.view.frame.size.width, height: self.view.frame.size.height)
}
} else if sender.state == UIGestureRecognizerState.ended || sender.state == UIGestureRecognizerState.cancelled {
if touchPoint.y - initialTouchPoint.y > 100 {
self.view.backgroundColor = UIColor.clear
self.dismiss(animated: true, completion: nil)
} else {
UIView.animate(withDuration: 0.3, animations: {
self.view.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: self.view.frame.size.height)
})
}
}
}
}
You can add this UIView extension
import UIKit
import RxSwift
struct AssociatedKeys {
static var actionState: UInt8 = 0
}
typealias ActionTap = () -> Void
extension UIView {
var addAction: ActionTap? {
get {
guard let value = objc_getAssociatedObject(self, &AssociatedKeys.actionState) as? ActionTap else {
return nil
}
return value
}
set {
objc_setAssociatedObject(self, &AssociatedKeys.actionState, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
self.tapWithAnimation()
}
}
func tapWithAnimation() {
self.gestureRecognizers?.removeAll()
let longTap = UILongPressGestureRecognizer(target: self, action: #selector(viewLongTap(_:)))
longTap.minimumPressDuration = 0.035
longTap.delaysTouchesBegan = true
self.addGestureRecognizer(longTap)
}
#objc
func viewLongTap(_ gesture: UILongPressGestureRecognizer) {
if gesture.state != .ended {
animateView(alpha: 0.3)
return
} else if gesture.state == .ended {
let touchLocation = gesture.location(in: self)
if self.bounds.contains(touchLocation) {
animateView(alpha: 1)
addAction?()
return
}
}
animateView(alpha: 1)
}
fileprivate func animateView(alpha: CGFloat) {
UIView.transition(with: self, duration: 0.3,
options: .transitionCrossDissolve, animations: {
self.subviews.forEach { subView in
subView.alpha = alpha
}
})
}
}
Example:
myView.addAction = {
print("click")
}
Use this class extension.
//Gesture extention
extension UIGestureRecognizer {
#discardableResult convenience init(addToView targetView: UIView,
closure: #escaping () -> Void) {
self.init()
GestureTarget.add(gesture: self,
closure: closure,
toView: targetView)
}
}
fileprivate class GestureTarget: UIView {
class ClosureContainer {
weak var gesture: UIGestureRecognizer?
let closure: (() -> Void)
init(closure: #escaping () -> Void) {
self.closure = closure
}
}
var containers = [ClosureContainer]()
convenience init() {
self.init(frame: .zero)
isHidden = true
}
class func add(gesture: UIGestureRecognizer, closure: #escaping () -> Void,
toView targetView: UIView) {
let target: GestureTarget
if let existingTarget = existingTarget(inTargetView: targetView) {
target = existingTarget
} else {
target = GestureTarget()
targetView.addSubview(target)
}
let container = ClosureContainer(closure: closure)
container.gesture = gesture
target.containers.append(container)
gesture.addTarget(target, action: #selector(GestureTarget.target(gesture:)))
targetView.addGestureRecognizer(gesture)
}
class func existingTarget(inTargetView targetView: UIView) -> GestureTarget? {
for subview in targetView.subviews {
if let target = subview as? GestureTarget {
return target
}
}
return nil
}
func cleanUpContainers() {
containers = containers.filter({ $0.gesture != nil })
}
#objc func target(gesture: UIGestureRecognizer) {
cleanUpContainers()
for container in containers {
guard let containerGesture = container.gesture else {
continue
}
if gesture === containerGesture {
container.closure()
}
}
}
}
EDIT 1 :-
Use like this
UIGestureRecognizer.init(addToView: yourView, closure: {
// your code
})
I am facing an issue, whenever I going to type in ALTextInputBar() there is a space between keyboard and ALTextInputBar() of 44 points. I don't know from where it is coming. Please have a look on code and image.
#IBOutlet weak var viewChatBox: UIView!
#IBOutlet weak var viewChatBoxBottomConstraint: NSLayoutConstraint!
let textInputBar = ALTextInputBar()
let keyboardObserver = ALKeyboardObservingView()
override func viewDidLoad() {
super.viewDidLoad()
IQKeyboardManager.shared.enable = false
IQKeyboardManager.shared.enableAutoToolbar = false
configureView()
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChangeFrame), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if #available(iOS 11, *) {
// safe area constraints already set
}
else {
if (!(self.topLayoutConstraint != nil)) {
topLayoutConstraint = viewTopBar.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor)
self.topLayoutConstraint?.isActive = true
}
if (!(self.bottomLayoutConstraint != nil)) {
// bottomLayoutConstraint = viewChatBox.bottomAnchor.constraint(equalTo: bottomLayoutGuide.topAnchor)
self.bottomLayoutConstraint?.isActive = true
}
}
}
func configureInputBar () {
btnChat = UIButton(frame: CGRect(x: 0, y: 0, width: 36, height: 36))
keyboardObserver.isUserInteractionEnabled = false
textInputBar.showTextViewBorder = true
textInputBar.leftView = nil
textInputBar.rightView = btnChat
textInputBar.alwaysShowRightButton = true
textInputBar.delegate = self
textInputBar.textView.autocorrectionType = .yes
textInputBar.backgroundColor = UIColor(white: 0.95, alpha: 1)
textInputBar.keyboardObserver = keyboardObserver
viewChatBox.addSubview(textInputBar)
applyConstraintToChatBox()
self.view.layoutIfNeeded()
}
func applyConstraintToChatBox() {
textInputBar.translatesAutoresizingMaskIntoConstraints = false
viewChatBox.translatesAutoresizingMaskIntoConstraints = false
let views = ["textView": textInputBar]
let hConstraints = NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[textView]-0-|", options: [], metrics: nil, views: views)
let vConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[textView]-0-|", options: [], metrics: nil, views: views)
viewChatBox.addConstraints(hConstraints)
viewChatBox.addConstraints(vConstraints)
}
override var inputAccessoryView: UIView? {
get {
return keyboardObserver
}
}
override var canBecomeFirstResponder: Bool {
return true
}
//MARK: - TEXTVIEW DELEGATE
func textView(textView: ALTextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
if (textInputBar.text.count == 0) {
return true
}
let newLength = textInputBar.text.count + text.count - range.length
return (newLength <= 144);
}
func inputBarDidChangeHeight(height: CGFloat) {
UIView.animate(withDuration: 0.3, delay: 0.0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.7, options: [.curveLinear], animations: { () -> Void in
self.view.layoutIfNeeded()
}, completion: nil)
}
// MARK: - KEYBOARDS
#objc func keyboardWillChangeFrame(notification: Notification) {
let endFrame = ((notification as NSNotification).userInfo![UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
viewChatBoxBottomConstraint.constant = view.bounds.height - endFrame.origin.y
print("CHAT BOX FRAME: \(viewChatBox.frame)")
print("TEXT FRAME FRAME: \(textInputBar.frame)")
self.view.layoutIfNeeded()
}
Late answer but may help someone. I had the same issue and found this below code in the documentation.
Only helpful for IQKeyboardManager users.
IQKeyboardManager
self.textField.keyboardDistanceFromTextField = 8; //This will modify default distance between textField and keyboard. For exact value, please manually check how far your textField from the bottom of the page. Mine was 8pt.