UIButton - text moved down - ios

While I am using this code
self.layer.cornerRadius = self.bounds.size.width / 2
self.layer.masksToBounds = true
//
self.titleLabel?.adjustsFontSizeToFitWidth = true
self.titleLabel?.minimumScaleFactor = 0.5
self.titleLabel?.baselineAdjustment = .AlignCenters
self.titleLabel?.numberOfLines = 1
//
self.showsTouchWhenHighlighted = true
to autoshrink label/text that is part of UIButton. For smaller type of devices I got the result like this
Any idea?
EDIT: I did it again from scratch and the result is bit different. Since I use almost everything the same, I might guess this is due to the fact that this version 8 of xCode with SWIFT 2.3 can produce strange things.
Basically what I did is to keep the button resizing with aspect ratio 1:1 and set constraints with the width 414 in the IB.
Smaller devices with width 320 are actually displaying the results bit down than centre depends on the size, bigger == more down. Strange. I didn't touch any insets btw. Default is 10 left and 10 right.

Exchanging this line actually works, strange
self.titleLabel?.baselineAdjustment = .None

Related

Spritekit scaling for universal app

I am having trouble properly setting up my app so that it displays correctly on all devices. I want my game to look best for iPhone and I understand that setting my scene size using GameScene(size: CGSize(width: 1334, height: 750)) and use .aspectFill means that on iPads there will be less space to display things which I'm fine with. The problem is, how do I position my nodes so that they are relative to the each devices frame height and width? I use self.frame.height, self.frame.width, self.frame.midX, etc. for positioning my nodes and when I run my game, it positions things properly considering I run on my iPhone 6, but on my iPad, everything seems blown up and nodes are off the screen. I'm going crazy trying to figure this out
I solved this in my game by using scaleFactors, numbers which tell my app how much to enlarge each length, width, height etc. Then I just make my game look well for one phone, and use that phone's width and height to calculate with which factor I need to enlarge it for other devices. In this example I use the iPhone 4 as a base, but you can use any device just change the numbers according to that device.
Portrait mode:
var widthFactor = UIScreen.main.bounds.width/320.0 //I divide it by the default iPhone 4 width
var heightFactor = UIScreen.main.bounds.height/480.0
Landscape mode:
var widthFactor = UIScreen.main.bounds.width/480.0 //I divide it by the default iPhone 4 landscape width
var heightFactor = UIScreen.main.bounds.height/320.0
Then when you make a node, a coin image for example, multiply its coordinates or width/height by the scaleFactors:
let coin = SKSpriteNode(imageNamed: "coin")
coin.position = CGPoint(x: 25 * widthFactor, y: self.size.height - 70 * heightFactor)
I think what you're looking for might be in this answer: https://stackoverflow.com/a/34878528/6728196
Specifically I think this part is what you're looking for (edited to fit your example):
if UIDevice.current.userInterfaceIdiom == .pad {
// Set things only for iPad
// Example: Adjust y positions using += or -=
buttonNode.position.y += 100
labelNode.position.y -= 100
}
Basically, this just adds or subtracts a certain amount from the iPhone position if the user is using an iPad. It's not too complicated, and you can increase or decrease both x and y values of position by a certain value of percentage of the screen (self.size.width * decimalPercentage).
Another benefit of using this way is that you're just modifying the iPhone positions, so it starts by using the default values that you set. Then if on iPad, it will make changes.
If this is hard to understand let me know so I can clear up the explanation

Why are SKSpriteNodes only partially rendering?

