iOS 框架更改一项属性(例如宽度)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9537573/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
iOS frame change one property (eg width)
提问by Hymansonkr
This question was originally asked for the objective-c programming language. At the time of writing, swift didn't even exist yet.
这个问题最初是针对 Objective-c 编程语言提出的。在撰写本文时,swift 甚至还不存在。
Question
题
Is it possible to change only oneproperty of a CGRect
?
是否可以只更改a 的一个属性CGRect
?
For example:
例如:
self.frame.size.width = 50;
instead of
代替
self.frame = CGRectMake(self.frame.origin.x,
self.frame.origin.y,
self.frame.size.width,
50);
of course I understand that self.frame.size.width
is read onlyso I'm wondering how to do this?
当然,我知道这self.frame.size.width
是只读的,所以我想知道如何做到这一点?
CSS ANALOGYproceed at your own risk
CSS ANALOGY自行承担风险
for those of you who are familiar with CSS
, the idea is very similar to using:
对于那些熟悉 的人来说CSS
,这个想法非常类似于使用:
margin-left: 2px;
instead of having to change the whole value:
而不必更改整个值:
margin: 5px 5px 5px 2px;
回答by Ole Begemann
To answer your original question: yes, it's possible to change just one member of a CGRect
structure. This code throws no errors:
回答您最初的问题:是的,可以仅更改CGRect
结构的一个成员。此代码不会引发任何错误:
myRect.size.width = 50;
What is notpossible, however, is to change a single member of a CGRect
that is itself a property of another object. In that very common case, you would have to use a temporary local variable:
什么是没有可能的,但是,是改变的一个成员CGRect
,其本身的另一个对象的属性。在这种非常常见的情况下,您必须使用临时局部变量:
CGRect frameRect = self.frame;
frameRect.size.width = 50;
self.frame = frameRect;
The reason for this is that using the property accessor self.frame = ...
is equivalent to [self setFrame:...]
and this accessor always expects an entire CGRect
. Mixing C-style struct
access with Objective-C property dot notation does not work well in this case.
这样做的原因是使用属性访问self.frame = ...
器等效于[self setFrame:...]
并且此访问器始终需要一个完整的CGRect
. struct
在这种情况下,将 C 样式访问与 Objective-C 属性点符号混合使用效果不佳。
回答by ArtOfWarfare
I liked Ahmed Khalaf's answer, but it occurred to me that you may as well just write out a few C functions... the key advantage being that it'll be easier to track down errors in the event that you're using the wrong type.
我喜欢Ahmed Khalaf 的回答,但我突然想到,您不妨只写出一些 C 函数……主要优点是,如果您使用错误,则更容易追踪错误类型。
Having said that, I wrote a .h file with these function declarations:
话虽如此,我写了一个带有这些函数声明的 .h 文件:
CGRect CGRectSetWidth(CGRect rect, CGFloat width);
CGRect CGRectSetHeight(CGRect rect, CGFloat height);
CGRect CGRectSetSize(CGRect rect, CGSize size);
CGRect CGRectSetX(CGRect rect, CGFloat x);
CGRect CGRectSetY(CGRect rect, CGFloat y);
CGRect CGRectSetOrigin(CGRect rect, CGPoint origin);
And a corresponding .m file with these function implementations:
以及具有这些函数实现的相应 .m 文件:
CGRect CGRectSetWidth(CGRect rect, CGFloat width) {
return CGRectMake(rect.origin.x, rect.origin.y, width, rect.size.height);
}
CGRect CGRectSetHeight(CGRect rect, CGFloat height) {
return CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, height);
}
CGRect CGRectSetSize(CGRect rect, CGSize size) {
return CGRectMake(rect.origin.x, rect.origin.y, size.width, size.height);
}
CGRect CGRectSetX(CGRect rect, CGFloat x) {
return CGRectMake(x, rect.origin.y, rect.size.width, rect.size.height);
}
CGRect CGRectSetY(CGRect rect, CGFloat y) {
return CGRectMake(rect.origin.x, y, rect.size.width, rect.size.height);
}
CGRect CGRectSetOrigin(CGRect rect, CGPoint origin) {
return CGRectMake(origin.x, origin.y, rect.size.width, rect.size.height);
}
So, now, to do what you want, you can just do:
所以,现在,要做你想做的,你可以这样做:
self.frame = CGRectSetWidth(self.frame, 50);
Get even Fancier(update I made a year later)
变得更狂热(我一年后更新)
This has a redundant self.frame
in it, though. To fix that, you could add a category
on UIView
with methods that look like this:
不过,这其中有一个多余self.frame
的内容。为了解决这个问题,你可以添加一个category
上UIView
有方法是这个样子的:
- (void) setFrameWidth:(CGFloat)width {
self.frame = CGRectSetWidth(self.frame, width); // You could also use a full CGRectMake() function here, if you'd rather.
}
And now you can just type in:
现在你可以输入:
[self setFrameWidth:50];
Or, even better:
或者,甚至更好:
self.frameWidth = 50;
And just so you can do something like this:
这样你就可以做这样的事情:
self.frameWidth = otherView.frameWidth; // as opposed to self.frameWidth = otherView.frame.size.width;
You'll need to also have this in your category:
你还需要在你的类别中有这个:
- (CGFloat) frameWidth {
return self.frame.size.width;
}
Enjoy.
享受。
回答by n0_quarter
Based on ArtOfWarfare's solution(which is really awesome) I've build the UIView
category without C-functions.
基于ArtOfWarfare 的解决方案(这真的很棒),我构建了UIView
没有 C 函数的类别。
Usage examples:
用法示例:
[self setFrameWidth:50];
self.frameWidth = 50;
self.frameWidth += 50;
self.frameWidth = otherView.frameWidth; // as opposed to self.frameWidth = otherView.frame.size.width;
Header file UIView+easy_frame.h
:
头文件UIView+easy_frame.h
:
@interface UIView (easy_frame)
- (void) setFrameWidth:(CGFloat)width;
- (void) setFrameHeight:(CGFloat)height;
- (void) setFrameX:(CGFloat)x;
- (void) setFrameY:(CGFloat)y;
- (CGFloat) frameWidth;
- (CGFloat) frameHeight;
- (CGFloat) frameX;
- (CGFloat) frameY;
Implementation file UIView+easy_frame.m
:
实施文件UIView+easy_frame.m
:
#import "UIView+easy_frame.h"
@implementation UIView (easy_frame)
# pragma mark - Setters
- (void) setFrameWidth:(CGFloat)width
{
self.frame = CGRectMake(self.frame.origin.x,
self.frame.origin.y,
width,
self.frame.size.height);
}
- (void) setFrameHeight:(CGFloat)height
{
self.frame = CGRectMake(self.frame.origin.x,
self.frame.origin.y,
self.frame.size.width,
height);
}
- (void) setFrameX:(CGFloat)x
{
self.frame = CGRectMake(x,
self.frame.origin.y,
self.frame.size.width,
self.frame.size.height);
}
- (void) setFrameY:(CGFloat)y
{
self.frame = CGRectMake(self.frame.origin.x,
y,
self.frame.size.width,
self.frame.size.height);
}
# pragma mark - Getters
- (CGFloat) frameWidth
{
return self.frame.size.width;
}
- (CGFloat) frameHeight
{
return self.frame.size.height;
}
- (CGFloat) frameX
{
return self.frame.origin.x;
}
- (CGFloat) frameY
{
return self.frame.origin.y;
}
回答by pxlshpr
If you find yourself needing to do this sort of individual component modification, it may be worthwhile having macros like these somewhere accessible by all of your code:
如果您发现自己需要进行这种单独的组件修改,那么在所有代码都可以访问的地方使用这样的宏可能是值得的:
#define CGRectSetWidth(rect, w) CGRectMake(rect.origin.x, rect.origin.y, w, rect.size.height)
#define ViewSetWidth(view, w) view.frame = CGRectSetWidth(view.frame, w)
This way, whenever you need to change the width alone - you would simply write
这样,每当您需要单独更改宽度时 - 您只需编写
ViewSetWidth(self, 50);
instead of
代替
self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, 50);
回答by Robert Wagstaff
Based on n0_quarter answer, here's a UIView Extension written in Swift:
根据 n0_quarter 的答案,这是一个用 Swift 编写的 UIView 扩展:
/**
* Convenience category for manipulating UIView frames
*/
extension UIView {
//MARK: - Getters
func frameX() -> CGFloat {
return frame.origin.x
}
func frameY() -> CGFloat {
return frame.origin.y
}
func frameWidth() -> CGFloat {
return frame.size.width
}
func frameHeight() -> CGFloat {
return frame.size.height
}
//MARK: - Setters
func setFrameX(x: CGFloat) {
frame = CGRect(x: x, y: frame.origin.y, width: frame.size.width, height: frame.size.height)
}
func setFrameY(y: CGFloat) {
frame = CGRect(x: frame.origin.x, y: y, width: frame.size.width, height: frame.size.height)
}
func setFrameWidth(width: CGFloat) {
frame = CGRect(x: frame.origin.x, y: frame.origin.y, width: width, height: frame.size.height)
}
func setFrameHeight(height: CGFloat) {
frame = CGRect(x: frame.origin.x, y: frame.origin.y, width: frame.size.width, height: height)
}
}
回答by clearlight
In Swift you could extend the UIView class for the app, such that you could, for example, move the table header view up by 10 points like this:
在 Swift 中,您可以为应用程序扩展 UIView 类,例如,您可以像这样将表头视图向上移动 10 个点:
tableView.tableHeaderView!.frameAdj(0, -20, 0, 0)
(of course if you're using AutoLayout, that might not actually do anything... :) )
(当然,如果您使用的是 AutoLayout,那实际上可能不会做任何事情... :) )
By extending UIView (affecting every UIView and subclass of it in your app)
通过扩展 UIView(影响应用程序中的每个 UIView 及其子类)
extension UIView {
func frameAdj(x: CGFloat, _ y: CGFloat, _ width: CGFloat, _ height: CGFloat) {
self.frame = CGRectMake(
self.frame.origin.x + x,
self.frame.origin.y + y,
self.frame.size.width + width,
self.frame.size.height + height)
}
}
回答by wahkiz
Hope I am not too late to the party, here's my solution in ObjC.
希望我参加聚会还不算太晚,这是我在 ObjC 中的解决方案。
For me I prefer to stick to a single function instead of several functions, and I like the CSS approach shown by the poster. Below is the function I add to my UIView Category.
对我来说,我更喜欢坚持使用单个函数而不是多个函数,而且我喜欢海报所示的 CSS 方法。下面是我添加到 UIView 类别的函数。
- (void)resetFrame:(CGRect)frame {
CGRect selfFrame = self.frame;
selfFrame.origin = CGPointMake(frame.origin.x>0 ? frame.origin.x : selfFrame.origin.x, frame.origin.y>0 ? frame.origin.y : selfFrame.origin.y);
selfFrame.size = CGSizeMake(frame.size.width>0 ? frame.size.width : selfFrame.size.width, frame.size.height>0 ? frame.size.height : selfFrame.size.height);
[self setFrame:selfFrame]; }
Shown in the example, it looks at each values in the provided CGRect, and if the value is more than 0, it means we want to replace that value. And therefore, you can do CGRect(0,0,100,0) and it will assume we want to replace the width only.
如示例所示,它查看提供的 CGRect 中的每个值,如果该值大于 0,则表示我们要替换该值。因此,您可以执行 CGRect(0,0,100,0) 并且它会假设我们只想替换宽度。
回答by Bigyelow
frequently call setFrame method is not so good, like:
setFrameX(x)
setFrameY(y)
setFrameWidth(width)
...
频繁调用 setFrame 方法不太好,比如:
setFrameX(x)
setFrameY(y)
setFrameWidth(width)
...
instead, in swift we can make use of default parameters to set multiple parameters only in one call:
相反,在 swift 中,我们可以使用默认参数仅在一次调用中设置多个参数:
func setFrame(x x: CGFloat = CGFloat.NaN, y: CGFloat = CGFloat.NaN, width: CGFloat = CGFloat.NaN, height: CGFloat = CGFloat.NaN) {
let newX = x.isNaN ? self.frame.origin.x : x
let newY = y.isNaN ? self.frame.origin.y : y
let newWidth = width.isNaN ? self.bounds.size.width : width
let newHeight = height.isNaN ? self.bounds.size.height : height
self.frame = CGRect(x: newX, y: newY, width: newWidth, height: newHeight)
}
then update parameters of frame only need:
然后更新帧的参数只需要:
setFrame(x: x, width: min(maxX - x, titleLabel.bounds.size.width))
setFrame(width: titleDescriptionLabel.bounds.size.width + 5, height: titleDescriptionLabel.bounds.size.height + 6)
回答by DavidoM
-(void) sizeScreen : (UIView *) size : (double) width : (double) height : (double) x : (double) y {
CGRect frameRect = size.frame;
frameRect.size.width = width;
frameRect.size.height = height;
frameRect.origin.x = x;
frameRect.origin.y = y;
self.view.frame = frameRect;
}
}
its work great for me :)
它的工作对我来说很棒:)