- objective-c - iOS 5 : Can you override UIAppearance customisations in specific classes?
- iphone - 如何将 CGFontRef 转换为 UIFont?
- ios - 以编程方式关闭标记的信息窗口 google maps iOS
- ios - Xcode 5 - 尝试验证存档时出现 "No application records were found"
我有一个 UIScrollView。在这里我有一个 UIView,它有一个负原点的框架 - 我需要限制 ScrollView ,这样你就不能滚动整个 View ..
我已经在此 ScrollView 中实现了缩放。
缩放时, ScrollView 将根据比例调整可缩放 View 的大小。但它不会调整原点。
所以如果我有一个框架为 {0, -500}, {1000, 1000}
的 View我缩小到 0.5 的比例,这将给我一个新的框架 {0, -500}, {500, 500}
显然这样不好,整个view都被scrollview缩小了。我希望框架为 {0, -250}, {500, 500}
我可以通过正确调整原点来修复 scrollViewDidZoom 方法中的一些问题。这确实有效,但缩放不平滑。在这里更改原点会导致它跳跃。
我在 UIView 的文档中注意到它说(关于 frame 属性):
Warning: If the transform property is not the identity transform, the value of this property is undefined and therefore should be ignored.
不太清楚这是为什么。
我是不是处理这个问题有误?修复它的最佳方法是什么?
谢谢
下面是我正在使用的测试应用程序的一些源代码:
在 View Controller 中..
- (void)viewDidLoad
{
[super viewDidLoad];
self.bigView = [[BigView alloc] initWithFrame: CGRectMake(0, -400, 1000, 1000)];
[self.bigScroll addSubview: bigView];
self.bigScroll.delegate = self;
self.bigScroll.minimumZoomScale = 0.2;
self.bigScroll.maximumZoomScale = 5;
self.bigScroll.contentSize = bigView.bounds.size;
}
-(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return bigView;
}
- (void)scrollViewDidZoom:(UIScrollView *)scrollView {
// bigView.frame = CGRectMake(0, -400 * scrollView.zoomScale,
// bigView.frame.size.width, bigView.frame.size.height);
bigView.center = CGPointMake(500 * scrollView.zoomScale, 100 * scrollView.zoomScale);
}
然后在 View 中...
- (void)drawRect:(CGRect)rect
{
// Drawing code
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(ctx, [UIColor whiteColor].CGColor);
CGContextSetStrokeColorWithColor(ctx, [UIColor whiteColor].CGColor);
CGContextFillRect(ctx, CGRectMake(100, 500, 10, 10));
for (int i = 0; i < 1000; i += 100) {
CGContextStrokeRect(ctx, CGRectMake(0, i, 1000, 3));
}
}
请注意,这里的跳跃在较大的缩放比例下更为明显。在我的真实应用程序中,有更多的绘图和处理正在进行,跳跃在任何时候都更加明显。
最佳答案
您不必使用 frame 属性 - 鉴于 Apple 非常坚定的警告,您也不应该使用。在这种情况下,您通常可以使用 bounds
和 center
来实现您的结果。
在您的情况下,您可以忽略所有 subview 的属性。假设您的 subview 是 viewForZoomingInScrollView
,您可以使用 scrollView 的 contentOffset
和 zoomScale
属性
- (void) setMinOffsets:(UIScrollView*)scrollView
{
CGFloat minOffsetX = MIN_OFFSET_X*scrollView.zoomScale;
CGFloat minOffsetY = MIN_OFFSET_Y*scrollView.zoomScale;
if ( scrollView.contentOffset.x < minOffsetX
|| scrollView.contentOffset.y < minOffsetY ) {
CGFloat offsetX = (scrollView.contentOffset.x > minOffsetX)?
scrollView.contentOffset.x : minOffsetX;
CGFloat offsetY = (scrollView.contentOffset.y > minOffsetY)?
scrollView.contentOffset.y : minOffsetY;
scrollView.contentOffset = CGPointMake(offsetX, offsetY);
}
}
从您的 scrollView 委托(delegate)中的 scrollViewDidScroll
和 scrollViewDidZoom
调用它。这应该可以顺利进行,但如果您有疑问,您也可以通过子类化 scrollView 并使用 layoutSubviews
调用它来实现它。在他们的 PhotoScroller 示例中,Apple 通过覆盖 layoutSubviews
使 scrollView 的内容居中 - 尽管他们疯狂地忽略了自己的警告并调整 subview 的 frame 属性来实现这一点。
更新
上述方法消除了 ScrollView 达到其极限时的“弹跳”。如果您想保留反弹,您可以直接更改 View 的中心属性:
- (void) setViewCenter:(UIScrollView*)scrollView
{
UIView* view = [scrollView subviews][0];
CGFloat centerX = view.bounds.size.width/2-MIN_OFFSET_X;
CGFloat centerY = view.bounds.size.height/2-MIN_OFFSET_Y;
centerX *=scrollView.zoomScale;
centerY *=scrollView.zoomScale;
view.center = CGPointMake(centerX, centerY);
}
更新 2
从您更新的问题(带有代码)中,我可以看出这些解决方案都不能解决您的问题。似乎正在发生的事情是,您的偏移量越大,变焦运动变得越不稳定。偏移量为 100 点时, Action 仍然相当流畅,但偏移量为 500 点时,则粗糙得令人无法接受。这部分与您的 drawRect
例程有关,部分与 scrollView 中正在进行的(太多)重新计算有关以显示正确的内容。所以我有另一个解决方案......
在您的 viewController 中,将您的 customView 的边界/框架原点设置为正常 (0,0)。我们将使用图层来偏移内容。您需要将 QuartzCore 框架添加到您的项目中,并将其#import 到您的自定义 View 中。
在自定义 View 中初始化两个 CAShapeLayers - 一个用于框,另一个用于线。如果它们共享相同的填充和描边,你将只需要一个 CAShapeLayer(对于这个例子,我改变了你的填充和描边颜色)。每个 CAShapeLayer 都有它自己的 CGContext,你可以用颜色、线宽等每层初始化一次。然后要让 CAShapelayer 完成它的绘制,你所要做的就是用 CGPath 设置它的 path
属性。
#import "CustomView.h"
#import <QuartzCore/QuartzCore.h>
@interface CustomView()
@property (nonatomic, strong) CAShapeLayer* shapeLayer1;
@property (nonatomic, strong) CAShapeLayer* shapeLayer2;
@end
@implementation CustomView
#define MIN_OFFSET_X 100
#define MIN_OFFSET_Y 500
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self initialiseLayers];
}
return self;
}
- (void) initialiseLayers
{
CGRect layerBounds = CGRectMake( MIN_OFFSET_X,MIN_OFFSET_Y
, self.bounds.size.width + MIN_OFFSET_X
, self.bounds.size.height+ MIN_OFFSET_Y);
self.shapeLayer1 = [[CAShapeLayer alloc] init];
[self.shapeLayer1 setFillColor:[UIColor clearColor].CGColor];
[self.shapeLayer1 setStrokeColor:[UIColor yellowColor].CGColor];
[self.shapeLayer1 setLineWidth:1.0f];
[self.shapeLayer1 setOpacity:1.0f];
self.shapeLayer1.anchorPoint = CGPointMake(0, 0);
self.shapeLayer1.bounds = layerBounds;
[self.layer addSublayer:self.shapeLayer1];
设置界限是关键。与裁剪其 subview 的 View 不同,CALayers 将绘制超出其超层的边界。您将开始在 View 顶部上方绘制 MIN_OFFSET_Y
点,在左侧绘制 MIN_OFFSET_X
点。这允许您在 ScrollView 的内容 View 之外绘制内容,而无需 ScrollView 做任何额外的工作。
Unlike views, a superlayer does not automatically clip the contents of sublayers that lie outside its bounds rectangle. Instead, the superlayer allows its sublayers to be displayed in their entirety by default.
(Apple Docs, Building a Layer Hierarchy)
self.shapeLayer2 = [[CAShapeLayer alloc] init];
[self.shapeLayer2 setFillColor:[UIColor blueColor].CGColor];
[self.shapeLayer2 setStrokeColor:[UIColor clearColor].CGColor];
[self.shapeLayer2 setLineWidth:0.0f];
[self.shapeLayer2 setOpacity:1.0f];
self.shapeLayer2.anchorPoint = CGPointMake(0, 0);
self.shapeLayer2.bounds = layerBounds;
[self.layer addSublayer:self.shapeLayer2];
[self drawIntoLayer1];
[self drawIntoLayer2];
}
为每个形状层设置一条贝塞尔曲线路径,然后传入:
- (void) drawIntoLayer1 {
UIBezierPath* path = [[UIBezierPath alloc] init];
[path moveToPoint:CGPointMake(0,0)];
for (int i = 0; i < self.bounds.size.height+MIN_OFFSET_Y; i += 100) {
[path moveToPoint:
CGPointMake(0,i)];
[path addLineToPoint:
CGPointMake(self.bounds.size.width+MIN_OFFSET_X, i)];
[path addLineToPoint:
CGPointMake(self.bounds.size.width+MIN_OFFSET_X, i+3)];
[path addLineToPoint:
CGPointMake(0, i+3)];
[path closePath];
}
[self.shapeLayer1 setPath:path.CGPath];
}
- (void) drawIntoLayer2 {
UIBezierPath* path = [UIBezierPath bezierPathWithRect:
CGRectMake(100+MIN_OFFSET_X, MIN_OFFSET_Y, 10, 10)];
[self.shapeLayer2 setPath:path.CGPath];
}
这避免了对 drawRect
的需要 - 如果您更改路径属性,您只需要重新绘制图层。即使您确实像调用 drawRect 一样频繁地更改路径属性,绘图现在也应该明显更有效。由于 path
是一个动画属性,如果需要,您还可以免费获得动画。
在你的情况下,我们只需要设置一次路径,所以所有的工作都在初始化时完成一次。
现在您可以从 scrollView 委托(delegate)方法中删除任何居中代码,不再需要它了。
关于ios - UIScrollView 缩小具有 -ve 原点的 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16361810/
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,
我正在尝试创建一个可以像在 Excel 中一样放大和缩小的 QTableView。 此处提出了类似的问题:Zooming function on a QWidget 但是,我在 PyQt 而不是 C
如图所示。 我在 QScrollArea 中有 QWidget。QWidget 充当细胞图像和一些基于矢量的轮廓数据的渲染小部件。用户可以执行放大/缩小操作,简单地发生的是,它改变了 QPaint
双击 MKMapView 时:放大。 但是如何缩小呢? 最佳答案 总是使用两根手指来放大和缩小。在模拟器上,您需要按住选项键才能在模拟屏幕上显示“两根手指”(我认为这是 Alt 键,但我在 Mac 上
我有一些 javascript for {} 循环,我在整个项目中重复使用它们,它们都类似于: for (var i = 0; i < things.length; i++) { consol
我知道我可以使用C-x C- +进行放大/缩小,但这仅适用于当前文件。一旦我打开另一个文本,文本将恢复为默认值,一遍又一遍地做起来真的很累。如何保持当前emacs session 的全局缩放级别? 如
我对使用编译器工具自动化/简化 Angular 项目感兴趣,这可能适用于其他所有事情,但 Angular 注入(inject)和命名空间很尴尬,足以逃避编译器知识。执行此操作的最佳/专业方法是什么?
有没有办法在emacs上放大和缩小(动态改变字体大小,相当流畅)? 最佳答案 尝试 C-x C-+ 和 C-x C--;即 Control-x Control-减号/Control-再加上。 在一个组
我有一个Windows表单对象,其中包含3个对象,树 View ,richtextbox和tabcontrol。它们没有停靠在Windows窗体中,而是被 anchor 定(顶部+左侧)。 我已经编写
我想向 javascript-mode 添加功能,以便每当我在当前缓冲区上保存 Javascript 文件时,它都会在使用相对路径定义的目录中创建该文件的缩小文件,例如 ../foo 具有相同的文件名
这里有一些关于缩小.war文件的教程,甚至一些帖子。但是,最常见的技术(在Config.groovy中包含grails.war.resources = {})似乎对我不起作用。无论如何,grails会
如何使用 ScaleTransition缩小图像?我现在有这个,它只能放大。如果我误解了该方法,我不会,但我将其从 1 缩放到 0.8。由于某种原因,这种情况仍在扩大。 ScaleTransition
基本上,我想问ReplicaSets是否与CronJobs的suspend: "true"选项类似,但我愿意接受其他建议。 最佳答案 From the official Kubernetes doc
我想使用 boost::polygon 扩展/收缩带孔的多边形。所以澄清一点,我有一个单一的数据结构 boost::polygon::polygon_with_holes_data inPoly 其中
我有一个 map 列表: [%{~D[2019-02-11] => 7}, %{~D[2019-02-12] => 1}, %{~D[2019-02-15] => 1}] 我正在尝试将其变成一张大
我正在制作一个横幅,您可以使用jquery幻灯片功能缩放图像并且可以拖动图像。 除了一件事之外,它工作完美。当您使用图像下方的幻灯片放大图像时,效果非常好。您可以将图像拖动到您想要的位置。但当你想用幻
我们有一个 extjs 应用程序,其中我们布置的结构与 Sencha 推荐的结构不完全匹配。在我们的结构中,我们没有 app.js,但我们有一个 js,其中我们提到了自动加载和启动功能,示例如下以及文
我想在 Chrome/Firefox 中运行的应用程序是: 用 typescript 写 使用 React 使用 es 下一个功能(模块、导入等)编写 有一些导入是纯 js 文件 网页包 3 我可以在
我正在尝试像此处一样应用 Google map 的放大/缩小 - https://www.google.com/maps/@36.241201,-98.1261798,5.13z?hl=en我无法让它
我正在使用 Protractor ,需要缩小到 50%,我尝试了 StackOverflow 上发布的其他几个问题的解决方案,但没有任何效果。其中一些包括: browser.actions().key
我是一名优秀的程序员,十分优秀!