I am looking for a way to create a CIRCULAR UIView
that is resizable and stays centered (see image). The CIRCULAR view in this example is a UIView
subclass WCSDailyGoal
.
ContainerView.m
- (void)createDailyGoalView
{
_dailyGoalView = [[WCSDailyGoalView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
_dailyGoalView.delegate = self;
_dailyGoalView.goal = 200;
_dailyGoalView.center = self.view.center;
[self.view addSubview:_dailyGoalView];
}
WCSDailyGoal.m
- (void)setGoal:(CGFloat)goal
{
CGPoint saveCenter = self.center;
CGRect newFrame = CGRectMake(self.frame.origin.x, self.frame.origin.y, goal, goal);
self.frame = newFrame;
self.layer.cornerRadius = goal / 2.0;
self.center = saveCenter;
}
I was able to achieve this effect by making custom view (following code is in swift):
class ResizableCircleView: UIView {
var maxSize: CGFloat = 100
var minSize: CGFloat = 10
private var dragRecognizer: UIPanGestureRecognizer!
private var currentScale: CGFloat = 1
private var defaultSize: CGFloat { return frame.width / currentScale }
override func layoutSubviews() {
super.layoutSubviews()
if dragRecognizer == nil{
dragRecognizer = UIPanGestureRecognizer(target: self, action: "handleDrag:")
addGestureRecognizer(dragRecognizer)
}
backgroundColor = UIColor.blackColor()
layer.cornerRadius = frame.width / 2
clipsToBounds = true
}
func handleDrag(recognizer: UIPanGestureRecognizer){
let inTopArea = recognizer.locationInView(self).y < frame.height / 2
let dy = recognizer.translationInView(self).y
var newSize = frame.height + (inTopArea ? -1 : 1) * dy
newSize = min(maxSize, newSize)
newSize = max(minSize, newSize)
currentScale = newSize/defaultSize
transform = CGAffineTransformMakeScale(currentScale, currentScale)
recognizer.setTranslation(CGPointZero, inView: self)
}
}
You can adjust max and min sizes by setting desired values to maxSize
and minSize
. Hope this will help.
From your question it's not clear exactly what you want, nor what your problem is, but I'll try and answer it based on my assumptions of what you mean.
First of all - the view shouldn't manage its own position. The view controller should, or the parent view, ideally in viewDidLayoutSubviews
or layoutSubviews
as appropriate. self.center = ...
is always the wrong thing to do, because exactly where a view's center should be depends on the size and shape of its parent view, and a child view shouldn't have to know such things about its parent.
Second, there's no such thing as a 'round' UIView. You can make a square UIView
and mask its layer so it appears round by making a circle using a CAShapeLayer
with a circle as its path, then use myView.layer.mask = circleShapeLayer
to apply the mask.
To handle the interaction, use a PanGestureRecognizer
on the parent view. In gestureRecognizerShouldBegin
, determine if the touch is at about the right place to begin interaction (inside the circle? on the circle radius? on the circle radius at the top?), and return YES
or NO
as appropriate. In your gesture recognizer action function, calculate a new size for the circle and set the size of the circular view using myView.bounds = CGRectMake(0, 0, 2*circleRadius, 2*circleRadius);
.
This should do what you need.