我正在尝试绘制一个具有四个圆形 handle 的矩形。这是它的样子:
o----o
| |
| |
o----o
圆形 Handlebars 很“火”。换句话说,当用户触摸它时, handle 可以四处移动,而其余的点则被锚定。我想知道是否有人有编码此功能的方法。我正在查看 UIBezierPath 以绘制带圆圈的矩形,但我很难考虑如何让用户仅点击圆圈。我在想它可能需要五个不同的 UIBezierPath 对象,但最终 UI 将由这些对象的倍数组成。
如有任何建议,我们将不胜感激。谢谢。
最佳答案
我根本不会将它绘制为具有复杂 UIBezierPath 的单个形状。我会把它想象成 6 个不同的部分。一个容器、一个矩形和 4 个圆圈。
我会有一个简单的容器 UIView,它有一个矩形 View 和四个圆形 UIViews 在它的角落。然后在每个圆圈上放置一个 UIPanGestureRecognizer。在手势处理程序中,移动圆心并将底层矩形调整相同的量。这将避免任何复杂的路径或数学运算,并使矩形本身的加减量变得简单。
更新:代码!
我创建了一个独立的 UIView 子类来处理所有事情。您可以像这样创建一个:
HandlesView *view = [[HandlesView alloc] initWithFrame:self.view.bounds];
[view setAutoresizingMask:UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth];
[view setBackgroundColor:[UIColor redColor]];
[self.view addSubview:view];
// A custom property that contains the selected area of the rectangle. Its updated while resizing.
[view setSelectedFrame:CGRectMake(128.0, 128.0, 200.0, 200.0)];
View 本身的框架是总的可拖动区域。所选框架是内部可见矩形。
//
// HandlesView.h
// handles
//
// Created by Ryan Poolos on 2/12/13.
// Copyright (c) 2013 Ryan Poolos. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
@interface HandlesView : UIView
@property (nonatomic, readwrite) CGRect selectedFrame;
@end
这是实现。
//
// HandlesView.m
// handles
//
// Created by Ryan Poolos on 2/12/13.
// Copyright (c) 2013 Ryan Poolos. All rights reserved.
//
#import "HandlesView.h"
@interface HandlesView ()
{
UIView *rectangle;
NSArray *handles;
NSMutableArray *touchedHandles;
UIView *circleTL;
UIView *circleTR;
UIView *circleBL;
UIView *circleBR;
}
@end
@implementation HandlesView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
rectangle = [[UIView alloc] initWithFrame:CGRectInset(self.bounds, 22.0, 22.0)];
[self addSubview:rectangle];
// Create the handles and position.
circleTL = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 44.0, 44.0)];
[circleTL setCenter:CGPointMake(CGRectGetMinX(rectangle.frame), CGRectGetMinY(rectangle.frame))];
circleTR = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 44.0, 44.0)];
[circleTR setCenter:CGPointMake(CGRectGetMaxX(rectangle.frame), CGRectGetMinY(rectangle.frame))];
circleBL = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 44.0, 44.0)];
[circleBL setCenter:CGPointMake(CGRectGetMinX(rectangle.frame), CGRectGetMaxY(rectangle.frame))];
circleBR = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 44.0, 44.0)];
[circleBR setCenter:CGPointMake(CGRectGetMaxX(rectangle.frame), CGRectGetMaxY(rectangle.frame))];
handles = @[ circleTL, circleTR, circleBL, circleBR ];
for (UIView *handle in handles) {
// Round the corners into a circle.
[handle.layer setCornerRadius:(handle.frame.size.width / 2.0)];
[self setClipsToBounds:YES];
// Add a drag gesture to the handle.
[handle addGestureRecognizer:[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)]];
// Add the handle to the screen.
[self addSubview:handle];
}
}
return self;
}
- (void)setSelectedFrame:(CGRect)selectedFrame
{
[rectangle setFrame:selectedFrame];
[circleTL setCenter:CGPointMake(CGRectGetMinX(rectangle.frame), CGRectGetMinY(rectangle.frame))];
[circleTR setCenter:CGPointMake(CGRectGetMaxX(rectangle.frame), CGRectGetMinY(rectangle.frame))];
[circleBL setCenter:CGPointMake(CGRectGetMinX(rectangle.frame), CGRectGetMaxY(rectangle.frame))];
[circleBR setCenter:CGPointMake(CGRectGetMaxX(rectangle.frame), CGRectGetMaxY(rectangle.frame))];
}
- (CGRect)selectedFrame
{
return rectangle.frame;
}
// Forward the background color.
- (void)setBackgroundColor:(UIColor *)backgroundColor
{
// Set the container to clear.
[super setBackgroundColor:[UIColor clearColor]];
// Set our rectangle's color.
[rectangle setBackgroundColor:[backgroundColor colorWithAlphaComponent:0.5]];
for (UIView *handle in handles) {
[handle setBackgroundColor:backgroundColor];
}
}
- (void)handlePan:(UIPanGestureRecognizer *)gesture
{
// The handle we're moving.
UIView *touchedHandle = gesture.view;
// Keep track of touched Handles.
if (!touchedHandles) {
touchedHandles = [NSMutableArray array];
}
switch (gesture.state) {
case UIGestureRecognizerStateBegan:
[touchedHandles addObject:touchedHandle];
break;
case UIGestureRecognizerStateChanged:
{
CGPoint tranlation = [gesture translationInView:self];
// Calculate this handle's new center
CGPoint newCenter = CGPointMake(touchedHandle.center.x + tranlation.x, touchedHandle.center.y + tranlation.y);
// Move corresponding circles
for (UIView *handle in handles) {
if (handle != touchedHandle && ![touchedHandles containsObject:handle]) {
// Match the handles horizontal movement
if (handle.center.x == touchedHandle.center.x) {
handle.center = CGPointMake(newCenter.x, handle.center.y);
}
// Match the handles vertical movement
if (handle.center.y == touchedHandle.center.y) {
handle.center = CGPointMake(handle.center.x, newCenter.y);
}
}
}
// Move this circle
[touchedHandle setCenter:newCenter];
// Adjust the Rectangle
// The origin and just be based on the Top Left handle.
float x = circleTL.center.x;
float y = circleTL.center.y;
// Get the width and height based on the difference between handles.
float width = abs(circleTR.center.x - circleTL.center.x);
float height = abs(circleBL.center.y - circleTL.center.y);
[rectangle setFrame:CGRectMake(x, y, width, height)];
[gesture setTranslation:CGPointZero inView:self];
}
break;
case UIGestureRecognizerStateEnded:
[touchedHandles removeObject:touchedHandle];
break;
default:
break;
}
}
@end
这只是概念验证。有很多缺失的注意事项,比如能够拖到框外、多点触控并发症、负尺寸。所有这些问题都可以以非常不同的方式处理,并且是使这样的东西从一个好主意变成一个漂亮的自定义界面的秘诀。我会把那部分留给你。 :)
关于ios - 带有圆形 handle 的 UIBezierPath 矩形,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14840276/
这里有一个很好的答案解释了如何在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返回它复制的字节数,但是当我还没有下
我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的
1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里
使用rspec-rails3.0+,测试设置分为spec_helper和rails_helper我注意到生成的spec_helper不需要'rspec/rails'。这会导致zeus崩溃:spec_helper.rb:5:in`':undefinedmethod`configure'forRSpec:Module(NoMethodError)对thisissue最常见的回应是需要'rspec/rails'。但这是否会破坏仅使用spec_helper拆分rails规范和PORO规范的全部目的?或者这无关紧要,因为Zeus无论如何都会预加载Rails?我应该在我的spec_helper中做
假设我有一个类A,里面有一些方法。假设stringmethodName是这些方法之一,我已经知道我想给它什么参数。它们在散列中{'param1'=>value1,'param2'=>value2}所以我有:params={'param1'=>value1,'param2'=>value2}a=A.new()a.send(methodName,value1,value2)#callmethodnamewithbothparams我希望能够通过传递我的哈希以某种方式调用该方法。这可能吗? 最佳答案 确保methodName是一个符号,而
当我进入Rails控制台时,我已将pry设置为加载代替irb。我找不到该页面或不记得如何将其恢复为默认行为,因为它似乎干扰了我的Rubymine调试器。有什么建议吗? 最佳答案 我刚发现问题,pry-railsgem。忘记了它的目的是让“railsconsole”打开pry。 关于ruby-on-rails-带有Pry的Rails控制台,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/question
print"Enteryourpassword:"pass=STDIN.noecho(&:gets)puts"Yourpasswordis#{pass}!"输出:Enteryourpassword:input.rb:2:in`':undefinedmethod`noecho'for#>(NoMethodError) 最佳答案 一开始require'io/console'后来的Ruby1.9.3 关于ruby-为什么不能使用类IO的实例方法noecho?,我们在StackOverflow上
我了解instance_eval和class_eval之间的基本区别。我在玩弄时发现的是一些涉及attr_accessor的奇怪东西。这是一个例子:A=Class.newA.class_eval{attr_accessor:x}a=A.newa.x="x"a.x=>"x"#...expectedA.instance_eval{attr_accessor:y}A.y="y"=>NoMethodError:undefinedmethod`y='forA:Classa.y="y"=>"y"#WHATTT?这是怎么回事:instance_eval没有访问我们的A类(对象)然后它实际上将它添加到
我在一个简单的RailsAPI中有以下Controller代码:classApi::V1::AccountsControllerehead:not_foundendendend问题在于,生成的json具有以下格式:{id:2,name:'Simpleaccount',cash_flows:[{id:1,amount:34.3,description:'simpledescription'},{id:2,amount:1.12,description:'otherdescription'}]}我需要我生成的json是camelCase('cashFlows'而不是'cash_flows'
在Ruby(或Rails)中,我们可以做到new_params=params.merge({:order=>'asc'})现在new_params是一个带有添加键:order的散列。但是是否有一行可以返回带有已删除key的散列?线路new_params=params.delete(:order)不会工作,因为delete方法返回值,仅此而已。我们必须分3步完成吗?tmp_params=paramstmp_params.delete(:order)returntmp_params有没有更好的方法?因为我想做一个new_params=(params[:order].blank?||para