flowlayout add header and footer:iOS implement
This commit is contained in:
parent
0dbab344d9
commit
9429c75834
@ -70,23 +70,20 @@ class FlowAdapter extends RecyclerView.Adapter<FlowAdapter.DoricViewHolder> {
|
||||
holder.flowLayoutItemNode.blend(jsObject.getProperty("props").asObject());
|
||||
}
|
||||
if ((this.flowLayoutNode.hasHeader() && position == 0)
|
||||
|| (this.flowLayoutNode.hasFooter() && position == this.getItemCount() - 1)) {
|
||||
|| (this.flowLayoutNode.hasFooter() && position == this.getItemCount() - 1)
|
||||
|| this.flowLayoutNode.loadMore
|
||||
&& position == this.itemCount + (this.flowLayoutNode.hasHeader() ? 1 : 0)) {
|
||||
StaggeredGridLayoutManager.LayoutParams layoutParams = new StaggeredGridLayoutManager.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
holder.itemView.getLayoutParams().height
|
||||
);
|
||||
layoutParams.setFullSpan(true);
|
||||
holder.itemView.setLayoutParams(layoutParams);
|
||||
} else if (this.flowLayoutNode.loadMore
|
||||
}
|
||||
if (this.flowLayoutNode.loadMore
|
||||
&& position == this.itemCount + (this.flowLayoutNode.hasHeader() ? 1 : 0)
|
||||
&& !TextUtils.isEmpty(this.flowLayoutNode.onLoadMoreFuncId)) {
|
||||
callLoadMore();
|
||||
StaggeredGridLayoutManager.LayoutParams layoutParams = new StaggeredGridLayoutManager.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
holder.itemView.getLayoutParams().height
|
||||
);
|
||||
layoutParams.setFullSpan(true);
|
||||
holder.itemView.setLayoutParams(layoutParams);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@ class FlowDemo extends Panel {
|
||||
layoutConfig: layoutConfig().configWidth(LayoutSpec.MOST),
|
||||
})
|
||||
},
|
||||
loadMore: false,
|
||||
loadMore: true,
|
||||
onLoadMore: () => {
|
||||
setTimeout(() => {
|
||||
flowView.itemCount += 20
|
||||
|
@ -28,6 +28,8 @@ - (CGFloat)doricFlowLayoutItemHeightAtIndexPath:(NSIndexPath *)indexPath;
|
||||
|
||||
- (CGFloat)doricFlowLayoutItemWidthAtIndexPath:(NSIndexPath *)indexPath;
|
||||
|
||||
- (BOOL)doricFlowLayoutItemFullSpan:(NSIndexPath *)indexPath;
|
||||
|
||||
- (CGFloat)doricFlowLayoutColumnSpace;
|
||||
|
||||
- (CGFloat)doricFlowLayoutRowSpace;
|
||||
@ -92,7 +94,7 @@ - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSInde
|
||||
NSNumber *minYOfColumn = @(0);
|
||||
NSArray<NSNumber *> *keys = self.columnHeightInfo.allKeys;
|
||||
NSArray<NSNumber *> *sortedKeys = [keys sortedArrayUsingComparator:^NSComparisonResult(NSNumber *obj1, NSNumber *obj2) {
|
||||
return [obj1 intValue] <= [obj2 intValue] ? -1 : 1;
|
||||
return ([obj1 intValue] <= [obj2 intValue] ? NSOrderedAscending : NSOrderedDescending);
|
||||
}];
|
||||
|
||||
for (NSNumber *key in sortedKeys) {
|
||||
@ -100,17 +102,15 @@ - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSInde
|
||||
minYOfColumn = key;
|
||||
}
|
||||
}
|
||||
|
||||
CGFloat width = [self.delegate doricFlowLayoutItemWidthAtIndexPath:indexPath];
|
||||
CGFloat height = [self.delegate doricFlowLayoutItemHeightAtIndexPath:indexPath];
|
||||
CGFloat x = (width + self.columnSpace) * [minYOfColumn integerValue];
|
||||
CGFloat x = 0;
|
||||
CGFloat y = [self.columnHeightInfo[minYOfColumn] floatValue];
|
||||
if (y > 0) {
|
||||
y += self.rowSpace;
|
||||
}
|
||||
|
||||
if (width == self.collectionView.width) {
|
||||
x = 0;
|
||||
if ([self.delegate doricFlowLayoutItemFullSpan:indexPath]) {
|
||||
NSNumber *maxYColumn = @(0);
|
||||
for (NSNumber *key in sortedKeys) {
|
||||
if ([self.columnHeightInfo[key] floatValue] > [self.columnHeightInfo[maxYColumn] floatValue]) {
|
||||
@ -119,8 +119,12 @@ - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSInde
|
||||
}
|
||||
CGFloat maxY = [self.columnHeightInfo[maxYColumn] floatValue];
|
||||
y = maxY + self.rowSpace;
|
||||
self.columnHeightInfo[maxYColumn] = @(y + height);
|
||||
for (NSNumber *key in self.columnHeightInfo.allKeys) {
|
||||
self.columnHeightInfo[key] = @(y + height);
|
||||
}
|
||||
} else {
|
||||
CGFloat columnWidth = (self.collectionView.width - (self.columnCount - 1) * self.columnSpace) / self.columnCount;
|
||||
x = (columnWidth + self.columnSpace) * [minYOfColumn integerValue];
|
||||
self.columnHeightInfo[minYOfColumn] = @(y + height);
|
||||
}
|
||||
UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
|
||||
@ -163,6 +167,8 @@ @interface DoricFlowLayoutNode () <UICollectionViewDataSource, UICollectionViewD
|
||||
|
||||
@property(nonatomic, copy) NSString *onLoadMoreFuncId;
|
||||
@property(nonatomic, copy) NSString *loadMoreViewId;
|
||||
@property(nonatomic, copy) NSString *headerViewId;
|
||||
@property(nonatomic, copy) NSString *footerViewId;
|
||||
@property(nonatomic, assign) BOOL loadMore;
|
||||
@property(nonatomic, strong) NSMutableSet <DoricDidScrollBlock> *didScrollBlocks;
|
||||
@property(nonatomic, copy) NSString *onScrollFuncId;
|
||||
@ -201,6 +207,14 @@ - (UICollectionView *)build {
|
||||
}];
|
||||
}
|
||||
|
||||
- (BOOL)hasHeader {
|
||||
return self.headerViewId && self.headerViewId.length > 0;
|
||||
}
|
||||
|
||||
- (BOOL)hasFooter {
|
||||
return self.footerViewId && self.footerViewId.length > 0;
|
||||
}
|
||||
|
||||
- (void)blendView:(UICollectionView *)view forPropName:(NSString *)name propValue:(id)prop {
|
||||
if ([@"scrollable" isEqualToString:name]) {
|
||||
self.view.scrollEnabled = [prop boolValue];
|
||||
@ -240,14 +254,35 @@ - (void)blendView:(UICollectionView *)view forPropName:(NSString *)name propValu
|
||||
self.onScrollFuncId = prop;
|
||||
} else if ([@"onScrollEnd" isEqualToString:name]) {
|
||||
self.onScrollEndFuncId = prop;
|
||||
} else if ([@"header" isEqualToString:name]) {
|
||||
self.headerViewId = prop;
|
||||
} else if ([@"footer" isEqualToString:name]) {
|
||||
self.footerViewId = prop;
|
||||
} else {
|
||||
[super blendView:view forPropName:name propValue:prop];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSDictionary *)itemModelAt:(NSUInteger)position {
|
||||
if (position >= self.itemCount) {
|
||||
return [self subModelOf:self.loadMoreViewId];
|
||||
if (self.hasHeader && position == 0) {
|
||||
return [self subModelOf:self.headerViewId];
|
||||
}
|
||||
if (self.hasFooter && position == self.itemCount
|
||||
+ (self.loadMore ? 1 : 0)
|
||||
+ (self.hasHeader ? 1 : 0)
|
||||
+ (self.hasFooter ? 1 : 0)
|
||||
- 1) {
|
||||
return [self subModelOf:self.footerViewId];
|
||||
}
|
||||
if (self.loadMore && position >= self.itemCount + (self.hasHeader ? 1 : 0)) {
|
||||
if (self.loadMoreViewId && self.loadMoreViewId.length > 0) {
|
||||
return [self subModelOf:self.loadMoreViewId];
|
||||
} else {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
if (self.hasHeader) {
|
||||
position--;
|
||||
}
|
||||
NSString *viewId = self.itemViewIds[@(position)];
|
||||
if (viewId && viewId.length > 0) {
|
||||
@ -331,7 +366,7 @@ - (void)callLoadMore {
|
||||
}
|
||||
|
||||
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
|
||||
return self.itemCount + (self.loadMore ? 1 : 0);
|
||||
return self.itemCount + (self.loadMore ? 1 : 0) + (self.hasHeader ? 1 : 0) + (self.hasFooter ? 1 : 0);
|
||||
}
|
||||
|
||||
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
|
||||
@ -339,7 +374,18 @@ - (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collection
|
||||
NSDictionary *model = [self itemModelAt:position];
|
||||
NSDictionary *props = model[@"props"];
|
||||
NSString *identifier = props[@"identifier"] ?: @"doricCell";
|
||||
if (position >= self.itemCount && self.onLoadMoreFuncId) {
|
||||
if (self.hasHeader && position == 0) {
|
||||
identifier = @"doricHeaderCell";
|
||||
} else if (self.hasFooter
|
||||
&& position == self.itemCount
|
||||
+ (self.loadMore ? 1 : 0)
|
||||
+ (self.hasHeader ? 1 : 0)
|
||||
+ (self.hasFooter ? 1 : 0)
|
||||
- 1) {
|
||||
identifier = @"doricFooterCell";
|
||||
} else if (self.loadMore
|
||||
&& position == self.itemCount + (self.hasHeader ? 1 : 0)
|
||||
&& self.onLoadMoreFuncId) {
|
||||
identifier = @"doricLoadMoreCell";
|
||||
[self callLoadMore];
|
||||
}
|
||||
@ -355,7 +401,16 @@ - (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collection
|
||||
DoricFlowLayoutItemNode *node = cell.viewNode;
|
||||
node.viewId = model[@"id"];
|
||||
[node blend:props];
|
||||
if (position >= self.itemCount) {
|
||||
BOOL fillWidth = (self.hasHeader && position == 0)
|
||||
|| (self.hasFooter
|
||||
&& position == self.itemCount
|
||||
+ (self.loadMore ? 1 : 0)
|
||||
+ (self.hasHeader ? 1 : 0)
|
||||
+ (self.hasFooter ? 1 : 0)
|
||||
- 1)
|
||||
|| (self.loadMore
|
||||
&& position == self.itemCount + (self.hasHeader ? 1 : 0));
|
||||
if (fillWidth) {
|
||||
node.view.width = collectionView.width;
|
||||
} else {
|
||||
node.view.width = (collectionView.width - (self.columnCount - 1) * self.columnSpace) / self.columnCount;
|
||||
@ -399,6 +454,19 @@ - (NSInteger)doricFlowLayoutColumnCount {
|
||||
return self.columnCount;
|
||||
}
|
||||
|
||||
- (BOOL)doricFlowLayoutItemFullSpan:(NSIndexPath *)indexPath {
|
||||
NSUInteger position = (NSUInteger) indexPath.row;
|
||||
return (self.hasHeader && position == 0)
|
||||
|| (self.hasFooter
|
||||
&& position == self.itemCount
|
||||
+ (self.loadMore ? 1 : 0)
|
||||
+ (self.hasHeader ? 1 : 0)
|
||||
+ (self.hasFooter ? 1 : 0)
|
||||
- 1)
|
||||
|| (self.loadMore
|
||||
&& position == self.itemCount + (self.hasHeader ? 1 : 0));
|
||||
}
|
||||
|
||||
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
|
||||
for (DoricDidScrollBlock block in self.didScrollBlocks) {
|
||||
block(scrollView);
|
||||
|
@ -168,7 +168,8 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N
|
||||
&& position == self.itemCount
|
||||
+ (self.loadMore ? 1 : 0)
|
||||
+ (self.hasHeader ? 1 : 0)
|
||||
+ (self.hasFooter ? 1 : 0)) {
|
||||
+ (self.hasFooter ? 1 : 0)
|
||||
- 1) {
|
||||
reuseId = @"doricFooterCell";
|
||||
} else if (self.loadMore
|
||||
&& position == self.itemCount + (self.hasHeader ? 1 : 0)
|
||||
@ -269,8 +270,12 @@ - (NSDictionary *)itemModelAt:(NSUInteger)position {
|
||||
- 1) {
|
||||
return [self subModelOf:self.footerViewId];
|
||||
}
|
||||
if (position >= self.itemCount + (self.hasHeader ? 1 : 0)) {
|
||||
return [self subModelOf:self.loadMoreViewId];
|
||||
if (self.loadMore && position >= self.itemCount + (self.hasHeader ? 1 : 0)) {
|
||||
if (self.loadMoreViewId && self.loadMoreViewId.length > 0) {
|
||||
return [self subModelOf:self.loadMoreViewId];
|
||||
} else {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
if (self.hasHeader) {
|
||||
position--;
|
||||
|
5
doric-js/index.d.ts
vendored
5
doric-js/index.d.ts
vendored
@ -143,6 +143,11 @@ declare module 'doric/lib/src/ui/panel' {
|
||||
onShow(): void;
|
||||
onHidden(): void;
|
||||
onEnvChanged(): void;
|
||||
/**
|
||||
* Build view of the current Panel
|
||||
* This could be called any times at any time when necessary.
|
||||
* @param rootView root view of this panel
|
||||
*/
|
||||
abstract build(rootView: Group): void;
|
||||
addHeadView(type: string, v: View): void;
|
||||
allHeadViews(): IterableIterator<Map<string, View>>;
|
||||
|
5
doric-js/lib/src/ui/panel.d.ts
vendored
5
doric-js/lib/src/ui/panel.d.ts
vendored
@ -10,6 +10,11 @@ export declare abstract class Panel {
|
||||
onShow(): void;
|
||||
onHidden(): void;
|
||||
onEnvChanged(): void;
|
||||
/**
|
||||
* Build view of the current Panel
|
||||
* This could be called any times at any time when necessary.
|
||||
* @param rootView root view of this panel
|
||||
*/
|
||||
abstract build(rootView: Group): void;
|
||||
private __data__?;
|
||||
private __root__;
|
||||
|
@ -43,6 +43,11 @@ export abstract class Panel {
|
||||
this.__root__.children.length = 0
|
||||
this.build(this.__root__)
|
||||
}
|
||||
/**
|
||||
* Build view of the current Panel
|
||||
* This could be called any times at any time when necessary.
|
||||
* @param rootView root view of this panel
|
||||
*/
|
||||
abstract build(rootView: Group): void
|
||||
|
||||
private __data__?: object
|
||||
|
Reference in New Issue
Block a user