feat:List add header and footer

This commit is contained in:
pengfei.zhou 2021-10-09 16:50:34 +08:00 committed by osborn
parent f6d117da06
commit 5224be8f90
13 changed files with 243 additions and 46 deletions

View File

@ -39,14 +39,16 @@ import pub.doric.shader.ViewNode;
* @CreateDate: 2019-11-12 * @CreateDate: 2019-11-12
*/ */
class ListAdapter extends RecyclerView.Adapter<ListAdapter.DoricViewHolder> { class ListAdapter extends RecyclerView.Adapter<ListAdapter.DoricViewHolder> {
private static final int TYPE_LOAD_MORE = -1;
private static final int TYPE_HEADER = -2;
private static final int TYPE_FOOTER = -3;
private final ListNode listNode; private final ListNode listNode;
ListAdapter(ListNode listNode) { ListAdapter(ListNode listNode) {
this.listNode = listNode; this.listNode = listNode;
} }
private int itemCount = 0; int itemCount = 0;
private int loadAnchor = 0; private int loadAnchor = 0;
@NonNull @NonNull
@ -65,21 +67,35 @@ class ListAdapter extends RecyclerView.Adapter<ListAdapter.DoricViewHolder> {
holder.listItemNode.setId(jsObject.getProperty("id").asString().value()); holder.listItemNode.setId(jsObject.getProperty("id").asString().value());
holder.listItemNode.blend(jsObject.getProperty("props").asObject()); holder.listItemNode.blend(jsObject.getProperty("props").asObject());
} }
if (position >= this.listNode.itemCount && !TextUtils.isEmpty(this.listNode.onLoadMoreFuncId)) { if (this.listNode.loadMore
&& position == this.itemCount + (this.listNode.hasHeader() ? 1 : 0)
&& !TextUtils.isEmpty(this.listNode.onLoadMoreFuncId)) {
callLoadMore(); callLoadMore();
} }
} }
@Override @Override
public int getItemCount() { public int getItemCount() {
return this.itemCount; return this.itemCount
+ (this.listNode.loadMore ? 1 : 0)
+ (this.listNode.hasHeader() ? 1 : 0)
+ (this.listNode.hasFooter() ? 1 : 0);
} }
@Override @Override
public int getItemViewType(int position) { public int getItemViewType(int position) {
if (position >= this.listNode.itemCount) { if (this.listNode.hasHeader() && position == 0) {
return Integer.MAX_VALUE; return TYPE_HEADER;
} }
if (this.listNode.hasFooter() && position == this.getItemCount() - 1) {
return TYPE_FOOTER;
}
if (position >= this.itemCount + (this.listNode.hasHeader() ? 1 : 0)) {
return TYPE_LOAD_MORE;
}
JSValue value = getItemModel(position); JSValue value = getItemModel(position);
if (value != null && value.isObject()) { if (value != null && value.isObject()) {
if (value.asObject().getProperty("props").asObject().getProperty("identifier").isString()) { if (value.asObject().getProperty("props").asObject().getProperty("identifier").isString()) {
@ -89,14 +105,21 @@ class ListAdapter extends RecyclerView.Adapter<ListAdapter.DoricViewHolder> {
return super.getItemViewType(position); return super.getItemViewType(position);
} }
public void setItemCount(int itemCount) {
this.itemCount = itemCount;
}
private JSValue getItemModel(int position) { private JSValue getItemModel(int position) {
if (position >= this.listNode.itemCount) { if (this.listNode.hasHeader() && position == 0) {
return this.listNode.getSubModel(this.listNode.headerViewId);
}
if (this.listNode.hasFooter() && position == this.getItemCount() - 1) {
return this.listNode.getSubModel(this.listNode.footerViewId);
}
if (position >= this.itemCount + (this.listNode.hasHeader() ? 1 : 0)) {
return this.listNode.getSubModel(this.listNode.loadMoreViewId); return this.listNode.getSubModel(this.listNode.loadMoreViewId);
} }
if (this.listNode.hasHeader()) {
position--;
}
String id = listNode.itemValues.get(position); String id = listNode.itemValues.get(position);
if (TextUtils.isEmpty(id)) { if (TextUtils.isEmpty(id)) {
int batchCount = listNode.batchCount; int batchCount = listNode.batchCount;

View File

@ -15,6 +15,7 @@
*/ */
package pub.doric.shader.list; package pub.doric.shader.list;
import android.annotation.SuppressLint;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.SparseArray; import android.util.SparseArray;
import android.view.GestureDetector; import android.view.GestureDetector;
@ -61,6 +62,8 @@ public class ListNode extends SuperNode<RecyclerView> implements IDoricScrollabl
SparseArray<String> itemValues = new SparseArray<>(); SparseArray<String> itemValues = new SparseArray<>();
boolean loadMore = false; boolean loadMore = false;
String loadMoreViewId; String loadMoreViewId;
String headerViewId;
String footerViewId;
private final Set<DoricScrollChangeListener> listeners = new HashSet<>(); private final Set<DoricScrollChangeListener> listeners = new HashSet<>();
private String onScrollFuncId; private String onScrollFuncId;
private String onScrollEndFuncId; private String onScrollEndFuncId;
@ -167,9 +170,10 @@ public class ListNode extends SuperNode<RecyclerView> implements IDoricScrollabl
super.blend(jsObject); super.blend(jsObject);
if (mView != null) { if (mView != null) {
mView.post(new Runnable() { mView.post(new Runnable() {
@SuppressLint("NotifyDataSetChanged")
@Override @Override
public void run() { public void run() {
listAdapter.setItemCount(itemCount + (loadMore ? 1 : 0)); listAdapter.itemCount = itemCount;
listAdapter.notifyDataSetChanged(); listAdapter.notifyDataSetChanged();
} }
}); });
@ -240,6 +244,12 @@ public class ListNode extends SuperNode<RecyclerView> implements IDoricScrollabl
} }
}); });
break; break;
case "header":
this.headerViewId = prop.asString().value();
break;
case "footer":
this.footerViewId = prop.asString().value();
break;
default: default:
super.blend(view, name, prop); super.blend(view, name, prop);
break; break;
@ -317,4 +327,11 @@ public class ListNode extends SuperNode<RecyclerView> implements IDoricScrollabl
} }
} }
boolean hasHeader() {
return !TextUtils.isEmpty(this.headerViewId);
}
boolean hasFooter() {
return !TextUtils.isEmpty(this.footerViewId);
}
} }

