J'ai un UICollectionView
et je souhaite afficher les cellules horizontalement, par exemple
En anglais , il doit afficher: | cellA | cellB | cellC |
En arabe , il doit afficher: [cellC | cellB | cellA |
Pour RTL, le UICollectionViewFlowLayout
fonctionne bien par défaut pour moi si chaque cellule a la même taille. Cependant, si j'implémente collectionView: layout: sizeForItemAtIndexPath:
et que je définis des largeurs différentes pour chaque cellule, la CollectionView devient:
| cellA | cellB | cellC |
Y a-t-il un moyen de résoudre ce problème?
3 Réponses :
Cette classe travaille pour moi pour afficher la vue de la collection de gauche à droite avec différentes tailles de cellules.
#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
J'espère que cette aide. faites-moi savoir si une aide supplémentaire est nécessaire.
Vous devez créer votre propre UICollectionViewLayout
, comme je l'ai dit dans mon commentaire, nous allons commencer à l'envers, vous devez d'abord ajouter ces lignes sur votre ViewController
viewDidLoad
méthode
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] } }
c'est le délégué dont vous avez besoin pour implémenter
extension ViewController: SemanticLayoutDelegate{ func semanticDisposition() -> SemanticDisposition { return SemanticDisposition.rigthToLeft } }
en utilisant votre nom ViewController au lieu de ViewController ofc
Et ici vous avez la classe SemanticLayout
, vérifiez qu'elle est entièrement personnalisable vous pouvez définir si votre UICollectionView
sera RTL ou LTR avec la méthode déléguée semanticDisposition
let semanticLayout = SemanticLayout() semanticLayout.delegate = self self.collectionView.collectionViewLayout = semanticLayout
Résultat RTL
class RTLSupportedCollectionViewFlowLayout: UICollectionViewFlowLayout { override var flipsHorizontallyInOppositeLayoutDirection: Bool { return true } } you can use this flow layout. it is only needed when the item size returned is not same for all the cells.
Vous devez implémenter votre propre
UICollectionViewLayout
pour gérer cela@ReinierMelian Je devrai peut-être utiliser votre suggestion pour le résoudre.
Je travaille sur une réponse maintenant, dès que j'aurai quelque chose, je la posterai
La hauteur de vos cellules sera fixe? ou la largeur et la hauteur sont variables?
@ReinierMelian Seule la largeur est variable.
Vérifiez si c'est ce dont vous avez besoin imgur.com/a/FgqS0Bc ?
@ReinierMelian Oui. Avez-vous écrit votre propre UICollectionViewLayout?
Vérifiez ma réponse et faites-le moi savoir