【问题标题】:How to create several UIButtons along a path/BezierCurve?如何沿路径/BezierCurve 创建多个 UIButton?
【发布时间】:2013-06-20 23:05:16
【问题描述】:

如何沿路径/BezierCurve 创建对象?换句话说,我怎样才能沿着给定的路径创建多个 UIButton,并且沿着同一路径具有给定的间隔?

我看过很多关于移动物体的问题。但我需要一个解决方案来实际创建它们。

我想沿着路径走,并为每个 X 点/距离创建一个对象。像这样:

....@....@....@....@....

在这种情况下,每4个点,获取位置,并在那里创建一个UIButton。

【问题讨论】:

  • 请澄清您的问题。您想沿路径创建对象但不想在屏幕上绘制它们?嗯?
  • 我正在尝试沿路径创建多个 UIButton 对象。这可能吗?对于每个 X 点/距离,我需要返回 X/Y 位置,以便创建它们。
  • 我希望能够通过沿该路径的动画返回 X/Y 位置,但我不确定如何告诉动画触发每个 X 点的给定选择器/距离,同时返回位置。
  • 使用 UIButton 的setFrame 沿着路径循环和创建 UIButtons 非常容易,但是您对动画等非常不清楚。您可以越清楚地说明您的问题,就越容易这将是人们帮助你。
  • 对不起,我尽量说清楚。你将如何以给定的间隔沿着给定的路径创建 UIButton?这就是我要找的。我会更新问题以更好地反映我的问题。

标签: ios objective-c uibezierpath


【解决方案1】:

iOS 没有直接为您提供沿路径间隔的点的公共 API。但是有一个迂回的方法可以做到这一点。假设您希望路径上的点相隔 X 距离。

首先,创建一个包含您的路径的CGPathRef。 (如果您愿意,可以构造一个UIBezierPath,然后获取它的CGPath 属性。)

然后,调用CGPathCreateCopyByDashingPath,使用破折号{ X, X }。例如:

static CGFloat const kSpace = 10;
CGPathRef dashedPath = CGPathCreateCopyByDashingPath(path, NULL, 0,
    (CGFloat const []){ kSpace, kSpace }, 2);

这将返回一个包含多个子路径的新路径。每个子路径是原始路径的长度 X 段,并沿原始路径与其相邻子路径相隔 X 距离。因此,子路径的端点沿原始路径以长度 X 的间隔间隔开。

所以,最后,使用CGPathApply 枚举虚线路径,选择端点并在那里创建按钮。首先,您需要将其包装在一个接受块的函数中:

static void applyBlockToPathElement(void *info, const CGPathElement *element) {
    void (^block)(const CGPathElement *) = (__bridge void (^)(const CGPathElement *))(info);
    block(element);
}

void MyCGPathApplyBlock(CGPathRef path, void (^block)(const CGPathElement *element)) {
    CGPathApply(path, (__bridge void *)(block), applyBlockToPathElement);
}

然后您可以应用一个块来查找每个子路径端点并在那里创建一个按钮。假设你有一个名为 createButtonAtPoint: 的方法,这样的事情应该可以工作:

__block BOOL isInSubpath = NO;
__block CGPoint subpathStart = CGPointZero;
__block CGPoint currentPoint = CGPointZero;
MyCGPathApplyBlock(dashedPath, ^(const CGPathElement *element) {
    switch (element->type) {
        case kCGPathElementMoveToPoint:
            if (isInSubpath) {
                [self createButtonAtPoint:currentPoint];
                isInSubpath = NO;
            }
            currentPoint = element->points[0];
            break;

        case kCGPathElementCloseSubpath:
            // This should not appear in a dashed path.
            break;

        case kCGPathElementAddLineToPoint:
        case kCGPathElementAddQuadCurveToPoint:
        case kCGPathElementAddCurveToPoint:
            if (!isInSubpath) {
                [self createButtonAtPoint:currentPoint];
                isInSubpath = YES;
            }
            int pointIndex =
                element->type == kCGPathElementAddLineToPoint ? 0
                : element->type == kCGPathElementAddQuadCurveToPoint ? 1
                : /* element->type == kCGPathElementAddCurveToPoint ? */ 2;
            currentPoint = element->points[pointIndex];
            break;
    }
});

【讨论】:

  • 你完全理解我的问题。我仍在努力解决它,但是您的解决方案看起来很有希望!谢谢你这么好的回答,先生。
  • 刚刚在我的代码中实现了这一点。天哪,我很惊讶您的代码中没有一个拼写错误,而且您很容易就想到了这一点。它完美无缺!它仍然比我对 API 的了解略超前,我认为我什至不会接近做到这一点。再次感谢您!
  • 谢谢。我在 Xcode 中编写代码以避免错误,然后将其复制到答案中。我不会说这很容易。就是I've used this technique before
【解决方案2】:

您的问题解决了吗?如果没有,看看这个是否有帮助

  //if the interval is kown as float, suggesting it named padding

  //then you can

  for(i=0;i<numOfPaddings;i++){
      //create a button
      UIButton *aButton = [UIButton buttonWithType:UIButtonRoundRect/*I forgot how to spell,but it does not metter*/];
      //Set your button's position base on padding
      [aButton setFrame:CGRectMake(padding+padding*i,20,50,20)];
  }

【讨论】:

  • @rob mayoff 完美回答了我的问题,但感谢您的帮助!干杯 =)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-23
  • 1970-01-01
  • 1970-01-01
  • 2011-07-17
  • 2015-07-24
相关资源
最近更新 更多