Views in circle with animation - ios

What I've to do is to lay out few UIButtons circularly and whenever any button is tapped that button should animate to the top position(top of the circle, i.e. first button in the circle) and hence all the other buttons should animate appropriately so that the tapped button comes to the top.
Now, I've arranged the buttons circularly using
double perAngle = 2 * M_PI / BUTTONS_COUNT;
for (int i = 0; i < BUTTONS_COUNT; i++) {
UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(sin(perAngle * i) + basePoint.x, cos(perAngle * i) + basePoint.y, Width, Height)];
[self.View addSubView:btn];
}
I'm rotating this view around z-axis using CAAnimation so that it looks like all buttons are moving in circle when any button is tapped. The problem is I cannot decide by what angle to rotate so that every time only the tapped button comes to the top and not any other button.
Or any other totally different approach to achieve this?

Here is a playground that shows how to distribute the buttons in a circle using the transform (the starting angle is zero so just add whatever the current angle chould be and everythign will move). Whatever is at 270 degrees or 1.5 pi will be on top of the circle. You can animate the transforms to change the angle. Note that I am setting the frames here because its a playground. You can use constraints in your storyboard to achieve the same thing.
let view = UIView(frame: CGRect(x: 0, y: 0, width: 500, height: 500))
let buttonCount = 6
for i in 0..<buttonCount {
let button = UIButton()
button.center = view.center
button.setTitle("button \(i)", for: .normal)
button.sizeToFit()
view.addSubview(button)
var transform = CGAffineTransform(rotationAngle: -2 * CGFloat.pi * CGFloat(i) / CGFloat(buttonCount))
.translatedBy(x: 100, y: 0)
.rotated(by: 2 * CGFloat.pi * CGFloat(i) / CGFloat(buttonCount))
button.transform = transform
}
PlaygroundPage.current.liveView = view

Related

ios:how to add top and bottom border in tableview?

I want table like this image that show top and bottom border with color only
i have apply this code in viewDidLoad()
tblFilter.layer.borderWidth = 0.5
tblFilter.layer.borderColor = UIColor.white.cgColor
above code add border at all side that i dont want.
i want table border in only top or bottom side.
i want tableview border like given image. see given image.
please suggest me solution
Thanks
my problem is solved.
i added one custom view. In that view i added two view with 1px height at top and bottom of view and i added table-view in that custom view.
Try this
let topBorder = CAShapeLayer()
let topPath = UIBezierPath()
topPath.move(to: CGPoint(x: 0, y: 0))
topPath.addLine(to: CGPoint(x: tblFilter.frame.width, y: 0))
topBorder.path = topPath.cgPath
topBorder.strokeColor = UIColor.red.cgColor
topBorder.lineWidth = 1.0
topBorder.fillColor = UIColor.red.cgColor
tblFilter.layer.addSublayer(topBorder)
let bottomBorder = CAShapeLayer()
let bottomPath = UIBezierPath()
bottomPath.move(to: CGPoint(x: 0, y: tblFilter.frame.height))
bottomPath.addLine(to: CGPoint(x: tblFilter.frame.width, y: tblFilter.frame.height))
bottomBorder.path = bottomPath.cgPath
bottomBorder.strokeColor = UIColor.red.cgColor
bottomBorder.lineWidth = 1.0
bottomBorder.fillColor = UIColor.red.cgColor
tblFilter.layer.addSublayer(bottomBorder)
If don't want to use the table footer and header you can use the table header view and footer view where you can return view with white color and height would be 1 and width same as table width
Use tableview header and footer.
// in -viewDidLoad
self.tableView.tableHeaderView = ({UIView *line = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.tableView.frame.size.width, 1 / UIScreen.mainScreen.scale)];
line.backgroundColor = self.tableView.separatorColor;
line;
});
Same do it for footer also.
self.tableView.tableFooterView = ({UIView *line = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.tableView.frame.size.width, 1 / UIScreen.mainScreen.scale)];
line.backgroundColor = self.tableView.separatorColor;
line;
});
Or else just add UIVIEW to the background and set the color. That will also help.
Take two UIView. Give it white color.
y cordinate of top uiview is min y of uitableview and y cordinate of bottom uiview is max y of uitableview.
you can get min y and max y using GetMaxY and GetMinY.
width of both uiview are same as uitableview.
height of both uiview are 1px.
hope this will help you.
take label in the cell with height value as 1 and give border to it. Programmatically hide/show on your require index.

Size of custom UIButton(hexagon) don't work on different Iphones

