- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我正在编写一个应用程序,我在其中使用 UIKit Dynamics 来模拟不同圈子之间的交互。
我使用以下代码创建我的圈子:
self = [super initWithFrame:CGRectMake(location.x - radius/2.0, location.y - radius/2, radius, radius)];
if (self) {
[self.layer setCornerRadius: radius /2.0f];
self.clipsToBounds = YES;
self.layer.masksToBounds = YES;
self.backgroundColor = color;
self.userInteractionEnabled = NO;
}
return self;
其中 location 表示圆的所需位置,radius 表示其半径。
然后我将这些圆圈添加到不同的 UIBehaviours,方法是:
[_collision addItem:circle];
[_gravity addItem:circle];
[_itemBehaviour addItem:circle];
itemBaviour 定义如下:
_itemBehaviour = [[UIDynamicItemBehavior alloc] initWithItems:@[square]];
_itemBehaviour.elasticity = 1;
_itemBehaviour.friction = 0;
_itemBehaviour.resistance = 0;
_itemBehaviour.angularResistance = 0;
_itemBehaviour.allowsRotation = NO;
我遇到的问题是,我的圆圈表现得像正方形。当以某种方式被击中时,它们会获得角动量并失去速度。如果它们再次碰撞,有时角动量会再次恢复为速度。这对于正方形来说看起来很正常,但是当 View 是圆形时,就像我的情况一样,这种行为看起来很奇怪而且不自然。
打开一些调试选项,我做了这个截图:
如您所见,圆圈看起来是正方形。
所以我的问题是,我怎样才能创建一个真正的圆形 UIVIew,并且在 UIKit Dynamics 中表现如此?
最佳答案
我知道这个问题早于 iOS 9,但为了 future 读者的利益,您现在可以使用 collisionBoundsType
定义 View UIDynamicItemCollisionBoundsTypePath
和一个循环 collisionBoundingPath
.
因此,虽然您不能“创建一个真正的圆形 UIView
”,但您可以定义一个路径来定义在 View 内呈现的形状以及动画师,产生圆形 View 的效果(即使 View 本身显然仍然是矩形,因为所有 View 都是):
@interface CircleView: UIView
@property (nonatomic) CGFloat lineWidth;
@property (nonatomic, strong) CAShapeLayer *shapeLayer;
@end
@implementation CircleView
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
[self configure];
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self configure];
}
return self;
}
- (instancetype)init {
return [self initWithFrame:CGRectZero];
}
- (void)configure {
self.translatesAutoresizingMaskIntoConstraints = false;
// create shape layer for circle
self.shapeLayer = [CAShapeLayer layer];
self.shapeLayer.strokeColor = [[UIColor blueColor] CGColor];
self.shapeLayer.fillColor = [[[UIColor blueColor] colorWithAlphaComponent:0.5] CGColor];
self.lineWidth = 3;
[self.layer addSublayer:self.shapeLayer];
}
- (void)layoutSubviews {
[super layoutSubviews];
// path of shape layer is with respect to center of the `bounds`
CGPoint center = CGPointMake(self.bounds.origin.x + self.bounds.size.width / 2, self.bounds.origin.y + self.bounds.size.height / 2);
self.shapeLayer.path = [[self circularPathWithLineWidth:self.lineWidth center:center] CGPath];
}
- (UIDynamicItemCollisionBoundsType)collisionBoundsType {
return UIDynamicItemCollisionBoundsTypePath;
}
- (UIBezierPath *)collisionBoundingPath {
// path of collision bounding path is with respect to center of the dynamic item, so center of this path will be CGPointZero
return [self circularPathWithLineWidth:0 center:CGPointZero];
}
- (UIBezierPath *)circularPathWithLineWidth:(CGFloat)lineWidth center:(CGPoint)center {
CGFloat radius = (MIN(self.bounds.size.width, self.bounds.size.height) - self.lineWidth) / 2;
return [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:0 endAngle:M_PI * 2 clockwise:true];
}
@end
然后,当您进行碰撞时,它将遵循 collisionBoundingPath
值:
self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
// create circle views
CircleView *circle1 = [[CircleView alloc] initWithFrame:CGRectMake(60, 100, 80, 80)];
[self.view addSubview:circle1];
CircleView *circle2 = [[CircleView alloc] initWithFrame:CGRectMake(250, 150, 120, 120)];
[self.view addSubview:circle2];
// have them collide with each other
UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:@[circle1, circle2]];
[self.animator addBehavior:collision];
// with perfect elasticity
UIDynamicItemBehavior *behavior = [[UIDynamicItemBehavior alloc] initWithItems:@[circle1, circle2]];
behavior.elasticity = 1;
[self.animator addBehavior:behavior];
// and push one of the circles
UIPushBehavior *push = [[UIPushBehavior alloc] initWithItems:@[circle1] mode:UIPushBehaviorModeInstantaneous];
[push setAngle:0 magnitude:1];
[self.animator addBehavior:push];
产生:
顺便提一下,the documentation概述了路径的一些限制:
The path object you create must represent a convex polygon with counter-clockwise or clockwise winding, and the path must not intersect itself. The (0, 0) point of the path must be located at the center point of the corresponding dynamic item. If the center point does not match the path’s origin, collision behaviors may not work as expected.
但是一个简单的圆形路径很容易满足这些标准。
或者,对于 Swift 用户:
class CircleView: UIView {
var lineWidth: CGFloat = 3
var shapeLayer: CAShapeLayer = {
let _shapeLayer = CAShapeLayer()
_shapeLayer.strokeColor = UIColor.blue.cgColor
_shapeLayer.fillColor = UIColor.blue.withAlphaComponent(0.5).cgColor
return _shapeLayer
}()
override func layoutSubviews() {
super.layoutSubviews()
layer.addSublayer(shapeLayer)
shapeLayer.lineWidth = lineWidth
let center = CGPoint(x: bounds.midX, y: bounds.midY)
shapeLayer.path = circularPath(lineWidth: lineWidth, center: center).cgPath
}
private func circularPath(lineWidth: CGFloat = 0, center: CGPoint = .zero) -> UIBezierPath {
let radius = (min(bounds.width, bounds.height) - lineWidth) / 2
return UIBezierPath(arcCenter: center, radius: radius, startAngle: 0, endAngle: .pi * 2, clockwise: true)
}
override var collisionBoundsType: UIDynamicItemCollisionBoundsType { return .path }
override var collisionBoundingPath: UIBezierPath { return circularPath() }
}
class ViewController: UIViewController {
let animator = UIDynamicAnimator()
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let circle1 = CircleView(frame: CGRect(x: 60, y: 100, width: 80, height: 80))
view.addSubview(circle1)
let circle2 = CircleView(frame: CGRect(x: 250, y: 150, width: 120, height: 120))
view.addSubview(circle2)
animator.addBehavior(UICollisionBehavior(items: [circle1, circle2]))
let behavior = UIDynamicItemBehavior(items: [circle1, circle2])
behavior.elasticity = 1
animator.addBehavior(behavior)
let push = UIPushBehavior(items: [circle1], mode: .instantaneous)
push.setAngle(0, magnitude: 1)
animator.addBehavior(push)
}
}
关于ios - UIKit 动态 : recognize rounded Shapes and Boundaries,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23347466/
在 HTML 表单中发布用于创建多部分边界的有效字符是什么? 最佳答案 根据 RFC 2046 ,第 5.1.1 节: boundary := 0*69 bcharsnospace bchars
大家好,我卡颂。 本文会讲解React中Error Boundaries的完整实现逻辑。 一张图概括: 这里简单讲解下React工作流程,后文有用。分为三步: 触发更新
我正在尝试编写我的第一个 Elasticsearch 分析插件,我从 github 上找到了一个可扩展标准分析器插件项目:elasticsearch-analysis-standardext ,在项目
我正在开发一款游戏,其中你是一个发射子弹的简单圆圈及其多人游戏等等。好吧,我试图让边界有点像你必须经历的迷宫类型的东西,我尝试过这样的碰撞检测: public void checkCollisions
我想设置一个模式,该模式将找到一个受第一次出现的“边界”限制的捕获组。但是现在使用最后一个边界。 例如: String text = "this should match from A to the
我想根据旋转矩阵计算欧拉角,以便找出与该旋转关联的方向。为此,我正在使用 MATLAB 和函数 rotm2eul,它首先提供关于 x 轴的旋转,然后是关于 y 轴的旋转,最后是关于 z 轴的旋转。 我
这个问题已经有答案了: No out of bounds error (7 个回答) 已关闭 7 年前。 在下面的代码中,我已将值分配给超出数组边界的数组元素,在 CLI 的 Linux 环境中,代码
我尝试使用 Python 请求模块将一些数据和文件发送到我的 django rest 应用程序,但出现以下错误。 raise MultiPartParserError('Invalid bou
我正在尝试为我玩的游戏开发一个在线 map 编辑程序。 map 的数据有点大。如果我发送每个方格的数据,中等大小 map 的数据接近 1 mb。 我认为我可以做的是在 map 上找到边界并以此为基础创
“Android 设计”网站推荐可 ScrollView 的“边界反馈”。 http://developer.android.com/design/style/touch-feedback.html
引用此 post 中给出的最佳答案,我注意到当 rnd=sum_of_weight 时,它在边界情况下失败。解决方法是在 [0,sum_of_weight) 中生成随机数,但是我想知道为什么代码对于这
在多部分(即 Content-Type=multipart/form-data)形式中,HTTP 服务器应该接受的边界字符串的长度是否有上限? 据我所知,相关的 RFC 说 70 个字符: RFC26
我有一串任意字符,其中一些是数字。我想将字符串分成由数字和非数字组成的字段。例如,如果我的字符串的值为 'abc34d-f9',我想得到一个数组 ['abc','34','d-f','9'] 我快到了
我正在尝试创建有关 Scooter 系统的用例图。我已经创建了图表,你可以在这里找到它: Use Case Diagram : 我收到了一些关于这张图的评论: 系统(或滑板车供应商)不是 Actor
我正在尝试从桌面上传图像,但找不到多部分边界的错误。如何设置上传图片的边界?第一次上传图片,请指教。 用户上传图片时的html事件监听 document.getElementById('image-f
我在发送带有文本附件的电子邮件时遇到问题(没有附件,一切都很好)。我正在使用 actionmailer 3.2.11 并尝试通过 Amazon SES 发送电子邮件。在我看来,亚马逊 snmp 服务器
来自 Akka 文档,Pipelining and Parallelism Akka Streams processing stages (be it simple operators on Flow
有一个 DAL 库公开了十几个存储库。每个实体一个存储库。有 PersonRepository 和 PhotoRepository。 当我向存储库添加新方法并且方法处理实体时,很明显我必须将它放在哪里
引用:perl string catenation and substitution in a single line? 给定输入: home/////test/tmp/ 以及所需的转换为: /hom
我有一个看起来像这样的大文件: V1 SNP1 SNP2 SNP3 SNP4 SNP5 SNP6 SNP7 SNP8 SNP9 GROUP1 1 NA 2 1 1
我是一名优秀的程序员,十分优秀!