水平的UITableView

41

我希望在我的iPad应用程序中实现一种布局,它具有可以左右滚动而不是上下滚动的uitable视图:

所以,不是:

行1 行2 行3 (垂直滚动) 它会是: 行1、行2、行3 (水平滚动)

我已经看到UITableview只设计成垂直滚动,所以使用转换不能得到期望的效果。是否有一种标准方法来利用类似于UITableview提供的数据源提供商完成此操作?
我基本上想做类似于iPad上的BBC新闻阅读器应用程序中的故事列表选择。

谢谢

7个回答

28

我已经发布了演示如何使用transforms实现水平滚动表视图的示例代码。它叫做EasyTableView,并为垂直和水平滚动表视图提供了相同的接口。


26

这是我使用的方法:

1) 实现自己的UITableView子类并覆盖其initWithCoder:方法如下所示:

- (id)initWithCoder:(NSCoder *)aDecoder
{
    assert([aDecoder isKindOfClass:[NSCoder class]]);

    self = [super initWithCoder:aDecoder];

    if (self) {

        const CGFloat k90DegreesCounterClockwiseAngle = (CGFloat) -(90 * M_PI / 180.0);

        CGRect frame = self.frame;
        self.transform = CGAffineTransformRotate(CGAffineTransformIdentity, k90DegreesCounterClockwiseAngle);
        self.frame = frame;    

    }

    assert(self);
    return self;
}

2)创建自己的UITableViewCell类,并再次覆盖initWithCoder:

- (id)initWithCoder:(NSCoder *)aDecoder
{
    assert([aDecoder isKindOfClass:[NSCoder class]]);

    self = [super initWithCoder:aDecoder];

    if (self) {

        const CGFloat k90DegreesClockwiseAngle = (CGFloat) (90 * M_PI / 180.0);

        self.transform = CGAffineTransformRotate(CGAffineTransformIdentity, k90DegreesClockwiseAngle);
    }

    assert(self);
    return self;
}

3)现在,您可以在IB中创建一个UITableView元素,并在身份检查器中将其类设置为"MyHorizontalTableView"。

4)在IB中创建UITableViewCell元素,并在身份检查器中将其类设置为"MyHorizontalTableViewCell"。

就是这样。

如果您不喜欢使用IB来实例化您的表视图或单元格,也可以通过覆盖其他初始化程序来使用此方法。

我围绕这个概念构建了一个示例项目,可以在GitHub上找到。


3
很好,但是有一个问题...如果我在运行应用程序时尝试调整表格大小,单元格不会垂直调整大小。水平大小不是问题,因为代理中有heightForRow方法...但是没有一个用于宽度的方法...并且在转换后,自动调整大小将无法工作 :-( - Maurice Raguse
我需要完成这4个步骤吗? - Omer Obaid
@OmerObaid - 有其他实现相同结果的方法。你可以理论上覆盖其他初始化器。这只是其中一种方法。 - diegoreymendez
@diegoreymendez:在iOS 8.1.3(iPad)上,转换计算无法正常工作。 - Maulik
1
优秀的解决方案。整洁明了。+1 - viral
显示剩余4条评论

10

如果你的应用只需要支持iOS 6及以上版本,最好的方法是使用UICollectionView

如果你需要支持iOS 4/5,那么可以尝试使用其中一个开源重写的UICollectionView库,例如PSTCollectionView


你能给我一些提示(链接或代码),告诉我如何做到这一点吗?我猜我得玩一下 UICollectionViewLayout。任何帮助都将不胜感激。谢谢! - Colas
你是正确的;你应该使用单行网格布局。 - JosephH
我该如何创建单行网格布局?到目前为止,我使用了一个技巧:我要求两个元素之间的最小空间非常大。 - Colas

5
这个问题已经被苹果公司回答了。苹果公司提供了滚动示例。

演示如何实现两种不同风格的UIScrollViews。第一个滚动条包含多个图像,展示如何使用多个数据块(在我们的情况下是5个单独的UIImageViews)布局大型内容。

这也适用于iPad。

3
资源链接已失效 :( - ULazdins
1
那个示例代码太老了。你仍然可以访问它:https://web-beta.archive.org/web/20100805074840/http://developer.apple.com:80/iphone/library/samplecode/Scrolling/Listings/ReadMe_txt.html - Saqib Saud

3

目前,您需要使用UIScrollView,并仅将滚动设置为水平滚动。至于数据,您需要自己处理dequeing和优化。如果你不期望有超过十几个对象,那么你可能可以跳过它,但如果它们是数据密集型的,请尝试实现类似UITableView使用的数据源和加载。请注意,BBC News阅读器应用程序还使用启用分页功能,以每个“页面(大约4个新闻图标)”滚动。


1
我写了一个简单的UIScrollView子类,就像UITableView一样实现了单元格重用,该项目MMHorizontalListView在gitHub上,还有一个测试项目,所以你可以看到如何使用它的示例,它也可以在旧的iOS版本(如4.x,可能甚至更旧)中使用。

1

有一个简单而巧妙的技巧可以使UITableView完美地实现垂直和水平滚动。

你可以使用autolayout或不使用 - 我将用autolayout来解释。

在你的UITableView上,有一个宽度约束和没有尾部对齐约束。将这个宽度约束与IBOutlet绑定,并在控制器中设置以下属性:

let contentWidth = 1000 // you calculate that
tableViewWidthConstraint.constant = contentWidth
tableView.contentSize.width = (contentWidth * 2) - UIScreen.main.bounds.size.width
需要在水平方向上渲染所有内容,以实现全宽度显示。通过将内容大小与屏幕大小进行比较,可以实现此功能。

以下位置均可使用,但您可以在生命周期的不同步骤中尝试:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    tableViewWidthConstraint.constant = contentWidth
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    tableView.contentSize.width = (contentWidth * 2) - UIScreen.main.bounds.size.width
}

// and this is needed to support rotation:
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        coordinator.animate(alongsideTransition: { (UIViewControllerTransitionCoordinatorContext) -> Void in
            self.tableView.contentSize.width = (contentWidth * 2) - UIScreen.main.bounds.size.width
        }, completion: nil)
    }
    super.viewWillTransition(to: size, with: coordinator)
}

尝试了上面的代码,但是表格视图无法水平滚动。表格视图的宽度已经增加了,但是没有滚动。请帮忙。 - Thripthi Haridas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接