Rotating button cause changing it's frame - swift

Yellow part is the button:
Inside PanGesture:
case .changed:
tempAngle = atan2(touchPoint.y - nailPoint.y, touchPoint.x - nailPoint.x)
changedAngle = tempAngle
let distance = distanceFromTwoPoints(nailPoint, touchPoint)
drawTempUnitButton(buttonPoint: nailPoint, unitButtonWidth: distance, anchorPoint: currentAnglePoint, angle: tempAngle, button: tempUnitButton, unitValue: distance)
How I create button, both width and height are fixed
func drawTempUnitButton(buttonPoint:CGPoint, unitButtonWidth:CGFloat, anchorPoint:CGPoint, angle:CGFloat, button:UIButton, unitValue:CGFloat){
self.addSubview(button)
button.frame = CGRect(x: buttonPoint.x, y: buttonPoint.y, width: unitButtonWidth, height: 30)
let floatUnitValue = Float(unitValue)
let buttonTxt = String(floatUnitValue)
button.setTitle(buttonTxt, for: .normal)
button.titleLabel?.textAlignment = .center
button.setTitleColor(.red, for: .normal)
button.titleLabel?.font = .boldSystemFont(ofSize: 16)
button.backgroundColor = UIColor.yellow
button.setAnchorPoint(anchorPoint)
let transform = CGAffineTransform(rotationAngle: angle)
button.transform = transform
}
What is the problem with it?

Base on Leo Dabus comment, I fixed with these
button.frame = CGRect(x: buttonPoint.x, y: buttonPoint.y, width: 0, height: 0)
button.bounds.size.width = unitButtonWidth
button.bounds.size.height = 30

Related

How can one position navigation bar item in Swift?

I have a navigation bar that currently only has a back button. I am trying to add an image button on the right side of the navigation bar but the image I am using is larger than the navigation bar and ends up covering the back button and gets positioned strangely.
This is the code:
let mapBtn = UIButton(type: .system)
mapBtn.setImage(#imageLiteral(resourceName: "map-1"), for: .normal)
mapBtn.frame = CGRect(x: 0,y: 0,width: 5,height: 5)
self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: mapBtn)
This is an image of what is happening:
https://imgur.com/a/kzcwbGK
Is there anyway to add a constraint to the mapBtn to make it stick to the right side as it should be?
Try to resize your image
func resizeImage(image: UIImage, targetSize: CGSize) -> UIImage? {
let size = image.size
let widthRatio = targetSize.width / image.size.width
let heightRatio = targetSize.height / image.size.height
// Figure out what our orientation is, and use that to form the rectangle
var newSize: CGSize
if(widthRatio > heightRatio) {
newSize = CGSize(width: size.width * heightRatio, height: size.height * heightRatio)
} else {
newSize = CGSize(width: size.width * widthRatio, height: size.height * widthRatio)
}
// This is the rect that we've calculated out and this is what is actually used below
let rect = CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height)
// Actually do the resizing to the rect using the ImageContext stuff
UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
image.draw(in: rect)
if let newImage = UIGraphicsGetImageFromCurrentImageContext(){
UIGraphicsEndImageContext()
return newImage
}else{
return nil
}
}
let mapBtn = UIButton(type: .system)
let img = UIImage(named: "map-1")
let resizedImage = resizeImage(image: img, targetSize: CGSize(width: 5.0, height: 5.0)
mapBtn.frame = CGRect(x: 0,y: 0,width: 5,height: 5)
mapBtn.setImage(resizedImage, for: .normal)
self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: mapBtn)
set this.
mapBtn.imageView?.contentMode = .scaleAspectFit

Cant set right frame for ImageView

