如何跨视图层次定位布局?
How to locate the layout across view hierarchy?
我在列表视图控制器中有一个 menuView。当单元格中的更多按钮被录音时,menuView 添加到 UITableViewCell 上。
我用单例实现了效果
@implementation ProductsOperationMenu
static ProductsOperationMenu *_instance;
+ (instancetype)sharedInstance{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [[self alloc] initWithFrame:CGRectZero];
});
return _instance;
}
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
[self setup];
}
return self;
}
ZBMyProductsCell.m
@implementation ZBMyProductsCell
- (void)awakeFromNib
{
[super awakeFromNib];
_operationMenu = [[ProductsOperationMenu alloc] initWithFrame: CGRectZero];
}
- (IBAction)operationButtonClick:(UIButton *)sender {
if ([self.contentView.subviews containsObject:_operationMenu]) {
_operationMenu.hidden = ![_operationMenu isHidden];
} else{
[self.contentView addSubview:_operationMenu];
_operationMenu.hidden = NO;
}
[_operationMenu mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.mas_equalTo(205);
make.height.mas_equalTo(60);
make.bottom.mas_equalTo(self.operationButton).offset(0);
make.right.mas_equalTo(self.operationButton.mas_left).offset(-10);
}];
}
没有单例,就变成了这样:
那么问题来了
我想把menuView放到controller的view上,因为它是unique或者hidden,以前属于cell。
如何将选中的更多按钮的布局转换为控制器的视图?
如何使用计算方法?
- convertPoint:toView:
- convertPoint:fromView:
......
我用简单的方法做到了。这是代码:
- (void)clickOperationButtonOfProductsCell:(ZBMyProductsCell *)myProductsCell{
NSUInteger * operationIndex = [self.myProductsTableView.visibleCells indexOfObject:myProductsCell];
CGFloat originY = operationIndex.row * 110 + 50 + 40;
CGRect originFrame = CGRectMake(KScreenWidth - 55, originY, 0, 60);
CGRect finalFrame = CGRectMake(KScreenWidth - 260, originY, 205, 60);
self.operationMenuView.frame = originFrame;
[UIView animateWithDuration: 0.5 delay: 0 options: UIViewAnimationOptionCurveEaseIn animations:^{
self.operationMenuView.frame = finalFrame;
} completion:^(BOOL finished) { }];
}
如何更自适应地实现?
在每个单元格模型中创建一个名为 cellIndexpath 的变量,并在 cellForRow 中初始化它
cell.cellIndexpath = indexpath
也许你可以这样试试:
// here is your cell where the more button belongs to
@interface ZBMyProductsCell: UITableViewCell
@property (nonatomic, copy) void(^moreAction)(ZBMyProductsCell *cell);
@end
@implementation ZBMyProductsCell
- (void)_moreButtonClicked:(UIButton *)sender {
!self.moreAction ?: self.moreAction(self);
}
@end
// here is your view controller where your table view belongs to
// this is a `UITableViewDataSource` delegate method
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
ZBMyProductsCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ZBMyProductsCell" forIndexPath:indexPath];
// Configure the cell...
cell.moreAction = ^(ZBMyProductsCell *cell) {
CGRect rect = [tableView rectForRowAtIndexPath:indexPath];
// write your own code to show/hide the menu
};
return cell;
}
看看 UIPopoverPresnetationController
看看它是否能胜任这项工作。它应该在 iPhone 上可用。将 menu view
放在 controller’view
上会在您滚动 table 视图时导致问题 。
使用
UIMenuController *menu = [UIMenuController sharedMenuController];
[menu setTargetRect:self.detaiLabel.frame inView:self];
我在列表视图控制器中有一个 menuView。当单元格中的更多按钮被录音时,menuView 添加到 UITableViewCell 上。
@implementation ProductsOperationMenu
static ProductsOperationMenu *_instance;
+ (instancetype)sharedInstance{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [[self alloc] initWithFrame:CGRectZero];
});
return _instance;
}
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
[self setup];
}
return self;
}
ZBMyProductsCell.m
@implementation ZBMyProductsCell
- (void)awakeFromNib
{
[super awakeFromNib];
_operationMenu = [[ProductsOperationMenu alloc] initWithFrame: CGRectZero];
}
- (IBAction)operationButtonClick:(UIButton *)sender {
if ([self.contentView.subviews containsObject:_operationMenu]) {
_operationMenu.hidden = ![_operationMenu isHidden];
} else{
[self.contentView addSubview:_operationMenu];
_operationMenu.hidden = NO;
}
[_operationMenu mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.mas_equalTo(205);
make.height.mas_equalTo(60);
make.bottom.mas_equalTo(self.operationButton).offset(0);
make.right.mas_equalTo(self.operationButton.mas_left).offset(-10);
}];
}
没有单例,就变成了这样:
那么问题来了
我想把menuView放到controller的view上,因为它是unique或者hidden,以前属于cell。
如何将选中的更多按钮的布局转换为控制器的视图? 如何使用计算方法?
- convertPoint:toView:
- convertPoint:fromView:
......
我用简单的方法做到了。这是代码:
- (void)clickOperationButtonOfProductsCell:(ZBMyProductsCell *)myProductsCell{
NSUInteger * operationIndex = [self.myProductsTableView.visibleCells indexOfObject:myProductsCell];
CGFloat originY = operationIndex.row * 110 + 50 + 40;
CGRect originFrame = CGRectMake(KScreenWidth - 55, originY, 0, 60);
CGRect finalFrame = CGRectMake(KScreenWidth - 260, originY, 205, 60);
self.operationMenuView.frame = originFrame;
[UIView animateWithDuration: 0.5 delay: 0 options: UIViewAnimationOptionCurveEaseIn animations:^{
self.operationMenuView.frame = finalFrame;
} completion:^(BOOL finished) { }];
}
如何更自适应地实现?
在每个单元格模型中创建一个名为 cellIndexpath 的变量,并在 cellForRow 中初始化它
cell.cellIndexpath = indexpath
也许你可以这样试试:
// here is your cell where the more button belongs to
@interface ZBMyProductsCell: UITableViewCell
@property (nonatomic, copy) void(^moreAction)(ZBMyProductsCell *cell);
@end
@implementation ZBMyProductsCell
- (void)_moreButtonClicked:(UIButton *)sender {
!self.moreAction ?: self.moreAction(self);
}
@end
// here is your view controller where your table view belongs to
// this is a `UITableViewDataSource` delegate method
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
ZBMyProductsCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ZBMyProductsCell" forIndexPath:indexPath];
// Configure the cell...
cell.moreAction = ^(ZBMyProductsCell *cell) {
CGRect rect = [tableView rectForRowAtIndexPath:indexPath];
// write your own code to show/hide the menu
};
return cell;
}
看看 UIPopoverPresnetationController
看看它是否能胜任这项工作。它应该在 iPhone 上可用。将 menu view
放在 controller’view
上会在您滚动 table 视图时导致问题 。
使用
UIMenuController *menu = [UIMenuController sharedMenuController];
[menu setTargetRect:self.detaiLabel.frame inView:self];