已编辑
有关最新项目,请参阅 Nathan 的评论部分。只剩下一个问题:获得正确的按钮。
已编辑
我想要一个用户可以旋转的 UIView。该 UIView 应包含一些可以单击的 UIButton。我遇到了困难,因为我正在使用 UIControl 子类来制作旋转 View ,并且在该子类中我必须禁用用户在 UIControl 中的 subview 上的交互(使其旋转),这可能导致 UIButtons 不可点击。如何制作一个用户可以旋转的 UIView 并且包含可点击的 UIButtons? This是指向我的项目的链接,可让您抢先一步:它包含 UIButtons 和可旋转的 UIView。但是我无法点击 UIButtons。
有更多细节的旧问题
我正在使用这个 pod:https://github.com/joshdhenry/SpinWheelControl我想对按钮点击使用react。我可以添加按钮,但是我无法在按钮中接收点击事件。我正在使用 hitTests 但它们从未被执行过。用户应该旋转轮子并能够单击其中一个饼图中的按钮。
在此处获取项目:https://github.com/Jasperav/SpinningWheelWithTappableButtons
查看下面我在 pod 文件中添加的代码:
我在 SpinWheelWedge.swift 中添加了这个变量:
let button = SpinWheelWedgeButton()
我添加了这个类:
class SpinWheelWedgeButton: TornadoButton {
public func configureWedgeButton(index: UInt, width: CGFloat, position: CGPoint, radiansPerWedge: Radians) {
self.frame = CGRect(x: 0, y: 0, width: width, height: 30)
self.layer.anchorPoint = CGPoint(x: 1.1, y: 0.5)
self.layer.position = position
self.transform = CGAffineTransform(rotationAngle: radiansPerWedge * CGFloat(index) + CGFloat.pi + (radiansPerWedge / 2))
self.backgroundColor = .green
self.addTarget(self, action: #selector(pressed(_:)), for: .touchUpInside)
}
@IBAction func pressed(_ sender: TornadoButton){
print("hi")
}
}
这是 TornadoButton 类:
class TornadoButton: UIButton{
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
let pres = self.layer.presentation()!
let suppt = self.convert(point, to: self.superview!)
let prespt = self.superview!.layer.convert(suppt, to: pres)
if (pres.hitTest(suppt)) != nil{
return self
}
return super.hitTest(prespt, with: event)
}
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
let pres = self.layer.presentation()!
let suppt = self.convert(point, to: self.superview!)
return (pres.hitTest(suppt)) != nil
}
}
我将其添加到 SpinWheelControl.swift 的循环“for wedgeNumber in”中
wedge.button.configureWedgeButton(index: wedgeNumber, width: radius * 2, position: spinWheelCenter, radiansPerWedge: radiansPerWedge)
wedge.addSubview(wedge.button)
这是我认为可以在 SpinWheelControl.swift 中检索按钮的地方:
override open func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
let p = touch.location(in: touch.view)
let v = touch.view?.hitTest(p, with: nil)
print(v)
}
只有“v”始终是旋转轮本身,而不是按钮。我也没有看到打印的按钮,并且永远不会执行 hittest。这段代码有什么问题,为什么 hitTest 不执行?我宁愿有一个普通的 UIBUtton,但我认为我需要为此进行 HitTest 。
最佳答案
这是针对您的特定项目的解决方案:
在drawWheel在 SpinWheelControl.swift 中发挥作用, 在 spinWheelView 上启用用户交互.为此,请删除以下行:
self.spinWheelView.isUserInteractionEnabled = false
再次在drawWheel函数,使按钮成为 spinWheelView 的 subview , 而不是 wedge .在楔形之后添加按钮作为 subview ,因此它会出现在楔形层的顶部。
旧的:
wedge.button.configureWedgeButton(index: wedgeNumber, width: radius * 0.45, position: spinWheelCenter, radiansPerWedge: radiansPerWedge)
wedge.addSubview(wedge.button)
spinWheelView.addSubview(wedge)
新:
wedge.button.configureWedgeButton(index: wedgeNumber, width: radius * 0.45, position: spinWheelCenter, radiansPerWedge: radiansPerWedge)
spinWheelView.addSubview(wedge)
spinWheelView.addSubview(wedge.button)
创建一个新的 UIView将触摸传递到其 subview 的子类。
class PassThroughView: UIView {
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
for subview in subviews {
if !subview.isHidden && subview.alpha > 0 && subview.isUserInteractionEnabled && subview.point(inside: convert(point, to: subview), with: event) {
return true
}
}
return false
}
}
在 drawWheel 的最开始函数,声明 spinWheelView类型为 PassThroughView .这将允许按钮接收触摸事件。
spinWheelView = PassThroughView(frame: self.bounds)
通过这些少量更改,您应该会得到以下行为:
(按下任何按钮时,消息将打印到控制台。)
此解决方案允许用户像往常一样旋转滚轮,以及点击任何按钮。但是,这可能不是满足您需求的完美解决方案,因为存在一些限制:
根据您的需要,您可以考虑构建自己的 Spinner,而不是依赖第三方 pod。这个 pod 的困难在于它使用了 beginTracking(_ touch: UITouch, with event: UIEvent?)和相关功能而不是手势识别器。如果你使用手势识别器,那么使用所有 UIButton 会更容易。功能。
或者,如果您只想识别楔形范围内的触地事件,您可以继续使用 hitTest进一步的想法。
编辑:确定按下了哪个按钮。
如果我们知道 selectedIndex车轮和起点selectedIndex ,我们可以计算出按下了哪个按钮。
目前,开始 selectedIndex为 0,按钮标签顺时针增加。点击所选按钮(tag = 0),打印 7,这意味着按钮在其起始状态下“旋转”了 7 个位置。如果车轮从不同的位置开始,这个值就会不同。
这是一个快速函数,它使用两条信息来确定被点击的按钮的标签:滚轮的 selectedIndex和 subview.tag来自当前point(inside point: CGPoint, with event: UIEvent?)实现 PassThroughView .
func determineButtonTag(selectedIndex: Int, subviewTag: Int) -> Int {
return subviewTag + (selectedIndex - 7)
}
再次重申,这绝对是一种 hack,但它确实有效。如果您计划继续向该微调器控件添加功能,我强烈建议您改为创建自己的控件,以便您可以从一开始就设计它以满足您的需求。
关于ios - 在 UIControl/可旋转 View 中获取 UIButton 的点击事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46574223/
我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何
我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>
我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R
我是rails的新手,想在form字段上应用验证。myviewsnew.html.erb.....模拟.rbclassSimulation{:in=>1..25,:message=>'Therowmustbebetween1and25'}end模拟Controller.rbclassSimulationsController我想检查模型类中row字段的整数范围,如果不在范围内则返回错误信息。我可以检查上面代码的范围,但无法返回错误消息提前致谢 最佳答案 关键是您使用的是模型表单,一种显示ActiveRecord模型实例属性的表单。c
有没有办法在这个简单的get方法中添加超时选项?我正在使用法拉第3.3。Faraday.get(url)四处寻找,我只能先发起连接后应用超时选项,然后应用超时选项。或者有什么简单的方法?这就是我现在正在做的:conn=Faraday.newresponse=conn.getdo|req|req.urlurlreq.options.timeout=2#2secondsend 最佳答案 试试这个:conn=Faraday.newdo|conn|conn.options.timeout=20endresponse=conn.get(url
这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下
我有一个存储主机名的Ruby数组server_names。如果我打印出来,它看起来像这样:["hostname.abc.com","hostname2.abc.com","hostname3.abc.com"]相当标准。我想要做的是获取这些服务器的IP(可能将它们存储在另一个变量中)。看起来IPSocket类可以做到这一点,但我不确定如何使用IPSocket类遍历它。如果它只是尝试像这样打印出IP:server_names.eachdo|name|IPSocket::getaddress(name)pnameend它提示我没有提供服务器名称。这是语法问题还是我没有正确使用类?输出:ge
我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c
我安装了ruby版本管理器,并将RVM安装的ruby实现设置为默认值,这样'哪个ruby'显示'~/.rvm/ruby-1.8.6-p383/bin/ruby'但是当我在emacs中打开inf-ruby缓冲区时,它使用安装在/usr/bin中的ruby。有没有办法让emacs像shell一样尊重ruby的路径?谢谢! 最佳答案 我创建了一个emacs扩展来将rvm集成到emacs中。如果您有兴趣,可以在这里获取:http://github.com/senny/rvm.el
我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的