How can I horizontally center two side-by-side UILabels? - ios

I have a series of labels that I want to center horizontally (that is, along the X axis), like this:
thing1: value1
thing2: value2
etc.
Autolayout doesn't seem to allow this. Even if I stick the two together and use the guidelines to center the pair, the center constraint only applies to the first label in the pair.
The various "things" will have different lengths, and I want to colons to line up (right-justified) and the values on the left to line up (left-justified).
Is there any way to do this?

This is easy to do in code. The x-offset of the first label should be half the difference between the width of the parent view and the sum of the widths of the two labels. For example:
CGFloat xOffset = ((parentView.frame.size.width -
(view1.frame.size.width + view2.frame.size.width)) / 2);
// now position the first label using this offset
view1.frame = CGRectMake(xOffset,
view1.frame.origin.y,
view1.frame.size.width,
view1.frame.size.height);
// and position the second view relative to the first
view2.frame = CGRectMake(CGRectGetMaxX(view1.frame),
view2.frame.origin.y,
view2.frame.size.width,
view2.frame.size.height);

Related

Multicolumn list with flexible columns width - iOS

I want to create list with two columns. Text in first column should be aligned to left and text in second column should be aligned to right. Space between columns should be constant. Different cases depends on texts length should be covered:
1.
Text 123
TextText 12
Tex 123
Text 1
Te 123456
T 12
Te 1234
Te 1
Text 123
TextText 12
TextTextTextTextText 123
Text 1
Both columns should have flexible width depends on the longest text. They also should have some minimum width so it will not be completely invisible if text in other column will be too long. Whole list also should have flexible width, of course there is some max width and then text in first column should be divided into lines. I don't want to divide into lines text in second column as long as I don't have to.
How to create such list?
I try to use for it two stack views one next to the other. These two stack views I have in my custom control. My custom control is added to container view using xib and have constraints equals to 0 for top, leading and bottom and greater or equals 0 for trailing. To these stack views I add labels programatically and I also set content hugging priority for them (first label has lower priority than second one). One think stil doesn't work, first stack view is as width as first label in this stack view. It doesn't change his width when other labels with longer texts are added. Is it possible to have working solution without calculating stack views width manually?
private void Initialize()
{
_firstStackView = new UIStackView
{
TranslatesAutoresizingMaskIntoConstraints = false,
Axis = UILayoutConstraintAxis.Vertical,
Spacing = 4
};
_secondStackView = new UIStackView
{
TranslatesAutoresizingMaskIntoConstraints = false,
Axis = UILayoutConstraintAxis.Vertical,
Spacing = 4,
Alignment = UIStackViewAlignment.Trailing
};
Add(_firstStackView);
Add(_secondStackView);
AddConstraints();
}
private void AddConstraints()
{
NSLayoutConstraint.ActivateConstraints(
new[]
{
_firstStackView.LeadingAnchor.ConstraintEqualTo(LeadingAnchor),
_secondStackView.LeadingAnchor.ConstraintEqualTo(_firstStackView.TrailingAnchor, 20),
TrailingAnchor.ConstraintEqualTo(_secondStackView.TrailingAnchor),
_firstStackView.TopAnchor.ConstraintEqualTo(TopAnchor),
_firstStackView.BottomAnchor.ConstraintEqualTo(BottomAnchor),
_secondStackView.CenterYAnchor.ConstraintEqualTo(_firstStackView.CenterYAnchor),
_secondStackView.WidthAnchor.ConstraintGreaterThanOrEqualTo(WidthAnchor, 0.25f),
_firstStackView.WidthAnchor.ConstraintGreaterThanOrEqualTo(WidthAnchor, 0.25f),
});
}
You can use UICollectionView to create list with two columns. Space between columns and grid size can be adjusted by changing UICollectionViewLayout.
Implement text adaptive width and height:
Instantiate UILabel
Set the UILabel property to get the text content and font
Calculate the size according to text and font
Use CGSize to set the maximum width you want
Set the frame according to the size
You can see some useful info here
For more details, you can refer to the following doc:
Collection Views in Xamarin.iOS | Microsoft Docs

Swift 4 - Editing label frame.size.height with negative number

So I have a label that I've made in Xcode's storyboard which I want to later edit in my code. I want it to simulate something like a vertical bar so I am editing its height by doing:
answerE.frame.size.height = -200
The problem comes from the negative number, I want the label to "grow" up so the height has to be negative from its original position... I have the line in code in a simple action on button press, but each time the line is executed the label moves "up" and eventually after 3-4 clicks is out of the screen.
I just want to edit its height, what is the correct way and what am I doing wrong?
My exact line in code is:
label.frame.size.height = -CGFloat(Double(x)/Double(y) * (200))
If you have added the label in storyboard, why not you use constraints to get the result.
Add leading, trailing , bottom and fixed height constraint and connect IBOutlet to height constraint. Change the constant value of height constraint at the event which you want to perform.
If I'm right, you want the label to gain height, keeping the same bottom edge, but the top edge moving up.
In order to do this, you want to change the frame.origin.y as you change the frame.size.height at the same amount, as its placement (and so top edge) is determined by its origin. So maybe make it zero height, place it where you want it in storyboard, and then when you want it to 'grow' by x:
label.frame.size.height = label.frame.height + x
label.frame.origin.y = label.frame.origin.y - x

Swift: programmatically align labels for different IOS screen sizes