I've coded a basic layout of "cards" for level selection in a game using Swift and SpriteKit. It's basically just 6 level selection cards side by side that have a picture of the level that the user can select. To create them I am running a for-loop and placing the first one in the center of the screen, a padding, then the second one, then padding etc. Each card is an SKSpriteNode from a png image. Each card is approx a 3rd of the device wide and about a 3rd of the devices height.
I create all six of them and then created an action that moves all 6 cards left or right to select which on the player would like. The one in the center is the one that is selected.
Everything works great on iphone simulators (tested on iPhone 6, iPhone 6 plus, iPhone 7 Plus and iPhone 5... all work great). On iPad simulators the first and last card have a portion of the image that doesn't render at all. The first card has about 1/4 of it lost on the left side, the last card has about 1/4 or it lost on the far right side. I tried running it on a physical iPad as well and it has the same issue. When I run it on an iPad Pro 12.7 it gets worse... it cuts off more of the image.
If I choose only to display 5 of the 6 cards they all render great.
If I choose to shrink them down to about 1/4 of the device width and 1/4 of the device height and lessen the padding they render fine.
I tried playing with the Scene and View sizes and scales and didn't have any improvement.
I've tried using different images and there is no changes at all.
I've double checked all zPositions and found no improvement.
I've tried systematically removing all other objects in the scene and still have the problem.
I've put them on their own "layer" which is an SKEffectNode named cardNode. (it's an SKEffectNode because I choose to later blur it when an alert screen comes up in front of it). I thought that putting them onto their own layer might help but it didn't.
I've put physics bodies on the cards just to make sure that they are still "there" and the physics bodies appear in the correct places. If I click on part of the node that isn't rendered it still does behave properly as though it was still rendered in that area.
I can't figure out where to go from here to fix this. Ideally I would like to add more cards yet in the future but getting stuck on this problem.
Here is the code that I have for creating the cards.
let cardNode = SKEffectNode()
let levelCardArray: [String] = [
"BlackBoxLevelCard.png"
,"FruitLevelCard.png"
,"SportsLevelCard.png"
,"BarnLevelCard.png"
,"SeaLevelCard.png"
,"SpaceLevelCard.png"
]
let screenWidth = UIScreen.main.bounds.width
let screenHeight = UIScreen.main.bounds.height
let w10 = screenWidth * 0.10
let w40 = screenWidth * 0.40
let w50 = screenWidth * 0.50
let w60 = screenWidth * 0.60
let h50 = screenHeight * 0.50
let cardMargin = w10
let cardSize = CGSize(width: w40, height: w60)
let startPosition = CGPoint(x: w50, y: h50)
override func didMove(to view: SKView) {
let scene = levelSelectionScene(size: view.bounds.size)
scene.backgroundColor = UIColor.black
let skView = view as SKView
skView.ignoresSiblingOrder = true
cardNode.zPosition = 100
self.addChild(cardNode)
for i in 1...levelCardArray.count {
let currentArrayValue = i - 1
let cardSprite = SKSpriteNode(imageNamed: levelCardArray[currentArrayValue])
cardSprite.size = cardSize
cardSprite.position = CGPoint(x: startPosition.x + (CGFloat(currentArrayValue) * (cardSize.width + cardMargin)), y: startPosition.y)
cardSprite.zPosition = cardNode.zPosition
cardSprite.name = "levelCardObject"
cardNode.addChild(cardSprite)
}
Any help or insight would be greatly appreciated. Thanks guys!
I tried all day today to try to find a way to make this work through resizing the scenes and views and haven't had any luck with it at all.
My solution is to check for the device type and if it's an iPad I am reducing the image sizes and buffer between images until it doesn't cut them off. I don't consider this a very good solution, really just a work around until I can find a better way to do it. Thank you guys for your thoughts though. I definitely appreciate it!

SKEmitterNode particles clumping together on creation

I have an SKEmitterNode that is acting strange in different versions of iOS. If you look at the screenshot below, you will see that when my scene is loaded, the emitter I am using dumps an odd group of rain drops when the scene first loads.
The strangest part is that this happens in some versions of iOS like 8.1 and 9.2, but in some other versions like 9.0 and 7.0 it runs as expected. (meaning no initial clump of drops, just randomly spaced drops.)
Here is my code in didMoveToView:
let rainEmitterPath:NSString = NSBundle.mainBundle().pathForResource("homeScreenRain", ofType: "sks")!
self.rainEmitter01 = NSKeyedUnarchiver.unarchiveObjectWithFile(rainEmitterPath as String) as! SKEmitterNode
self.rainEmitter01.position = CGPointMake(device.x/2, device.y + 50)
self.rainEmitter01.targetNode = self
self.rainEmitter01.particleZPosition = 6.0
self.rainEmitter01.particleBirthRate = 300
self.rainEmitter01.particleSpeed = 5000 * worldScale
self.rainEmitter01.particleSpeedRange = worldScale * 1000
self.rainEmitter01.particleScale = worldScale
self.rainEmitter01.particleScaleRange = worldScale
self.rainEmitter01.particlePositionRange = CGVector(dx: device.x + 100, dy: 5)
//self.rainEmitter01.advanceSimulationTime(7.0)
self.addChild(rainEmitter01)
I have tried using the advanceSimulationTime method, but for some reason the group of drops still falls even after the delay.
I have also tried varying the y size of the position range because I figured that my height of 5 was causing this, but nothing changed even when I make the height equal to the size of the screen, and a height of 5 still works in other versions of iOS.
Anyone know why this is happening and a solution/workaround?
Thanks in advance.

How to correctly set a circle imageView with Swift?

im trying to make a circle imageprofile, like the profile image of instagram/whatsapp. Right now my code seems to work, but i did it in 2 different ways and both works, so i want to know which one is the best
First way:
profileImageView.layer.cornerRadius = profileImageView.frame.width / 2
profileImageView.clipsToBounds = true
Second way
profileImageView.layer.cornerRadius = profileImageView.frame.width / 2
profileImageView.layer.masksToBounds = true
Also i would like if someone can explain me about "clipToBounds" and "maskToBounds", what they do. Thanks!
clipsToBounds is a boolean value that determines whether subviews are confined to the bounds of the view.
Setting this value to YES causes subviews to be clipped to the bounds of the receiver. If set to NO, subviews whose frames extend beyond the visible bounds of the receiver are not clipped. The default value is NO.
Basically, this thing plays with the view's property.
Whereas masksToBounds is a boolean indicating whether sublayers are clipped to the layer’s bounds.And this thing plays with the layer of the view.
The way that I always do it, specifically in a situation where I want to show a profile picture in my application, I use this code:
profileImage.layer.cornerRadius = self.profileImage.frame.size.width / 2;
profileImage.clipsToBounds = true;
This is what I would recommend to do!

How do i resize an object created in actionscript with the point of origin staying central

widthEssentially, i am creating objects in Flash using actionscript. I currently have a problem where i am resizing the object in actionscript but as the point of reference seems to be the top left hand corner, the object when shrinking seems to also move towards the top left of the screen.
Is there a way to either code the point of origin for an object to the center of the object using code or to have it resize without seemingly moving?
my code for creating and resizing an object is like this (it will grow and shrink but at moment im just tryint to fix this problem before i move on):
var blob1:Loader = new Loader();
blob1.x = 1000;
blob1.y = 450;
blob1.load(new URLRequest("blob1.png"));
addChild(blob1);
blob1.addEventListener(Event.ENTER_FRAME, blobTween);
function blobTween(event:Event)
{
var size = 0;
if (size == 0){
blob1.width += 5;
blob1.height += 5;
}else if (size == 1){
}
Can't you update x and y while you change width and height ?
blob1.x += deltaWidth / 2
blob1.y += deltaHeight / 2
You increment width and height by 5, so deltaWidth = 5 and deltaHeight = 5 .
NOTE: deltaWidth / 2 doesn't divide equally, so you'll have slight shift. I suggest having deltaWidth = 6 and deltaHeight = 6 , or something similar.
GreenSock has a great library for doing just that; TransformManager.
http://www.greensock.com/transformmanageras3/
my solution in the end was a bit strange. I took the shape, divided it into 4 quarters and reattached them in flash by placing the objects in the same place and rotating them (as it rotates from the top left corner, the 4 quarters form a complete shape with each quarter having their top left corner in the centre of the "object"). I then resized them all at once to do it properly.
Whats weird is that the top right and bottom left corners required different math from the other two corners. Which makes no sense whatsoever. 2 corners required width and height to be adjusted. The other two corners required just width to be adjusted. very strange but worked :/

Resources