I cant set my UIImageView as half size of my tableview.backgroundview in upper part of my controller.
i tried to set origin of avatar as origin view, but it doesnt work.
let avatar = UIImageView(frame: self.view.frame)
let imgageOfAvatar = UIImage(named: "avatar.jpg")
avatar.image = imgageOfAvatar
avatar.frame = CGRect(x: self.view.frame.origin, y: self.view.frame.origin , width: self.view.frame.width, height: self.view.frame.height / 2)
avatar.frame.origin = self.view.frame.origin
//avatar.contentMode = UIViewContentMode.scaleAspectFill
self.tableView.addSubview(avatar)
self.tableView.sendSubview(toBack: avatar)
https://pp.userapi.com/c847120/v847120175/19f9cf/128kU2yWq-E.jpg
Try this
avatar.frame.origin.x = self.view.frame.origin.x
avatar.frame.origin.y = self.view.frame.origin.y
avatar.frame = CGRect(origin:self.view.frame.origin, size: width: self.view.frame.width, height: self.view.frame.height / 2)
you should add it to view like this:
let avatar = UIImageView(frame: self.view.frame)
let imgageOfAvatar = UIImage(named: "avatar.jpg")
avatar.image = imgageOfAvatar
avatar.frame = CGRect(x: self.view.frame.origin.x, y: self.view.frame.origin.y , width: self.view.frame.width, height: self.view.frame.height / 2)
avatar.frame.origin = self.view.frame.origin
self.view.insertSubview(avatar, at: 0)
I got the intended result
output
let avatar = UIImageView(frame: self.view.frame)
let imgageOfAvatar = UIImage(named: "dog.jpeg")
avatar.image = imgageOfAvatar
avatar.frame = CGRect(origin: self.view.frame.origin,
size: CGSize(width: self.view.frame.width,
height: self.view.frame.height / 2))
self.tableview.addSubview(avatar)
self.tableview.sendSubviewToBack(avatar)

Swift - How to make animated arrow point in right direction?

I have two buttons which when connected, show a line with an animated arrow to show that they are connected.The issue is the arrow it self is not rotating appropriately to point in the right direction when animated.
How can I rotate the arrow to point in the right direction when moving?
class ViewController: UIViewController {
let line = CAShapeLayer()
let linePath = UIBezierPath()
var triangleImage = UIImage(named: "triangle" )
let startCoordinate = CGRect(x: 100, y: 100, width: 0, height: 0)
let btn1 = UIButton()
let btn2 = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
btn1.createRectangleButton(buttonPositionX: 100, buttonPositionY: 100, buttonWidth: 80, buttonHeight: 40, buttonTitle: "", buttonTag: 0)
btn2.createRectangleButton(buttonPositionX: 300, buttonPositionY: 400, buttonWidth: 80, buttonHeight: 40, buttonTitle: "", buttonTag: 1)
view.addSubview(btn1)
view.addSubview(btn2)
let imageView = UIImageView(image: triangleImage)
imageView.frame = CGRect(x:100, y:100, width: 20, height: 20)
imageView.center = self.btn1.center
view.addSubview(imageView)
linePath.move(to: btn1.center)
linePath.addLine(to: btn2.center)
line.path = linePath.cgPath
line.strokeColor = UIColor.red.cgColor
self.view.layer.addSublayer(line)
view.bringSubviewToFront(imageView)
UIView.animate(withDuration: 3, delay: 0.0, options: [.repeat, .curveLinear], animations: {
imageView.center = self.btn2.center
}, completion: nil)
}
note: the code above will look slightly different to the image
Try this rotation transformation
// rotation
imageView.transform = CGAffineTransform(rotationAngle: atan2(btn2.center.y - btn1.center.y, btn2.center.x - btn1.center.x) + CGFloat.pi / 2)
// used triangle image below

Circular crop for photos from photo library when using UIImagePickerController

