Ios UICollectionView没有';t在RTL中从右向左填充数据
我有一个Ios UICollectionView没有';t在RTL中从右向左填充数据,ios,right-to-left,collectionview,Ios,Right To Left,Collectionview,我有一个UICollectionView,希望水平显示单元格,例如 在英语中,应显示: | cellA | cellB | cellC | 阿拉伯语,应显示: [cellC | cellB | cellA | 对于RTL,默认情况下,如果每个单元格的大小相同,UICollectionViewFlowLayout对我来说效果很好。但是,如果我实现collectionView:layout:sizeForItemAtIndexPath:并为每个单元格设置不同的宽度,则collectionView将变
UICollectionView
,希望水平显示单元格,例如
在英语中,应显示:
| cellA | cellB | cellC |
阿拉伯语,应显示:
[cellC | cellB | cellA |
对于RTL,默认情况下,如果每个单元格的大小相同,UICollectionViewFlowLayout
对我来说效果很好。但是,如果我实现collectionView:layout:sizeForItemAtIndexPath:
并为每个单元格设置不同的宽度,则collectionView将变为:
|细胞|细胞B |细胞C|
有什么方法可以解决这个问题吗?这个类为我提供了从左到右显示集合视图的功能,其中包含不同大小的单元格
#import <UIKit/UIKit.h>
#import <objc/runtime.h>
static const char kBundleKey = 0;
@interface BundleEx : NSBundle
@end
@implementation BundleEx
- (NSString *)localizedStringForKey:(NSString *)key value:(NSString *)value table:(NSString *)tableName
{
NSBundle *bundle = objc_getAssociatedObject(self, &kBundleKey);
if (bundle) {
return [bundle localizedStringForKey:key value:value table:tableName];
}
else {
return [super localizedStringForKey:key value:value table:tableName];
}
}
@end
@implementation NSBundle (Language)
+ (void)setLanguage:(NSString *)language
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
object_setClass([NSBundle mainBundle], [BundleEx class]);
});
if (isCurrentLanguageRTL) {
if ([[[UIView alloc] init] respondsToSelector:@selector(setSemanticContentAttribute:)]) {
[[UIView appearance] setSemanticContentAttribute:UISemanticContentAttributeForceRightToLeft];
[[UITableView appearance] setSemanticContentAttribute:UISemanticContentAttributeForceRightToLeft];
}
}else {
//FOR LTR
if ([[[UIView alloc] init] respondsToSelector:@selector(setSemanticContentAttribute:)]) {
[[UIView appearance] setSemanticContentAttribute:UISemanticContentAttributeForceLeftToRight];
[[UITableView appearance] setSemanticContentAttribute:UISemanticContentAttributeForceLeftToRight];
}
}
[[NSUserDefaults standardUserDefaults] synchronize];
id value = language ? [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:language ofType:@"lproj"]] : nil;
objc_setAssociatedObject([NSBundle mainBundle], &kBundleKey, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end
#导入
#进口
静态常量char kBundleKey=0;
@接口BundleEx:NSBundle
@结束
@实现BundleEx
-(NSString*)localizedStringForKey:(NSString*)键值:(NSString*)值表:(NSString*)表名
{
NSBundle*bundle=objc_getAssociatedObject(self,&kBundleKey);
如果(捆绑){
return[bundle localizedStringForKey:key-value:value-table:tableName];
}
否则{
return[super-localizedStringForKey:key-value:value-table:tableName];
}
}
@结束
@实现包(语言)
+(void)setLanguage:(NSString*)语言
{
静态调度一次;
一次发送(一次发送)^{
对象_setClass([NSBundle mainBundle],[BundleEx class]);
});
if(isCurrentLanguageRTL){
if([[[UIView alloc]init]respondsToSelector:@selector(setSemanticContentAttribute:)])){
[[UIView外观]setSemanticContentAttribute:UISemanticContentAttributeForceRightToLeft];
[[UITableView外观]setSemanticContentAttribute:UISemanticContentAttributeForceRightToLeft];
}
}否则{
//对于LTR
if([[[UIView alloc]init]respondsToSelector:@selector(setSemanticContentAttribute:)])){
[[UIView外观]setSemanticContentAttribute:UISemanticContentAttributeForceLeftToRight];
[[UITableView外观]setSemanticContentAttribute:UISemanticContentAttributeForceLeftToRight];
}
}
[[NSUserDefaults standardUserDefaults]同步];
id值=语言?[NSBundle bundleWithPath:[[NSBundle mainBundle]pathForResource:类型为@“lproj”的语言]]:nil;
objc_setAssociatedObject([NSBundle mainBundle],&kBundleKey,value,objc_ASSOCIATION_RETAIN_NONATOMIC);
}
@结束
希望有此帮助。如果需要进一步帮助,请告诉我。您需要创建自己的
UICollectionViewLayout
,正如我在评论中所说,我们将从后面开始,首先您需要在ViewController
viewDidLoad方法中添加这行代码
let semanticLayout = SemanticLayout()
semanticLayout.delegate = self
self.collectionView.collectionViewLayout = semanticLayout
这是您需要实现的委托
extension ViewController: SemanticLayoutDelegate{
func semanticDisposition() -> SemanticDisposition {
return SemanticDisposition.rigthToLeft
}
}
使用ViewController名称而不是ViewController ofc
这里有SemanticLayout
类,检查它是否是完全可定制的您可以定义您的UICollectionView
是RTL还是LTR,并使用委托方法semanticDisposition
import UIKit
protocol SemanticLayoutDelegate: UICollectionViewDelegateFlowLayout {
func semanticDisposition() -> SemanticDisposition
}
enum SemanticDisposition {
case leftToRigth
case rigthToLeft
}
class SemanticLayout: UICollectionViewLayout {
weak var delegate: SemanticLayoutDelegate!
fileprivate var cellPadding: CGFloat = 10
fileprivate var cache = [UICollectionViewLayoutAttributes]()
fileprivate var contentHeight: CGFloat = 0
private var rowsWidth : [CGFloat] = [0]
private var avaiableSpaces : [(Int,CGFloat)] = []
private var currentRow : Int = 0
private var rowHeigths : CGFloat = -1.0
fileprivate var contentWidth: CGFloat {
guard let collectionView = collectionView else {
return 0
}
let insets = collectionView.contentInset
return collectionView.bounds.width - (insets.left + insets.right)
}
private func availableWidthForRow(index:Int) -> CGFloat {
let ocuppedWidth = self.rowsWidth[index]
return self.contentWidth - ocuppedWidth
}
private func canAddCellAtRow(rowIndex:Int,size:CGSize) ->Bool
{
if(availableWidthForRow(index: rowIndex) >= size.width) {
return true
}
return false
}
override var collectionViewContentSize: CGSize {
return CGSize(width: contentWidth, height: contentHeight)
}
override func prepare() {
// Check if cache is empty
guard cache.isEmpty == true, let collectionView = collectionView else {
return
}
for item in 0 ..< collectionView.numberOfItems(inSection: 0) {
let indexPath = IndexPath(item: item, section: 0)
let viewSize: CGSize = delegate.collectionView!(collectionView, layout: self, sizeForItemAt: indexPath)
if(self.rowHeigths < 0) {
self.rowHeigths = viewSize.height
}
let width = viewSize.width
let height = viewSize.height
var xOffset = self.rowsWidth[self.currentRow]
if(self.canAddCellAtRow(rowIndex: self.currentRow, size: viewSize)) {
if(self.delegate.semanticDisposition() == .rigthToLeft) {
xOffset = (contentWidth - self.rowsWidth[self.currentRow]) - width
}
} else {
self.currentRow += 1
self.rowsWidth.append(0.0)
xOffset = self.rowsWidth[self.currentRow]
if(self.delegate.semanticDisposition() == .rigthToLeft) {
xOffset = (contentWidth - self.rowsWidth[self.currentRow]) - width
}
}
let yOffset = CGFloat(self.currentRow) * self.rowHeigths
let frame = CGRect(x: xOffset, y: yOffset, width: width, height: height)
let insetFrame = frame.insetBy(dx: cellPadding, dy: cellPadding)
let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
attributes.frame = insetFrame
cache.append(attributes)
contentHeight = max(contentHeight, frame.maxY)
self.rowsWidth[self.currentRow] += width
}
}
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
var visibleLayoutAttributes = [UICollectionViewLayoutAttributes]()
// Loop through the cache and look for items in the rect
for attributes in cache {
if attributes.frame.intersects(rect) {
visibleLayoutAttributes.append(attributes)
}
}
return visibleLayoutAttributes
}
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
return cache[indexPath.item]
}
}
导入UIKit
协议SemanticalyOutDelegate:UICollectionViewDelegateFlowLayout{
func semanticDisposition()->semanticDisposition
}
枚举语义位置{
案例左图
案例右侧至左侧
}
类SemanticLayout:UICollectionViewLayout{
弱变量委托:SemanticalyOutDelegate!
fileprivate变量cellPadding:CGFloat=10
fileprivate变量缓存=[UICollectionViewLayoutAttribute]()
fileprivate var contentHeight:CGFloat=0
私有变量rowsWidth:[CGFloat]=[0]
私有变量可用空间:[(Int,CGFloat)]=[]
私有变量currentRow:Int=0
私有变量rowHeights:CGFloat=-1.0
fileprivate var contentWidth:CGFloat{
guard let collectionView=collectionView else{
返回0
}
let insets=collectionView.contentInset
return collectionView.bounds.width-(insets.left+insets.right)
}
私有函数可用WidthForrow(索引:Int)->CGFloat{
设ocuppedWidth=self.rowsWidth[index]
返回self.contentWidth-ocuppedWidth
}
私有函数canAddCellAtRow(行索引:Int,大小:CGSize)->Bool
{
if(availableWidthForRow(索引:rowIndex)>=size.width){
返回真值
}
返回错误
}
覆盖变量collectionViewContentSize:CGSize{
返回CGSize(宽度:contentWidth,高度:contentHeight)
}
重写func prepare(){
//检查缓存是否为空
guard cache.isEmpty==true,让collectionView=collectionView else{
返回
}
对于0..class RTLSupportedCollectionViewFlowLayout: UICollectionViewFlowLayout {
override var flipsHorizontallyInOppositeLayoutDirection: Bool {
return true
}
}