I have 4 UIButtons:
import UIKit
class HexagonButton: UIButton {
override func drawRect(rect: CGRect) {
print("screenheight:\(self.frame.width)")
let polySize:CGFloat = self.frame.width // change this
let context = UIGraphicsGetCurrentContext()
CGContextSaveGState(context)
var t0 = CGContextGetCTM(context)
t0 = CGAffineTransformInvert(t0)
CGContextConcatCTM(context, t0)
//Begin drawing setup
CGContextBeginPath(context)
CGContextSetRGBStrokeColor(context, 0, 0, 0, 1)
CGContextSetLineWidth(context, 2.0)
//Start drawing polygon
let center = CGPointMake(polySize, polySize)
CGContextMoveToPoint(context, center.x, center.y + polySize)
for i in 0..<6
{
let x = polySize * CGFloat(sinf(Float(i) * 2.0 * Float(M_PI) / 6))
let y = polySize * CGFloat(cosf(Float(i) * 2.0 * Float(M_PI) / 6))
CGContextAddLineToPoint(context, center.x + x, center.y + y)
}
//Finish Drawing
CGContextClosePath(context)
CGContextSetFillColor(context, CGColorGetComponents(UIColor.formen25().CGColor))
CGContextDrawPath(context, CGPathDrawingMode.FillStroke)
CGContextFillPath(context)
CGContextRestoreGState(context)
}
}
In the storyboard I made the UIButtons width equal the height of his view with a multiplier = 0.2.
If I start the app on an Iphone 5 I get the following result:
But on an Iphone 6s plus it looks like this
The height of the View where the buttons are placed are changed by the user. Even if I use a static size for the buttons they are wrong on the iphone 6s plus. Is this a mistake of my HexagonButton?
Maybe I have to place the buttons in a specific way? I added the both UIButtons in the middle in a stackview and centered(horizontal and vertically) the stackview in the view. Then I centered the other UIButtons and gave them a top-and bottomspace(-14) to the stackview. I made all buttons the same size.
EDIT:
If I give the button a backgroundcolor it looks like this:

Swift add line above to control

In the below screen, I want to add horizontal line above to "Item" label and after "Add" button (below to the add button, I have dynamic table). UIGraphicsGetCurrentContext() doesn't work here.
Can someone help me how to do this?
It is simple to add a subview to act as a line. For example:
Swift 4
var lineView = UIView(frame: CGRect(x: 0, y: 100, width: 320, height: 1.0))
lineView.layer.borderWidth = 1.0
lineView.layer.borderColor = UIColor.black.cgColor
self.view.addSubview(lineView)
Objective C
UIView * lineview = [[UIView alloc] initWithFrame:CGRectMake(0, 100,320,1)];
lineview.layer.borderColor = [UIColor blackColor].CGColor;
lineview.layer.borderWidth = 1.0;
[self.view addSubview:lineview];
Or you can refer to this link to add CALayer or draw a view
how do you draw a line programmatically from a view controller?
You can achieve this in Storyboard.
All you have to do is drag a UIView with height = 1 and width whatever is good for you (ideally equal to screen width). Place it where you want the lines to be.
For Swift 3:
let lineView = UIView(frame: CGRect(x:0,
y: self.yourLabel.height - 1 ,
width: self.yourLabel.frame.width,
height: 1.4
)
)
lineView.backgroundColor = UIColor.blue
self.yourLabel.addSubview(lineView)

How to compute the frame of a UIView before the transform?

Question
I have a UIView and I apply to it a CGAffineTransform. I would like to be able to know the frame of the view if the transform had not be applied.
I am looking for a (simple) solution that handles the case where the transform is the "zero-transform" (which is not invertible).
My attempt
The following does not work for the "zero-transform", I guess.
CGRect result ;
CGAffineTransform transform = self.transform ;
result = CGRectApplyAffineTransform(self.frame, CGAffineTransformInvert(transform)) ;
return result ;
Why?
I need to do this for an animation:
initial settings: I set the transform "to 0". The view is inserted but the frames of all the elements do as if the view was not here.
final settings: I compute the frames of all my elements, and this time I take into account the new view. I set its transform "to 1".
Remarks
My transform is a scale transform.
transform does not affect center nor bounds.
So, you can calculate it by this simple code:
CGPoint center = view.center;
CGSize size = view.bounds.size;
CGRect frameForTransformIdentity = CGRectMake(
center.x - size.width / 2,
center.y - size.height / 2,
size.width,
size.height
);
Swift 4.1 version:
extension UIView
{
var frameWithoutTransform: CGRect
{
let center = self.center
let size = self.bounds.size
return CGRect(x: center.x - size.width / 2,
y: center.y - size.height / 2,
width: size.width,
height: size.height)
}
}

UIPanGestureRecognizer - Translations and rotations not happening evenly with negatives vs positives

Towards the top of the file I have this:
#define DEGREES_TO_RADIANS(x) (M_PI * x / 180.0)
In viewdidload I have this:
imageView.layer.anchorPoint = CGPointMake(0.5,0.5);
Then finally in the gesture recognizer I have this:
- (IBAction)handlePan:(UIPanGestureRecognizer *)sender {
CGPoint translation = [sender translationInView:self.view];
xPos += translation.x;
if(xPos > 150) xPos = 150;
if(xPos < -150) xPos = -150;
float rotate = 0;
if(xPos >= 50) {
rotate = (xPos - 50) * 0.025;
} else if(xPos <= -50) {
rotate = (xPos + 50) * 0.025;
}
imageView.transform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(rotate)), (xPos * 0.35), 0);
}
This appears to be applying the exact same effects to negatives (left) and positives (right).
With the UIImageView that is being rotated being placed in the center of the screen horizontally, and its anchor set to the center I would expect the maximum in both directions to be cut off equally by the edge of the screen. Instead the image goes much further to the right.
Left effect (negative):
Right effect (positive):
It looks like autolayout changes the anchor point as the image view is rotated and the frame changes.

Resources