gpt4 book ai didi

objective-c - iPad 自定义/动态布局

转载 作者:塔克拉玛干 更新时间:2023-11-02 10:13:26 25 4
gpt4 key购买 nike

我是 iOS 开发的新手。我已经完成了几个教程并了解了基础知识,但目前我仍然不知道如何进一步进行。我打算为基本的家庭自动化创建一个应用程序(即开关灯、测量温度等)。后端都设置好了,所以这只是关于前端的。这是我打算做的:

  • 应用的主视图应显示平面图或房屋布局
  • 在此平面图上,您应该可以添加灯/传感器/等。 - 让对象保持通用
  • 这些对象应该是可拖动的,以便您可以根据它们的实际位置(物理上)在平面图上排列它们 - 理想情况下,这种拖动模式是可切换的,类似于在主屏幕上重新排列图标
  • 每个对象都应该有一个弹出 View (即设置调光器强度、开关灯等)

我知道有很多工作要做,但我真的不知道如何设置。当前备选方案:

  1. 创建一个包含所有逻辑的自定义 UIView 子类,并使用自定义代码进行绘图,即拖动、弹出窗口定位等 - 但我觉得我不会真正利用 iOS 框架功能<
  2. 将平面图显示为 UIImageView 和每个对象的一个​​ UIButton。这样做的好处是我可以使用 StoryBoard 进行布局和布线(即为弹出窗口等创建 segues)——但我根本不知道如何使用可变数量的按钮来做到这一点(因为我不知道提前将有多少个按钮)。有什么方法可以在代码中创建这些按钮吗?
  3. 使用自定义 UITableView。我见过几个例子,即使布局与表格无关(就像我的例子一样),他们似乎也使用表格 View ,但我还没有找到任何教程来更详细地解释这个概念

还是我完全走错了路?感谢任何输入。

谢谢D.

更新:在对此进行更多研究和思考之后,我认为使用 iOS 6 的方法是使用具有自定义布局的 UICollectionView。一旦我想出了一个完整的解决方案,我会把它贴在这里。对于较旧的 iOS 版本,我认为使用 Option Nr 是有希望的。 2 - 即在代码中创建每个 UIButton(用于自动化对象,例如灯光)并使用自定义 UIView 子类来对这些按钮进行布局。

最佳答案

好吧,我认为 UICollectionView 是这种使用场景的理想选择,我很幸运能够在 iOS 编程被引入框架时开始使用它。以下示例是一个 UICollectionView,它根据元素的固有坐标显示其元素。此示例还可以应用于在 map 上定位对象。我在其他地方找不到任何示例,所以我将在此处发布主要步骤(因为我是初学者,请纠正任何错误)。

首先,我在 XCode 中创建了一个包含一个 View 和 Storyboard的简单项目。我删除了标准 View 并插入了一个 Collection View Controller ,并将我的 UICollectionViewController 子类配置为应该使用的类(在 Storyboard的 Controller 属性中)。

对于本示例,只需将默认 UICollectionViewCell 的背景设置为一种颜色并将标识符设置为“AutomationCell”(如果您更改它,请务必调整下面的代码)。

首先,我创建了一个简单的对象,它具有一些属性,代表一个应该显示在平面图上的对象:

@interface AULYAutomationObject : NSObject

@property NSString *title;
@property CGPoint position;

@end

然后我需要我自己的委托(delegate)作为标准 UICollectionViewDelegate 的子类,因为我的自定义 UICollectionViewLayout 将无法直接访问数据源对象。因此,我提供了一种方法来确定对象的位置:

@protocol AULYAutomationObjectLayoutDelegate <UICollectionViewDelegate>

- (CGPoint)getPositionForItemAtIndexPath:(NSIndexPath *)indexPath;

@end

确保在你的 Controller 中像这样实现这个协议(protocol):

@interface AULYViewController : UICollectionViewController <AULYAutomationObjectLayoutDelegate>

然后我在 View Controller 子类中实现了标准数据源和委托(delegate)方法以及我的自定义方法:

@interface AULYViewController ()

@property NSArray *objects;
@property (strong, nonatomic) IBOutlet UICollectionView *collectionView;

@end

@implementation AULYViewController

- (void)viewDidLoad
{
[super viewDidLoad];

// Set up the data source
NSMutableArray *automationObjects = [[NSMutableArray alloc] initWithCapacity:10];

// add some objects here...

self.objects = [automationObjects copy];

UILongPressGestureRecognizer *longPressRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];
[self.collectionView addGestureRecognizer:longPressRecognizer];
}