I'm new to Swift and ios development. I have 6 labels and a horizontal SKScene in my App. I would like to align those 6 labels beautifully and automatically. Now I have fixed the positions and the alignment always looks awful on some screen size while good on other.
I have not used storyboards or other graphical editors for building the ui but everything is done in code. Therefore I'm looking for a programmatic solution (code examples) for handling the alignment.
If you want to place them in the middle of the screen horizontally, but give them different y positions, you could just do something like this for each label:
label.position = CGPointMake(CGRectGetMidX(self.frame),CGRectGetMaxY(self.frame) * 0.80)
To place them at different y positions, just multiply by the maxY by a different decimal number. This way, all of the labels are aligned along the x-axis and appear at different y-positions, like a column and they will appear this way on every screen size because they are positioned relative to the screen size and not in a fixed position.
You can align the labels (lets say at the center of the screen) like this.
var label1 = UILabel(CGRectMake: 0, 0, 200, 40)
label1.center = CGPointMake(UIScreen.mainScreen().bounds.size.width/2, 30)
var label2 = UILabel(CGRectMake: 0, 0, 200, 40)
label2.center = CGPointMake(UIScreen.mainScreen().bounds.size.width/2, label1.center.y + 30)
and so on. Just reference the main screen bounds and not static points for alignment, so that they are centered in any screen size.
What I ended up doing was to create an empty SKSprite to which I included the SKLabels. Now I can control by the pixed the distances between labels but align the top-level sprite in the middle of the screen despite screen size.

How can I tap on a UICollectionView cell of a collection view in UIAutomation?

How can I tap on a UICollectionView cell of a collection view in UIAutomation?
I tried this
var iconsCollView = window.collectionViews()[0];
var iconRect = iconsCollView.cells()[0].rect();
var iconX = iconRect.origin.x/100;
var iconY = iconRect.origin.y/100;
iconsCollView.tapWithOptions({tapOffset:{x: iconX, y: iconY}});
but it taps another cell in the collection view, a wrong cell other than the cell I specified its offset.
Can you please help me? is there another way?
From the UIAElement class reference:
Your script should treat the rect object as a generic JavaScript object whose properties for origin, x, y, size, width, and height correspond to those of the analogous CGRect Cocoa structure. The rect object has the form {origin:{x:xposition,y:yposition}, size:{width:widthvalue, height:heightvalue}}. The relevant coordinates are screen-relative and are adjusted to account for device orientation.
From the same source under tapWithOptions method:
You can use offsets to achieve finer precision in specifying the hitpoint within the rect for the specified element. The offset comprises a pair of x and y values, each ranging from 0.0 to 1.0. These values represent, respectively, relative horizontal and vertical positions within the rect, with {x:0.0, y:0.0} as the top left and {x:1.0, y:1.0} as the bottom right. Thus, {x:0.3, y:0.6} specifies a position just below and to the left of center, and {x:1.0, y:0.5} specifies a position centered vertically at the far right.
From the source you provided, you're trying to tap inside of collection view passing some weirdly scaled offset coordinates of one of its cells (instead of expected relative horizontal and vertical positions within the rect of collection view).
If you want to tap the cell simply locate it and call the tap method on it:
var iconsCollView = window.collectionViews()[0];
var iconCellToTap = iconsCollView.cells()[0].tap();

iCarousel - How to shift the focus to the left side

I need to implement iCarousel in a way so that it looks like this:
I have done all the modifications at my end to make it look like this but now the problem is that iCarousel works with the center image in the focus. Can I make it so that if there are only two images, they don't appear in the center but rather on the left? Think about it like the "left indented" content.
How do I do this?
iCarousal provide a property to sift focus left or right by set the width offset.
For right side use this code for swift 2.3 -
let widthOffset: Float = -120.0
self.customCarousel.viewpointOffset = CGSize(width: CGFloat(widthOffset), height: CGFloat(0))
This should be the property in iCarousel you are looking for viewpointOffset
Example...
// Modifiy widthOffset so it works well in your case
float widthOffset = 100.0;
[_yourCarousel setViewpointOffset:CGSizeMake(widthOffset, 0)];
The viewpointOffset property doesn't really work that way. It will let you align to one edge, but then when you scroll to the end you'll have the same problem.
iCarousel wasn't designed to do this. I suggest you switch to SwipeView instead (http://github.com/nicklockwood/SwipeView) which has the same delegate/datasource interface, but has an alignment property that you can use to set edge alignment, like this:
swipeView.alignment = SwipeViewAlignmentEdge;
Visit https://github.com/nicklockwood/iCarousel/issues/142
it may help.
nicklockwood (author) answer:
You could use the delegate and create a custom transform that offsets all of your views by a negative amount. Something like this:
- (CATransform3D)carousel:(iCarousel *)carousel itemTransformForOffset:(CGFloat)offset baseTransform:(CATransform3D)transform
{
float OFFSET_WIDTH = ...; // set this to about half the width of your view
return CATransform3DMakeTranslation(offset * itemWidth - OFFSET_WIDTH, 0, 0);
}
The only problem would be that when you reach the rightmost end of the
carousel there would be a gap, but you could use placeholder views to
fill the gap up.
I tripped over the same problem. After simple math I've found a more accurate answer. I've put this code in my viewDidAppear() function, because when I put it in viewDidLoad() the view.frame.width and view.frame.height took the original width of my storyboard, which didn't fit to bigger devices.
My use case was the following. My iCarousel items are simple squares. That means, I have for example a height of 3 and a width of 3. But the width of my iCarousel view is 5. In sum I have 5-3=2 space, 1 left and 1 right (because we know it's default is centered). So last step is to divide with 2 to get the width on one site = 1. With this knowledge we just have to set the viewPointOffset to 1 (in this case).
Final formular: let widthOffset = (view.frame.width - view.frame.height) / 2
Example in my code:
let widthOffset: Float = Float((mDetailCarousel.frame.width - mDetailCarousel.frame.height) / 2 )
mDetailCarousel.viewpointOffset = CGSize(width: CGFloat(widthOffset), height: CGFloat(0))

Resources