there is a UIButton in view controller and when button clicked , UIButton move with random position in View Controller . The question it is how i can make disable movable ability when clicked again on button ?
this is moveable Method :
func randomPosition() {
self.movable_Button.layer.cornerRadius = 10
let buttonWidth = movable_Button.frame.width
let buttonHeight = movable_Button.frame.height
let viewWidth = movable_Button.superview!.bounds.width
let viewHeight = movable_Button.superview!.bounds.height
let xwidth = viewWidth - buttonWidth
let yheight = viewHeight - buttonHeight
let xPosition = CGFloat(arc4random_uniform(UInt32(xwidth)))
let yPosition = CGFloat(arc4random_uniform(UInt32(yheight)))
movable_Button.center.x = xPosition + buttonWidth / 2
movable_Button.center.y = yPosition + buttonHeight / 2
}
I think you have programmed something like
func onButtonClicked() {
randomPosition()
}
so you can make a new variable:
var clickedButton = false
func onButtonClicked() { // i know this is not the correct function, but i think you know what i mean ;)
if clickedButton == false {
randomPosition()
} else {
clickedButton = true
}
}
Related
I have this:
Created via this piece of code:
// Add hashtag collection to a post
func addHashtags(container: UIView, constraint: NSLayoutConstraint) -> Void {
let screenSize: CGRect = UIScreen.main.bounds
let screenWidth = screenSize.width - 16 - 16
var currentOriginX: CGFloat = 0
var currentOriginY: CGFloat = 0
for j in 0..<self.pseudo.count {
if currentOriginY < 144 {
// Create a new label
let labelHashtag = RoundedLabel()
labelHashtag.rounded = true
tagLabels.append(labelHashtag)
print(tagLabels.count)
// Set its properties (title, colors, corners, etc)
labelHashtag.text = pseudo[j] as? String
labelHashtag.font = UIFont.systemFont(ofSize: 12, weight: .semibold)
labelHashtag.textAlignment = .center
labelHashtag.textColor = UIColor.black
labelHashtag.backgroundColor = UIColor.white
labelHashtag.layer.borderColor = UIColor(red:0.88, green:0.88, blue:0.88, alpha:1.0).cgColor
labelHashtag.layer.borderWidth = 1
// Set its frame width and height
labelHashtag.frame.size.width = labelHashtag.intrinsicContentSize.width + tagPadding
labelHashtag.frame.size.height = tagHeight
// Add it to the scroll view
container.addSubview(labelHashtag)
// If current X + label width will be greater than container view width
// .. move to next row
if (currentOriginX + labelHashtag.frame.width > screenWidth) {
tagLabels[0].textColor = .red
print("übrig")
print(screenWidth - currentOriginX)
currentOriginX = 0
currentOriginY += tagHeight + tagSpacingY
}
// Set the btn frame origin
labelHashtag.frame.origin.x = currentOriginX
labelHashtag.frame.origin.y = currentOriginY
// Increment current X by btn width + spacing
currentOriginX += labelHashtag.frame.width + tagSpacingX
} else if currentOriginY == 90 {
}
// Update container view height
constraint.constant = currentOriginY + tagHeight
}
container.layoutIfNeeded()
}
I want to center all items in each row. I imagine I have to calculate the remaining width of my UIView and add a margin to the first item.
How can I add a margin to my UILabel? I can access it via tagLabels[0] and I think I know how to calculate the remaining width, but I don't know how I can add the margin to it.
On my users profile page, there is a scrollview users slide across to see more photos. Everything works with adding the photos but the problem is that each image added to the scrollviews subview, is added twice. This is the code I am using to populate the scrollview. I currently have an Imageview embed inside the scrollview on storyboard and use that as the default if user has no photos. The at the bottom should show the bug. I have tried using a combination of clipstobounds, scaleaspectfit, and setting background color to clear but nothing stops from showing an additional image in the background. Any ideas would be appreciated. On a side note, the bug is only noticed on the iphone 8 plus
var pages: Int = 1
var numPhotos: CGFloat = 1
var position: CGFloat = 1
let scrollWidth: CGFloat = profileImage.frame.width
let scrollHeight: CGFloat = profileImage.frame.height
let scrollY: CGFloat = profileImage.frame.origin.y
if let profileImg = user.profileImage {
profileResource = ImageResource(downloadURL: URL(string: profileImg)!, cacheKey: profileImg)
profileImage.kf.setImage(with: profileResource)
} else {
profileImage.image = #imageLiteral(resourceName: "requests_icon")
}
nameLbl.text = user.fullName
influenceLbl.text = "\(user.score)"
followersLbl.text = "\(user.followers)"
followingLbl.text = "\(user.following)"
if let image1 = user.photo1 {
let imageOne = UIImageView(frame: CGRect(x: scrollWidth * position, y: scrollY, width: scrollWidth, height: scrollHeight))
imageOne.contentMode = .scaleAspectFit
photo1Resource = ImageResource(downloadURL: URL(string: image1)!, cacheKey: image1)
imageOne.kf.setImage(with: photo1Resource)
pages = pages + 1
numPhotos = numPhotos + 1
position = position + 1
scrollView.addSubview(imageOne)
} else {
}
if let image2 = user.photo2 {
let imageTwo = UIImageView(frame: CGRect(x: scrollWidth * position, y: scrollY, width: scrollWidth, height: scrollHeight))
imageTwo.contentMode = .scaleAspectFit
photo2Resource = ImageResource(downloadURL: URL(string: image2)!, cacheKey: image2)
imageTwo.kf.setImage(with: photo2Resource)
pages = pages + 1
numPhotos = numPhotos + 1
position = position + 1
scrollView.addSubview(imageTwo)
} else {
}
if let image3 = user.photo3 {
let imageThree = UIImageView(frame: CGRect(x: scrollWidth * position, y: scrollY, width: scrollWidth, height: scrollHeight))
imageThree.contentMode = .scaleAspectFit
photo3Resource = ImageResource(downloadURL: URL(string: image3)!, cacheKey: image3)
imageThree.kf.setImage(with: photo3Resource)
pages = pages + 1
numPhotos = numPhotos + 1
position = position + 1
scrollView.addSubview(imageThree)
} else {
}
scrollView.contentSize = CGSize(width: profileImage.frame.width * numPhotos, height: scrollHeight)
scrollView.delegate = self
scrollView.contentMode = .scaleAspectFit
scrollView.clipsToBounds = true
pageControl.numberOfPages = pages
pageControl.currentPage = 0
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView){
let pageWidth:CGFloat = scrollView.frame.width
let currentPage:CGFloat = floor((scrollView.contentOffset.x-pageWidth/2)/pageWidth) + 1
self.pageControl.currentPage = Int(currentPage)
}
I am trying to update my score label at the end of the game. Since the variable (seems to be) outside of the scope I figured I would just remove the label and make a new one in the adjust function. I am not familiar with swift and would appreciate help. Can I just reposition or do I have to create new label? Cant figure it out. Thanks
func loadScore() {
let scoreBand = SKLabelNode(fontNamed: "Arial")
scoreBand.name = StickHeroGameSceneChildName.ScoreName.rawValue
scoreBand.text = "0"
scoreBand.position = CGPointMake(0, DefinedScreenHeight / 2 - 200)
scoreBand.fontColor = SKColor.whiteColor()
scoreBand.fontSize = 100
scoreBand.zPosition = StickHeroGameSceneZposition.ScoreZposition.rawValue
scoreBand.horizontalAlignmentMode = .Center
addChild(scoreBand)
}
func adjustScore() {
//var scoreBand = scoreBand
scoreBand.position = CGPointMake(0, DefinedScreenHeight / 2 - 100)//doesnt recognize scoreBand
}
You can reposition, just declare scoreBand as a variable of your containing class. For example:
class SomeClass: SKSpriteNode {
var scoreBand: SKLabelNode!
override init(size: CGSize) {
scoreBand = SKLabelNode(fontNamed: "Arial")
super.init(size: size)
anchorPoint = CGPointMake(0.5, 0.5)
physicsWorld.contactDelegate = self
}
func loadScore() {
scoreBand.name = StickHeroGameSceneChildName.ScoreName.rawValue
scoreBand.text = "0"
scoreBand.position = CGPointMake(0, DefinedScreenHeight / 2 - 200)
scoreBand.fontColor = SKColor.whiteColor()
scoreBand.fontSize = 100
scoreBand.zPosition = StickHeroGameSceneZposition.ScoreZposition.rawValue
scoreBand.horizontalAlignmentMode = .Center
addChild(scoreBand)
}
func adjustScore() {
scoreBand.position = CGPointMake(0, DefinedScreenHeight / 2 - 100)
}
}
I'm the author of a Hearthstone tracker, and I have to move several NSWindow over Hearthstone window.
I get the frame of Hearthstone using CGWindowListCopyWindowInfo.
Then, I have to move my windows at some positions relative to Hearthstone.
The red arrows are over opponent cards, green arrow is over turn button and blue arrows are at the left and right of the window.
My actual screen setup is the following :
which gives me the following frames
// screen 1 : {x 0 y 0 w 1.440 h 900}
// screen 2 : {x 1.440 y -180 w 1.920 h 1.080}
To place the opponent tracker (the left frame) at the right position, which is the most simple case, I use {x 0 y somepadding w 185 h hearthstoneHeight - somepadding} and get the correct frame with this
func relativeFrame(frame: NSRect) -> NSRect {
var relative = frame
relative.origin.x = NSMinX(hearthstoneFrame) + NSMinX(frame)
relative.origin.y = NSMinY(hearthstoneFrame) + NSMinY(frame)
return relative
}
The right tracker is placed using {x hearthstoneWidth - trackerWidth, ...}
For other overlays, I used my current (Hearthstone) resolution to place them and them calculate them using a simple math
x = x / 1404.0 * NSWidth(hearthstoneFrame)
y = y / 840.0 * NSHeight(hearthstoneFrame)
This works pretty well. Except if I use my second screen. In this case, the frames seems to be correct, but the position of the window is not good.
Here is a screenshot of a debug window with {x 0 y 0 w hearthstoneWidth h hearthsoneHeight }. If I compare the frames of Hearthstone and my overlay, they are identical.
The complete function is the following (I'm in a "static class", I only show revelant code). I guess I'm missing something in the calculation but I can't find what.
class frameRelative {
static var hearthstoneFrame = NSZeroRect
static func findHearthstoneFrame() {
let options = CGWindowListOption(arrayLiteral: .ExcludeDesktopElements)
let windowListInfo = CGWindowListCopyWindowInfo(options, CGWindowID(0))
if let info = (windowListInfo as NSArray? as? [[String: AnyObject]])?
.filter({
!$0.filter({ $0.0 == "kCGWindowName" && $0.1 as? String == "Hearthstone" }).isEmpty
})
.first {
var rect = NSRect()
let bounds = info["kCGWindowBounds"] as! CFDictionary
CGRectMakeWithDictionaryRepresentation(bounds, &rect)
rect.size.height -= titleBarHeight // remove the 22px from the title
hearthstoneFrame = rect
}
}
static func frameRelative(frame: NSRect, _ isRelative: Bool = false) -> NSRect {
var relative = frame
var pointX = NSMinX(relative)
var pointY = NSMinY(relative)
if isRelative {
pointX = pointX / 1404.0 * NSWidth(hearthstoneFrame)
pointY = pointY / 840.0 * NSHeight(hearthstoneFrame)
}
let x: CGFloat = NSMinX(hearthstoneFrame) + pointX
let y = NSMinY(hearthstoneFrame) + pointY
relative.origin = NSMakePoint(x, y)
return relative
}
}
// somewhere here
let frame = NSMakeRect(0, 0, hearthstoneWidth, hearthstoneHeight)
let relativeFrame = SizeHelper.frameRelative(frame)
myWindow.setFrame(relativeFrame, display: true)
Any help will be appreciate :)
I eventually solved this issue so I decided to post the answer to close this thread... and maybe if someone face the same issue one day.
The solution was to substract the max y from the first screen with the max y of the Hearthstone window.
The final code of findHearthstoneFrame is
static func findHearthstoneFrame() {
let options = CGWindowListOption(arrayLiteral: .ExcludeDesktopElements)
let windowListInfo = CGWindowListCopyWindowInfo(options, CGWindowID(0))
if let info = (windowListInfo as NSArray? as? [[String: AnyObject]])?.filter({
!$0.filter({ $0.0 == "kCGWindowName"
&& $0.1 as? String == "Hearthstone" }).isEmpty
}).first {
if let id = info["kCGWindowNumber"] as? Int {
self.windowId = CGWindowID(id)
}
var rect = NSRect()
let bounds = info["kCGWindowBounds"] as! CFDictionary
CGRectMakeWithDictionaryRepresentation(bounds, &rect)
if let screen = NSScreen.screens()?.first {
rect.origin.y = NSMaxY(screen.frame) - NSMaxY(rect)
}
self._frame = rect
}
}
And the frameRelative is
static let BaseWidth: CGFloat = 1440.0
static let BaseHeight: CGFloat = 922.0
var scaleX: CGFloat {
return NSWidth(_frame) / SizeHelper.BaseWidth
}
var scaleY: CGFloat {
// 22 is the height of the title bar
return (NSHeight(_frame) - 22) / SizeHelper.BaseHeight
}
func frameRelative(frame: NSRect, relative: Bool = true) -> NSRect {
var pointX = NSMinX(frame)
var pointY = NSMinY(frame)
let width = NSWidth(frame)
let height = NSHeight(frame)
if relative {
pointX = pointX * scaleX
pointY = pointY * scaleY
}
let x: CGFloat = NSMinX(self.frame) + pointX
let y: CGFloat = NSMinY(self.frame) + pointY
let relativeFrame = NSRect(x: x, y: y, width: width, height: height)
return relativeFrame
}
I have a Scroll View in which I load an Image that can be zoomed and where I can "navigate".
I'm trying to add buttons programmatically to the view such as MKAnnotation that are used in MapKit.
Is that possible?
The methods I use are scrollViewDidZoom
func scrollViewDidZoom(scrollView: UIScrollView) {
centerScrollViewContents()
}
where the function centerScrollViewContents is
func centerScrollViewContents() {
let boundsSize = scrollView.bounds.size
var contentFrame = imageView.frame
if contentFrame.size.width < boundsSize.width {
contentFrame.origin.x = (boundsSize.width - contentFrame.size.width) / 2
} else { contentFrame.origin.x = 0 }
if contentFrame.size.height < boundsSize.height {
contentFrame.origin.y = (boundsSize.height - contentFrame.size.height) / 2
} else { contentFrame.origin.y = 0 }
imageView.frame = contentFrame
}
I add the button/annotation with a UITapGestureRecognizer implemented as
let posTocco = sender.locationInView(scrollView)
println("\(posTocco), \(scrollView.zoomScale)")
var button = UIButton()
let image = UIImage(named: "arrow.png") as UIImage?
button.frame = CGRectMake(posTocco.x, posTocco.y, 30, 30)
button.setImage(image, forState: .Normal)
scrollView.addSubview(button)
For sure I need to define the button/annotation outside the tapGesture function but I cannot figure out how to move the button within the image zoom.
Any help?
EDIT:
I partially figured out how to solve this, but the button slightly move at the first zoom in/out.
I create a new variable which stores the latest zoomValue fattoreScalaCorrente and in the scrollViewDidZoom(scrollView:) I do the magic
var newLoc = CGPoint(x: posAssolute.x * scrollView.zoomScale, y: posAssolute.y * scrollView.zoomScale)
button.frame = CGRectMake(newLoc.x, newLoc.y, button.frame.width, button.frame.height)
Do you have any idea why my button is moving slightly at the first zoom?
EDIT2:
After the suggestion given using
button.frame = CGRectMake(newLoc.x - button.frame.width/2, newLoc.y - button.frame.height/2, button.frame.width, button.frame.height)
The button seems to move a little and I cannot understand why.
Try to replace
button.frame = CGRectMake(newLoc.x, newLoc.y, button.frame.width, button.frame.height)
with
button.frame = CGRectMake(newLoc.x - button.frame.width/2, newLoc.y - button.frame.height/2, button.frame.width, button.frame.height)