I am trying to change the square crop tool to circular one for the images selected from Photo Library in Swift 4. I tried many old codes available in here with no luck. Can somebody please help me.
There are mainly 2 issues in this code.
It doesn't hide the already existing square cropping area.
It shows the choose and cancel buttons under the old overlay, so cant tap on it.
Any help would be appreciated.
My code:
private func hideDefaultEditOverlay(view: UIView)
{
for subview in view.subviews
{
if let cropOverlay = NSClassFromString("PLCropOverlayCropView")
{
if subview.isKind(of: cropOverlay) {
subview.isHidden = true
break
}
else {
hideDefaultEditOverlay(view: subview)
}
}
}
}
private func addCircleOverlayToImageViewer(viewController: UIViewController) {
let circleColor = UIColor.clear
let maskColor = UIColor.black.withAlphaComponent(0.8)
let screenHeight = UIScreen.main.bounds.size.height
let screenWidth = UIScreen.main.bounds.size.width
hideDefaultEditOverlay(view: viewController.view)
let circleLayer = CAShapeLayer()
let circlePath = UIBezierPath(ovalIn: CGRect(x: 0, y: screenHeight - screenWidth, width: screenWidth, height: screenWidth))
circlePath.usesEvenOddFillRule = true
circleLayer.path = circlePath.cgPath
circleLayer.fillColor = circleColor.cgColor
let maskPath = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: screenWidth, height: screenHeight), cornerRadius: 0)
maskPath.append(circlePath)
maskPath.usesEvenOddFillRule = true
let maskLayer = CAShapeLayer()
maskLayer.path = maskPath.cgPath
maskLayer.fillRule = kCAFillRuleEvenOdd
maskLayer.fillColor = maskColor.cgColor
viewController.view.layer.addSublayer(maskLayer)
// Move and Scale label
let label = UILabel(frame: CGRect(x: 0, y: 20, width: view.frame.width, height: 50))
label.text = "Move and Scale"
label.textAlignment = .center
label.textColor = UIColor.white
viewController.view.addSubview(label)
}

Saving NSUserDefaults with UISwitch in Swift 2