#pragma mark - UICollectionViewController
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return self.objects.count;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
AULYAutomationObjectViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"AutomationCell" forIndexPath:indexPath];
// If you have a custom UICollectionViewCell with a label as outlet
// you could for example then do this:
// AULYAutomationObject *automationObject = self.objects[indexPath.row];
// cell.label.text = automationObject.title;
return cell;
}

#pragma mark - AULYAutomationObjectLayoutDelegate

- (CGPoint)getPositionForItemAtIndexPath:(NSIndexPath *)indexPath
{
AULYAutomationObject *automationObject = self.objects[indexPath.item];
return automationObject.position;
}

在实际项目中,您可能会进行一些从对象模型位置到屏幕上位置的转换(例如,GPS 数据到像素),但为了简单起见,这里省略了这一点。

完成之后,我们还需要设置我们的布局。这具有以下属性:

@interface AULYAutomationObjectLayout : UICollectionViewLayout

@property (nonatomic, strong) NSIndexPath *draggedObject;
@property (nonatomic) CGPoint dragPosition;

@end

以及以下实现:

@implementation AULYAutomationObjectLayout

- (void)setDraggedObject:(NSIndexPath *)draggedObject
{
_draggedObject = draggedObject;
[self invalidateLayout];
}

- (void)setDragPosition:(CGPoint)dragPosition
{
_dragPosition = dragPosition;
[self invalidateLayout];
}

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewLayoutAttributes *layoutAttributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
id viewDelegate = self.collectionView.delegate;
if ([viewDelegate respondsToSelector:@selector(getPositionForItemAtIndexPath:)])
{
CGPoint itemPosition = [viewDelegate getPositionForItemAtIndexPath:indexPath];
layoutAttributes.center = itemPosition;
layoutAttributes.size = CGSizeMake(ITEM_SIZE, ITEM_SIZE);
}

if ([self.draggedObject isEqual:indexPath])
{
layoutAttributes.center = self.dragPosition;
layoutAttributes.transform3D = CATransform3DMakeScale(1.5, 1.5, 1.0);
layoutAttributes.zIndex = 1;
}

return layoutAttributes;
}

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
NSMutableArray *allAttributes = [[NSMutableArray alloc] initWithCapacity:4];
for (NSInteger i = 0; i < [self.collectionView numberOfItemsInSection:0]; i++)
{
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
UICollectionViewLayoutAttributes *layoutAttributes = [self layoutAttributesForItemAtIndexPath:indexPath];
[allAttributes addObject:layoutAttributes];
}
return allAttributes;
}

- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
{
return YES;
}

- (CGSize)collectionViewContentSize
{
return [self.collectionView frame].size;
}

@end

要在 Storyboard中设置自定义布局,只需转到 Controller View 的属性并选择自定义作为布局类型 - 然后选择您的自定义类。

现在要启用长按手势的拖放支持,只需将以下内容添加到您的 Controller :

- (void)handleTapGesture:(UITapGestureRecognizer *)sender
{
AULYAutomationObjectLayout *automationLayout = (AULYAutomationObjectLayout *)self.collectionView.collectionViewLayout;
if (sender.state == UIGestureRecognizerStateBegan)
{
CGPoint initialPinchPoint = [sender locationInView:self.collectionView];
NSIndexPath* tappedCellPath = [self.collectionView indexPathForItemAtPoint:initialPinchPoint];
[self.collectionView performBatchUpdates:^{
automationLayout.draggedObject = tappedCellPath;
automationLayout.dragPosition = initialPinchPoint;
} completion:nil];
}
else if (sender.state == UIGestureRecognizerStateChanged)
{
automationLayout.dragPosition = [sender locationInView:self.collectionView];
}
else if (sender.state == UIGestureRecognizerStateEnded)
{
AULYAutomationObject *automationObject = self.objects[automationLayout.draggedObject.item];
automationObject.position = [sender locationInView:self.collectionView];
[self.collectionView performBatchUpdates:^{
automationLayout.draggedObject = nil;
automationLayout.dragPosition = CGPointMake(0.0, 0.0);
} completion:nil];
}
}

一个重要提示:(这至少花费了我一个小时):使用 transform3D 时,您应该确保将 QuartzCore 导入到您的链接框架中(在方向设置下方的项目属性中)。否则,您将收到 Mach-O 链接器错误,指出无法找到 _CATransform3DMakeScale。

关于objective-c - iPad 自定义/动态布局,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12728342/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com