View File

@ -47,6 +47,12 @@ class ListVH extends ViewHolder {
height: 50, height: 50,
}), }),
this.list = list({ this.list = list({
header: listItem(text({
text: "This is header",
})),
footer: listItem(text({
text: "This is footer",
})),
itemCount: 0, itemCount: 0,
layoutConfig: { layoutConfig: {
widthSpec: LayoutSpec.MOST, widthSpec: LayoutSpec.MOST,

View File

@ -53,6 +53,8 @@ @interface DoricListNode () <UITableViewDataSource, UITableViewDelegate>
@property(nonatomic, copy) NSString *onLoadMoreFuncId; @property(nonatomic, copy) NSString *onLoadMoreFuncId;
@property(nonatomic, copy) NSString *renderItemFuncId; @property(nonatomic, copy) NSString *renderItemFuncId;
@property(nonatomic, copy) NSString *loadMoreViewId; @property(nonatomic, copy) NSString *loadMoreViewId;
@property(nonatomic, copy) NSString *headerViewId;
@property(nonatomic, copy) NSString *footerViewId;
@property(nonatomic, assign) BOOL loadMore; @property(nonatomic, assign) BOOL loadMore;
@property(nonatomic, assign) NSUInteger loadAnchor; @property(nonatomic, assign) NSUInteger loadAnchor;
@property(nonatomic, strong) NSMutableSet <DoricDidScrollBlock> *didScrollBlocks; @property(nonatomic, strong) NSMutableSet <DoricDidScrollBlock> *didScrollBlocks;
@ -93,6 +95,14 @@ - (UITableView *)build {
}]; }];
} }
- (BOOL)hasHeader {
return self.headerViewId && self.headerViewId.length > 0;
}
- (BOOL)hasFooter {
return self.footerViewId && self.footerViewId.length > 0;
}
- (void)blendView:(UITableView *)view forPropName:(NSString *)name propValue:(id)prop { - (void)blendView:(UITableView *)view forPropName:(NSString *)name propValue:(id)prop {
if ([@"scrollable" isEqualToString:name]) { if ([@"scrollable" isEqualToString:name]) {
self.view.scrollEnabled = [prop boolValue]; self.view.scrollEnabled = [prop boolValue];
@ -126,17 +136,17 @@ - (void)blendView:(UITableView *)view forPropName:(NSString *)name propValue:(id
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
[view scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:[prop unsignedIntegerValue] inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO]; [view scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:[prop unsignedIntegerValue] inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];
}); });
} else if ([@"header" isEqualToString:name]) {
self.headerViewId = prop;
} else if ([@"footer" isEqualToString:name]) {
self.footerViewId = prop;
} else { } else {
[super blendView:view forPropName:name propValue:prop]; [super blendView:view forPropName:name propValue:prop];
} }
} }
- (void)blend:(NSDictionary *)props {
[super blend:props];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.itemCount + (self.loadMore ? 1 : 0); return self.itemCount + (self.loadMore ? 1 : 0) + (self.hasHeader ? 1 : 0) + (self.hasFooter ? 1 : 0);
} }
- (void)callLoadMore { - (void)callLoadMore {
@ -152,13 +162,24 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N
NSDictionary *props = model[@"props"]; NSDictionary *props = model[@"props"];
NSString *reuseId = props[@"identifier"]; NSString *reuseId = props[@"identifier"];
self.itemActions[@(position)] = props[@"actions"]; self.itemActions[@(position)] = props[@"actions"];
if (position > 0 && position >= self.itemCount && self.onLoadMoreFuncId) { if (self.hasHeader && position == 0) {
reuseId = @"doricHeaderCell";
} else if (self.hasFooter
&& position == self.itemCount
+ (self.loadMore ? 1 : 0)
+ (self.hasHeader ? 1 : 0)
+ (self.hasFooter ? 1 : 0)) {
reuseId = @"doricFooterCell";
} else if (self.loadMore
&& position > 0
&& position == self.itemCount + (self.hasHeader ? 1 : 0)
&& self.onLoadMoreFuncId) {
reuseId = @"doricLoadMoreCell"; reuseId = @"doricLoadMoreCell";
[self callLoadMore]; [self callLoadMore];
} }
DoricTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseId ?: @"doriccell"]; DoricTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseId ?: @"doricCell"];
if (!cell) { if (!cell) {
cell = [[DoricTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseId ?: @"doriccell"]; cell = [[DoricTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseId ?: @"doricCell"];
DoricListItemNode *listItemNode = (DoricListItemNode *) [DoricViewNode create:self.doricContext withType:@"ListItem"]; DoricListItemNode *listItemNode = (DoricListItemNode *) [DoricViewNode create:self.doricContext withType:@"ListItem"];
[listItemNode initWithSuperNode:self]; [listItemNode initWithSuperNode:self];
cell.doricListItemNode = listItemNode; cell.doricListItemNode = listItemNode;
@ -239,9 +260,22 @@ - (nullable UISwipeActionsConfiguration *)tableView:(UITableView *)tableView tra
} }
- (NSDictionary *)itemModelAt:(NSUInteger)position { - (NSDictionary *)itemModelAt:(NSUInteger)position {
if (position >= self.itemCount) { 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 (position >= self.itemCount + (self.hasHeader ? 1 : 0)) {
return [self subModelOf:self.loadMoreViewId]; return [self subModelOf:self.loadMoreViewId];
} }
if (self.hasHeader) {
position--;
}
NSString *viewId = self.itemViewIds[@(position)]; NSString *viewId = self.itemViewIds[@(position)];
if (viewId && viewId.length > 0) { if (viewId && viewId.length > 0) {
return [self subModelOf:viewId]; return [self subModelOf:viewId];
@ -262,7 +296,7 @@ - (NSDictionary *)itemModelAt:(NSUInteger)position {
NSUInteger pos = start + idx; NSUInteger pos = start + idx;
self.itemViewIds[@(pos)] = thisViewId; self.itemViewIds[@(pos)] = thisViewId;
}]; }];
NSString *viewId = self.itemViewIds[@(position)]; viewId = self.itemViewIds[@(position)];
if (viewId && viewId.length > 0) { if (viewId && viewId.length > 0) {
return [self subModelOf:viewId]; return [self subModelOf:viewId];
} else { } else {
@ -431,18 +465,18 @@ - (void)removeDidScrollBlock:(__nonnull DoricDidScrollBlock)didScrollListener {
- (void)scrollToItem:(NSDictionary *)params { - (void)scrollToItem:(NSDictionary *)params {
BOOL animated = [params[@"animated"] boolValue]; BOOL animated = [params[@"animated"] boolValue];
NSUInteger scrolledPosition = [params[@"index"] unsignedIntegerValue]; NSUInteger scrolledPosition = [params[@"index"] unsignedIntegerValue];
if (scrolledPosition < self.itemCount && scrolledPosition >= 0) { if (scrolledPosition < self.itemCount && scrolledPosition >= 0) {
for (int i = 0; i <= scrolledPosition; i++) { for (int i = 0; i <= scrolledPosition; i++) {
[self tableView:self.view cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]]; [self tableView:self.view cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
} }
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
[self.view scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:scrolledPosition inSection:0] atScrollPosition:UITableViewScrollPositionNone animated:animated]; [self.view scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:scrolledPosition inSection:0] atScrollPosition:UITableViewScrollPositionNone animated:animated];
}); });
} else { } else {
[self.doricContext.driver.registry onLog:DoricLogTypeError [self.doricContext.driver.registry onLog:DoricLogTypeError
message:[NSString stringWithFormat:@"scrollToItem Error:%@", @"scrolledPosition range error"]]; message:[NSString stringWithFormat:@"scrollToItem Error:%@", @"scrolledPosition range error"]];
} }
} }