I have posted all my code below to fully demonstrate what I am trying to accomplish. I have a UI Switch, that I would like to save a NSUserDefault on what game mode they would like. I am not sure why this is not working correctly, as it currently does not save- as the switch doesn't work.
import SpriteKit
class ModeScene: SKScene {
var modeSwitch = UISwitch()
var motionLabel = UILabel()
var touchLabel = UILabel()
override func didMoveToView(view: SKView) {
let MotionMode = NSUserDefaults.standardUserDefaults()
let TouchMode = NSUserDefaults.standardUserDefaults()
modeSwitch.center = CGPoint(x: view.center.x, y: view.frame.size.height / 1.3)
modeSwitch.addTarget(self, action: Selector("updateMode"), forControlEvents: UIControlEvents.ValueChanged)
if TouchMode {
modeSwitch.on = false
}
else{
modeSwitch.on = true
}
self.view?.addSubview(modeSwitch)
motionLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 700, height: 200))
motionLabel.center = CGPoint(x: view.center.x * 3.4, y: view.frame.size.height / 1.3)
motionLabel.text = "Accelerometer"
motionLabel.textColor = UIColor.whiteColor()
motionLabel.font = UIFont(name:"ArialRoundedMTBold", size: 16)
self.view?.addSubview(motionLabel)
touchLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 700, height: 200))
touchLabel.center = CGPoint(x: view.center.x * 2.25, y: view.frame.size.height / 1.3)
touchLabel.text = "Touch To Move"
touchLabel.textColor = UIColor.whiteColor()
touchLabel.font = UIFont(name:"ArialRoundedMTBold", size: 16)
self.view?.addSubview(touchLabel)
DoneBtn = UIButton(frame: CGRect(x: 0, y: 0, width: 400, height: 30))
DoneBtn.center = CGPoint(x: view.center.x * 1.7, y: view.frame.size.height / 14)
DoneBtn.setTitle("Done", forState: UIControlState.Normal)
DoneBtn.setTitleColor(UIColor.whiteColor(), forState: UIControlState.Normal)
DoneBtn.addTarget(self, action: Selector("done"), forControlEvents: UIControlEvents.TouchUpInside)
self.view?.addSubview(DoneBtn)
updateMode()
}
func updateMode(){
if modeSwitch.on {
// mode is accel
let MotionMode = NSUserDefaults.standardUserDefaults()
MotionMode.setValue(true, forKey: "MotionMode")
NSLog("Mode is accel")
}
else{
// mode is touch
let TouchMode = NSUserDefaults.standardUserDefaults()
TouchMode.setObject(true, forKey: "TouchMode")
NSLog("Mode is touch")
}
}
func done(){
self.scene?.view?.presentScene(StartScene(size: self.scene!.size), transition: SKTransition.fadeWithColor(UIColor.blackColor(), duration: 1))
headerLabel.removeFromSuperview()
DoneBtn.removeFromSuperview()
modeSwitch.removeFromSuperview()
touchLabel.removeFromSuperview()
motionLabel.removeFromSuperview()
}
}
Code Update:
import SpriteKit
class ModeScene: SKScene {
var modeSwitch = UISwitch()
var motionLabel = UILabel()
var touchLabel = UILabel()
var DoneBtn : UIButton!
override func didMoveToView(view: SKView) {
backgroundColor = SKColor.blackColor()
modeSwitch.center = CGPoint(x: view.center.x, y: view.frame.size.height / 1.3)
modeSwitch.addTarget(self, action: Selector("updateMode"), forControlEvents: UIControlEvents.ValueChanged)
self.view?.addSubview(modeSwitch)
motionLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 700, height: 200))
motionLabel.center = CGPoint(x: view.center.x * 3.4, y: view.frame.size.height / 1.3)
motionLabel.text = "Accelerometer"
motionLabel.textColor = UIColor.whiteColor()
motionLabel.font = UIFont(name:"ArialRoundedMTBold", size: 16)
self.view?.addSubview(motionLabel)
touchLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 700, height: 200))
touchLabel.center = CGPoint(x: view.center.x * 2.25, y: view.frame.size.height / 1.3)
touchLabel.text = "Touch To Move"
touchLabel.textColor = UIColor.whiteColor()
touchLabel.font = UIFont(name:"ArialRoundedMTBold", size: 16)
self.view?.addSubview(touchLabel)
DoneBtn = UIButton(frame: CGRect(x: 0, y: 0, width: 400, height: 30))
DoneBtn.center = CGPoint(x: view.center.x * 1.7, y: view.frame.size.height / 14)
DoneBtn.setTitle("Done", forState: UIControlState.Normal)
DoneBtn.setTitleColor(UIColor.whiteColor(), forState: UIControlState.Normal)
DoneBtn.addTarget(self, action: Selector("done"), forControlEvents: UIControlEvents.TouchUpInside)
self.view?.addSubview(DoneBtn)
let defaults = NSUserDefaults.standardUserDefaults()
if let motionMode = defaults.objectForKey("motionMode") as? Bool {
if motionMode {
// true
modeSwitch.on = true
} else {
// false
modeSwitch.on = false
}
}
updateMode()
}
func updateMode(){
let defaults = NSUserDefaults.standardUserDefaults()
if modeSwitch.on {
// mode is accel
defaults.setBool(true, forKey: "motionMode")
NSLog("Mode is accel")
}
else{
// mode is touch
defaults.setBool(true, forKey: "touchMode")
NSLog("Mode is touch")
}
}
func done(){
self.scene?.view?.presentScene(StartScene(size: self.scene!.size), transition: SKTransition.fadeWithColor(UIColor.blackColor(), duration: 1))
headerLabel.removeFromSuperview()
DoneBtn.removeFromSuperview()
modeSwitch.removeFromSuperview()
touchLabel.removeFromSuperview()
motionLabel.removeFromSuperview()
}
}
You forgot to actually load the values from NSUserDefaults.
You set them with setValue and setObject, but you never load them back.
Use the valueForKey or objectForKey methods to retrieve your values.
let defaults = NSUserDefaults.standardUserDefaults()
let MotionMode = defaults.objectForKey("MotionMode") as! Bool
if MotionMode {
// true
} else {
// false
}
Even better with safe unwrapping:
let defaults = NSUserDefaults.standardUserDefaults()
if let MotionMode = defaults.objectForKey("MotionMode") as? Bool {
if MotionMode {
// true
} else {
// false
}
}
A few notes: variables should begin with a lowercase letter, so "MotionMode" should be "motionMode", etc. You could use the specialized object getters like boolForKey instead of the generic objectForKey which forces you to typecast to Bool. Of course it goes with setBool on the other side. Last: the variable you call "MotionMode" actually holds NSUserDefaults.standardUserDefaults(), so I called it "defaults" instead in my example.
Your question has several parts, but it's better to make a single post for a single question. So I've focused about the failing NSUserDefaults part because it was the most important. Using my answer, if your code still doesn't work because of the UI parts, then you should post a new different question about it to keep things clear.