Resizable Centered Circular UIView

2019-04-15 19:46发布

问题:

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;
}

回答1:

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.



回答2:

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.