View File

@ -2326,12 +2326,17 @@ var List = /** @class */ (function (_super) {
return _this; return _this;
} }
List.prototype.allSubviews = function () { List.prototype.allSubviews = function () {
var ret = __spreadArray$1([], __read$1(this.cachedViews.values()));
if (this.loadMoreView) { if (this.loadMoreView) {
return __spreadArray$1(__spreadArray$1([], __read$1(this.cachedViews.values())), [this.loadMoreView]); ret.push(this.loadMoreView);
} }
else { if (this.header) {
return this.cachedViews.values(); ret.push(this.header);
} }
if (this.footer) {
ret.push(this.footer);
}
return ret;
}; };
List.prototype.scrollToItem = function (context, index, config) { List.prototype.scrollToItem = function (context, index, config) {
var animated = config === null || config === void 0 ? void 0 : config.animated; var animated = config === null || config === void 0 ? void 0 : config.animated;
@ -2358,6 +2363,12 @@ var List = /** @class */ (function (_super) {
if (this.loadMoreView) { if (this.loadMoreView) {
this.dirtyProps['loadMoreView'] = this.loadMoreView.viewId; this.dirtyProps['loadMoreView'] = this.loadMoreView.viewId;
} }
if (this.header) {
this.dirtyProps['header'] = this.header.viewId;
}
if (this.footer) {
this.dirtyProps['footer'] = this.footer.viewId;
}
return _super.prototype.toModel.call(this); return _super.prototype.toModel.call(this);
}; };
__decorate$9([ __decorate$9([
@ -2404,6 +2415,14 @@ var List = /** @class */ (function (_super) {
Property, Property,
__metadata$9("design:type", Boolean) __metadata$9("design:type", Boolean)
], List.prototype, "bounces", void 0); ], List.prototype, "bounces", void 0);
__decorate$9([
Property,
__metadata$9("design:type", ListItem)
], List.prototype, "header", void 0);
__decorate$9([
Property,
__metadata$9("design:type", ListItem)
], List.prototype, "footer", void 0);
return List; return List;
}(Superview)); }(Superview));
function list(config) { function list(config) {

View File

@ -1747,12 +1747,17 @@ class List extends Superview {
this.batchCount = 15; this.batchCount = 15;
} }
allSubviews() { allSubviews() {
const ret = [...this.cachedViews.values()];
if (this.loadMoreView) { if (this.loadMoreView) {
return [...this.cachedViews.values(), this.loadMoreView]; ret.push(this.loadMoreView);
} }
else { if (this.header) {
return this.cachedViews.values(); ret.push(this.header);
} }
if (this.footer) {
ret.push(this.footer);
}
return ret;
} }
scrollToItem(context, index, config) { scrollToItem(context, index, config) {
const animated = config === null || config === void 0 ? void 0 : config.animated; const animated = config === null || config === void 0 ? void 0 : config.animated;
@ -1778,6 +1783,12 @@ class List extends Superview {
if (this.loadMoreView) { if (this.loadMoreView) {
this.dirtyProps['loadMoreView'] = this.loadMoreView.viewId; this.dirtyProps['loadMoreView'] = this.loadMoreView.viewId;
} }
if (this.header) {
this.dirtyProps['header'] = this.header.viewId;
}
if (this.footer) {
this.dirtyProps['footer'] = this.footer.viewId;
}
return super.toModel(); return super.toModel();
} }
} }
@ -1825,6 +1836,14 @@ __decorate$9([
Property, Property,
__metadata$9("design:type", Boolean) __metadata$9("design:type", Boolean)
], List.prototype, "bounces", void 0); ], List.prototype, "bounces", void 0);
__decorate$9([
Property,
__metadata$9("design:type", ListItem)
], List.prototype, "header", void 0);
__decorate$9([
Property,
__metadata$9("design:type", ListItem)
], List.prototype, "footer", void 0);
function list(config) { function list(config) {
const ret = new List; const ret = new List;
ret.apply(config); ret.apply(config);

View File

@ -3268,12 +3268,17 @@ class List extends Superview {
this.batchCount = 15; this.batchCount = 15;
} }
allSubviews() { allSubviews() {
const ret = [...this.cachedViews.values()];
if (this.loadMoreView) { if (this.loadMoreView) {
return [...this.cachedViews.values(), this.loadMoreView]; ret.push(this.loadMoreView);
} }
else { if (this.header) {
return this.cachedViews.values(); ret.push(this.header);
} }
if (this.footer) {
ret.push(this.footer);
}
return ret;
} }
scrollToItem(context, index, config) { scrollToItem(context, index, config) {
const animated = config === null || config === void 0 ? void 0 : config.animated; const animated = config === null || config === void 0 ? void 0 : config.animated;
@ -3299,6 +3304,12 @@ class List extends Superview {
if (this.loadMoreView) { if (this.loadMoreView) {
this.dirtyProps['loadMoreView'] = this.loadMoreView.viewId; this.dirtyProps['loadMoreView'] = this.loadMoreView.viewId;
} }
if (this.header) {
this.dirtyProps['header'] = this.header.viewId;
}
if (this.footer) {
this.dirtyProps['footer'] = this.footer.viewId;
}
return super.toModel(); return super.toModel();
} }
} }
@ -3346,6 +3357,14 @@ __decorate$9([
Property, Property,
__metadata$9("design:type", Boolean) __metadata$9("design:type", Boolean)
], List.prototype, "bounces", void 0); ], List.prototype, "bounces", void 0);
__decorate$9([
Property,
__metadata$9("design:type", ListItem)
], List.prototype, "header", void 0);
__decorate$9([
Property,
__metadata$9("design:type", ListItem)
], List.prototype, "footer", void 0);
function list(config) { function list(config) {
const ret = new List; const ret = new List;
ret.apply(config); ret.apply(config);

4
doric-js/index.d.ts vendored
View File

@ -699,7 +699,7 @@ declare module 'doric/lib/src/widget/list' {
}[]; }[];
} }
export class List extends Superview { export class List extends Superview {
allSubviews(): IterableIterator<ListItem> | ListItem[]; allSubviews(): ListItem[];
itemCount: number; itemCount: number;
renderItem: (index: number) => ListItem; renderItem: (index: number) => ListItem;
batchCount: number; batchCount: number;
@ -720,6 +720,8 @@ declare module 'doric/lib/src/widget/list' {
* Take effect only on iOS * Take effect only on iOS
*/ */
bounces?: boolean; bounces?: boolean;
header?: ListItem;
footer?: ListItem;
scrollToItem(context: BridgeContext, index: number, config?: { scrollToItem(context: BridgeContext, index: number, config?: {
animated?: boolean; animated?: boolean;
}): Promise<any>; }): Promise<any>;

View File

@ -15,7 +15,7 @@ export declare class ListItem extends Stack {
} }
export declare class List extends Superview { export declare class List extends Superview {
private cachedViews; private cachedViews;
allSubviews(): IterableIterator<ListItem> | ListItem[]; allSubviews(): ListItem[];
itemCount: number; itemCount: number;
renderItem: (index: number) => ListItem; renderItem: (index: number) => ListItem;
batchCount: number; batchCount: number;
@ -36,6 +36,8 @@ export declare class List extends Superview {
* Take effect only on iOS * Take effect only on iOS
*/ */
bounces?: boolean; bounces?: boolean;
header?: ListItem;
footer?: ListItem;
scrollToItem(context: BridgeContext, index: number, config?: { scrollToItem(context: BridgeContext, index: number, config?: {
animated?: boolean; animated?: boolean;
}): Promise<any>; }): Promise<any>;

View File

@ -43,12 +43,17 @@ export class List extends Superview {
this.batchCount = 15; this.batchCount = 15;
} }
allSubviews() { allSubviews() {
const ret = [...this.cachedViews.values()];
if (this.loadMoreView) { if (this.loadMoreView) {
return [...this.cachedViews.values(), this.loadMoreView]; ret.push(this.loadMoreView);
} }
else { if (this.header) {
return this.cachedViews.values(); ret.push(this.header);
} }
if (this.footer) {
ret.push(this.footer);
}
return ret;
} }
scrollToItem(context, index, config) { scrollToItem(context, index, config) {
const animated = config === null || config === void 0 ? void 0 : config.animated; const animated = config === null || config === void 0 ? void 0 : config.animated;
@ -74,6 +79,12 @@ export class List extends Superview {
if (this.loadMoreView) { if (this.loadMoreView) {
this.dirtyProps['loadMoreView'] = this.loadMoreView.viewId; this.dirtyProps['loadMoreView'] = this.loadMoreView.viewId;
} }
if (this.header) {
this.dirtyProps['header'] = this.header.viewId;
}
if (this.footer) {
this.dirtyProps['footer'] = this.footer.viewId;
}
return super.toModel(); return super.toModel();
} }
} }
@ -121,6 +132,14 @@ __decorate([
Property, Property,
__metadata("design:type", Boolean) __metadata("design:type", Boolean)
], List.prototype, "bounces", void 0); ], List.prototype, "bounces", void 0);
__decorate([
Property,
__metadata("design:type", ListItem)
], List.prototype, "header", void 0);
__decorate([
Property,
__metadata("design:type", ListItem)
], List.prototype, "footer", void 0);
export function list(config) { export function list(config) {
const ret = new List; const ret = new List;
ret.apply(config); ret.apply(config);

View File

@ -39,11 +39,17 @@ export class List extends Superview {
private cachedViews: Map<string, ListItem> = new Map private cachedViews: Map<string, ListItem> = new Map
allSubviews() { allSubviews() {
const ret = [...this.cachedViews.values()]
if (this.loadMoreView) { if (this.loadMoreView) {
return [...this.cachedViews.values(), this.loadMoreView] ret.push(this.loadMoreView)
} else {
return this.cachedViews.values()
} }
if (this.header) {
ret.push(this.header)
}
if (this.footer) {
ret.push(this.footer)
}
return ret
} }
@Property @Property
@ -81,6 +87,12 @@ export class List extends Superview {
@Property @Property
bounces?: boolean bounces?: boolean
@Property
header?: ListItem
@Property
footer?: ListItem
scrollToItem(context: BridgeContext, index: number, config?: { animated?: boolean, }) { scrollToItem(context: BridgeContext, index: number, config?: { animated?: boolean, }) {
const animated = config?.animated const animated = config?.animated
return this.nativeChannel(context, 'scrollToItem')({ index, animated, }) as Promise<any> return this.nativeChannel(context, 'scrollToItem')({ index, animated, }) as Promise<any>
@ -108,6 +120,12 @@ export class List extends Superview {
if (this.loadMoreView) { if (this.loadMoreView) {
this.dirtyProps['loadMoreView'] = this.loadMoreView.viewId this.dirtyProps['loadMoreView'] = this.loadMoreView.viewId
} }
if (this.header) {
this.dirtyProps['header'] = this.header.viewId
}
if (this.footer) {
this.dirtyProps['footer'] = this.footer.viewId
}
return super.toModel() return super.toModel()
} }
} }

View File

@ -3322,12 +3322,17 @@ class List extends Superview {
this.batchCount = 15; this.batchCount = 15;
} }
allSubviews() { allSubviews() {
const ret = [...this.cachedViews.values()];
if (this.loadMoreView) { if (this.loadMoreView) {
return [...this.cachedViews.values(), this.loadMoreView]; ret.push(this.loadMoreView);
} }
else { if (this.header) {
return this.cachedViews.values(); ret.push(this.header);
} }
if (this.footer) {
ret.push(this.footer);
}
return ret;
} }
scrollToItem(context, index, config) { scrollToItem(context, index, config) {
const animated = config === null || config === void 0 ? void 0 : config.animated; const animated = config === null || config === void 0 ? void 0 : config.animated;
@ -3353,6 +3358,12 @@ class List extends Superview {
if (this.loadMoreView) { if (this.loadMoreView) {
this.dirtyProps['loadMoreView'] = this.loadMoreView.viewId; this.dirtyProps['loadMoreView'] = this.loadMoreView.viewId;
} }
if (this.header) {
this.dirtyProps['header'] = this.header.viewId;
}
if (this.footer) {
this.dirtyProps['footer'] = this.footer.viewId;
}
return super.toModel(); return super.toModel();
} }
} }
@ -3400,6 +3411,14 @@ __decorate$9([
Property, Property,
__metadata$9("design:type", Boolean) __metadata$9("design:type", Boolean)
], List.prototype, "bounces", void 0); ], List.prototype, "bounces", void 0);
__decorate$9([
Property,
__metadata$9("design:type", ListItem)
], List.prototype, "header", void 0);
__decorate$9([
Property,
__metadata$9("design:type", ListItem)
], List.prototype, "footer", void 0);
function list(config) { function list(config) {
const ret = new List; const ret = new List;
ret.apply(config); ret.apply(config);

File diff suppressed because one or more lines are too long