在常规UITableView
编辑模式下,将单元格拖动到您希望单元格所在的位置,其他单元格可以弹出到位。我想创建一个UITableView
编辑模式,您可以在其中选择一个单元格,当您滚动桌面视图以移动所选项目时,它将保持在中心,将所选项目保持在中心,表格单元格围绕中心移动选定的细胞。
有效的'赏金值'答案将需要一个最低限度的工作示例,将选定的单元格保存在表格的中心,并可以通过向上和向下滑动表格来移动。包括表中第一个和最后一个位置的边缘情况。或者,您可以概述您认为可行的关键点,如果它们引导我朝着正确的方向发展,那么您将获得赏金。
我在GitHub上建立了一个名为PickerTableView的项目。在开发分支上工作。选择正在进行,我正在研究子类化TableView来处理滚动单元格的移动。在我之前找到一个有效的解决方案仍然可以获得赏金。
根据评论,我将提供一些ASCII艺术。
|==========|
| Next|
|==========|
| |
|----------|
| |
|----------|
| |
|----------|
| |
|----------|
| |
|==========|
|==========|
| Next|
|==========|
| |
|----------|
| |
|----------|
| X|
|----------|
| |
|----------|
| |
|==========|
|=============|
| Done|
|=============|
| |
|-------------|
| |
|-------------|
| This cell is|
| Highlighted |
| and locked |
| in place |
|-------------|
| |
|-------------|
| |
|=============|
滚动tableview时,未选中的单元格会在所选单元格周围流动,而所选单元格位于中间位置。
答案 0 :(得分:2)
如果选定的单元格不是真正的单元格而是单独的UIView
(可以看起来像单元格),是否可以接受?如果是这样,你可以这样做:
UIView
。-scrollViewDidScroll:
来重新定位单元格。UIView
为了看到它的实际效果,我已经创建了一个UIViewController子类供您测试:
PickerTableViewController.h
#import <UIKit/UIKit.h>
@interface PickerTableViewController : UIViewController
@end
@interface SelectedItemView : UIView
@property (nonatomic, readonly) UILabel *label;
@end
PickerTableViewController.m
#import "PickerTableViewController.h"
@interface PickerTableViewController () <UITableViewDataSource, UITableViewDelegate>
@property (strong, nonatomic) UIButton *button;
@property (strong, nonatomic) UITableView *tableView;
@property (strong, nonatomic) UIView *tableViewContainer;
@property (strong, nonatomic) SelectedItemView *selectedItemView;
@property (strong, nonatomic) NSMutableArray *items;
@property (nonatomic, getter = isPicking) BOOL picking;
@property (strong, nonatomic) NSNumber *selectedItem;
@end
@implementation PickerTableViewController
- (id)init
{
self = [super init];
if (self) {
// generate random cell contents
NSInteger countItems = 20;
self.items = [NSMutableArray arrayWithCapacity:countItems];
for (int i = 0; i < countItems; i++) {
[self.items addObject:@(arc4random() % 100)];
}
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
self.button.backgroundColor = [UIColor yellowColor];
[self.button setTitle:@"Done" forState:UIControlStateNormal];
[self.button addTarget:self action:@selector(stopPicking) forControlEvents:UIControlEventTouchUpInside];
self.button.enabled = self.isPicking;
[self.view addSubview:self.button];
// use a container for easy alignment of selected item view to center of table
_tableViewContainer = [[UIView alloc] init];
[self.view addSubview:_tableViewContainer];
_tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
self.tableView.delegate = self;
self.tableView.dataSource = self;
[self.tableViewContainer addSubview:self.tableView];
}
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
CGFloat const buttonHeight = 100.0f;
CGRect const buttonFrame = CGRectMake(0.0f, 0.0f, self.view.bounds.size.width, buttonHeight);
self.button.frame = buttonFrame;
CGRect tableFrame = self.view.bounds;
tableFrame.origin.y += buttonHeight;
tableFrame.size.height -= buttonHeight;
self.tableViewContainer.frame = tableFrame;
self.tableView.frame = self.tableViewContainer.bounds;
// allow table to scroll to first and last row
CGFloat selectedItemViewY = self.selectedItemView.center.y;
self.tableView.contentInset = UIEdgeInsetsMake(selectedItemViewY, 0.0f, selectedItemViewY, 0.0f);
}
#pragma mark - Custom
- (SelectedItemView *)selectedItemView
{
if (!_selectedItemView) {
CGRect frame = CGRectMake(0.0f, 0.0f, self.tableView.bounds.size.width, self.tableView.rowHeight);
_selectedItemView = [[SelectedItemView alloc] initWithFrame:frame];
_selectedItemView.center = CGPointMake(self.tableView.bounds.size.width * 0.5f, self.tableView.bounds.size.height * 0.5f);
_selectedItemView.hidden = YES;
[self.tableViewContainer addSubview:_selectedItemView];
}
return _selectedItemView;
}
- (void)startPickingForItemAtIndex:(NSInteger)index
{
if (self.isPicking) {
return;
}
self.picking = YES;
// update tableview
self.selectedItem = [self.items objectAtIndex:index];
[self.items removeObjectAtIndex:index];
[self.tableView reloadData];
[self repositionCells];
// update views
self.selectedItemView.label.text = [NSString stringWithFormat:@"%@", self.selectedItem];
self.selectedItemView.hidden = NO;
self.button.enabled = YES;
}
- (void)stopPicking
{
if (!self.isPicking) {
return;
}
self.picking = NO;
// calculate new index for item
NSSortDescriptor *sd = [NSSortDescriptor sortDescriptorWithKey:@"row" ascending:YES];
NSArray *sds = [NSArray arrayWithObject:sd];
NSArray *indexPaths = [[self.tableView indexPathsForVisibleRows] sortedArrayUsingDescriptors:sds];
NSInteger selectedItemIndex = NSNotFound;
for (NSIndexPath *indexPath in indexPaths) {
if ([self isCellAtIndexPathBelowSelectedItemView:indexPath]) {
selectedItemIndex = indexPath.row;
break;
}
}
if (selectedItemIndex == NSNotFound) {
selectedItemIndex = self.items.count;
}
// update tableview
[self.items insertObject:self.selectedItem atIndex:selectedItemIndex];
self.selectedItem = nil;
[self.tableView reloadData];
// update views
self.selectedItemView.hidden = YES;
self.button.enabled = NO;
}
- (BOOL)isCellAtIndexPathBelowSelectedItemView:(NSIndexPath *)indexPath
{
CGFloat yInTable = indexPath.row * self.tableView.rowHeight;
CGFloat yInContainer = yInTable - self.tableView.contentOffset.y;
return yInContainer > self.selectedItemView.frame.origin.y;
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.items.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
cell.textLabel.text = [NSString stringWithFormat:@"%@", [self.items objectAtIndex:indexPath.row]];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (self.isPicking) {
[self stopPicking];
}
// scroll position seems to be confused... UITableViewScrollPositionMiddle doesn't work?
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:NO];
[self startPickingForItemAtIndex:indexPath.row];
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (self.isPicking) {
[self repositionCells];
}
}
- (void)repositionCells
{
CGFloat tableOffset = self.tableView.contentOffset.y;
NSArray *indexPaths = [self.tableView indexPathsForVisibleRows];
CGFloat selectedItemViewY = self.selectedItemView.frame.origin.y;
CGFloat const bufferHeight = self.tableView.rowHeight; // adjust to liking
for (NSIndexPath *indexPath in indexPaths) {
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
CGRect cellFrame = cell.frame;
CGFloat cellYInTable = indexPath.row * self.tableView.rowHeight;
cellFrame.origin.y = cellYInTable;
CGFloat cellYInContainer = cellYInTable - tableOffset;
if (cellYInContainer <= selectedItemViewY) {
cellFrame.origin.y -= bufferHeight;
} else {
cellFrame.origin.y += bufferHeight;
}
cell.frame = cellFrame;
}
}
@end
@interface SelectedItemView ()
@property (strong, nonatomic) UILabel *label;
@end
@implementation SelectedItemView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.userInteractionEnabled = NO;
self.backgroundColor = [UIColor blueColor];
_label = [[UILabel alloc] init];
_label.backgroundColor = [UIColor clearColor];
[self addSubview:_label];
}
return self;
}
- (void)layoutSubviews
{
[super layoutSubviews];
self.label.frame = self.bounds;
}
@end
答案 1 :(得分:2)
当你在编辑模式中选择一个单元格时。做这些:
renderInContext
剪切移动的单元格的图像。干杯很开心。
答案 2 :(得分:0)
由于我的答案是最好的,所以我会提供自己的答案。
我在GitHub上建立了一个名为PickerTableView的项目。在开发分支上工作。该项目使用Cocoapods作为依赖项。选择正在运行,我已经将TableView子类化为处理滚动单元格的移动。
答案 3 :(得分:0)
这是一个做你想做的事情的例子(也就是经过一些调整之后)。我认为它的代码非常简单:
https://github.com/nielsbot/funny-tables
(对于您的使用案例,当您进入编辑模式时,您会显示centerTableView
和bottomTableView
。)