feat:add onScroll and onScrollEnd for list and flowlayout

This commit is contained in:
pengfei.zhou 2020-03-11 13:41:22 +08:00 committed by osborn
parent 8db0e8e9f9
commit 7b371ca58b
16 changed files with 316 additions and 5 deletions

View File

@ -16,6 +16,7 @@
package pub.doric.shader.flowlayout;
import android.graphics.Rect;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
@ -23,6 +24,7 @@ import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
import com.github.pengfeizhou.jscore.JSONBuilder;
import com.github.pengfeizhou.jscore.JSObject;
import com.github.pengfeizhou.jscore.JSValue;
@ -80,6 +82,8 @@ public class FlowLayoutNode extends SuperNode<RecyclerView> implements IDoricScr
boolean loadMore = false;
String loadMoreViewId;
private Set<DoricScrollChangeListener> listeners = new HashSet<>();
private String onScrollFuncId;
private String onScrollEndFuncId;
public FlowLayoutNode(DoricContext doricContext) {
super(doricContext);
@ -143,6 +147,12 @@ public class FlowLayoutNode extends SuperNode<RecyclerView> implements IDoricScr
case "loadMore":
this.loadMore = prop.asBoolean().value();
break;
case "onScroll":
this.onScrollFuncId = prop.asString().value();
break;
case "onScrollEnd":
this.onScrollEndFuncId = prop.asString().value();
break;
default:
super.blend(view, name, prop);
break;
@ -204,11 +214,34 @@ public class FlowLayoutNode extends SuperNode<RecyclerView> implements IDoricScr
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int offsetX = recyclerView.computeHorizontalScrollOffset();
int offsetY = recyclerView.computeVerticalScrollOffset();
for (DoricScrollChangeListener listener : listeners) {
int offsetX = recyclerView.computeHorizontalScrollOffset();
int offsetY = recyclerView.computeVerticalScrollOffset();
listener.onScrollChange(recyclerView, offsetX, offsetY, offsetX - dx, offsetY - dy);
}
if (!TextUtils.isEmpty(onScrollFuncId)) {
callJSResponse(onScrollFuncId, new JSONBuilder()
.put("x", DoricUtils.px2dp(offsetX))
.put("y", DoricUtils.px2dp(offsetY))
.toJSONObject());
}
}
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
if (!TextUtils.isEmpty(onScrollEndFuncId)) {
int offsetX = recyclerView.computeHorizontalScrollOffset();
int offsetY = recyclerView.computeVerticalScrollOffset();
callJSResponse(
onScrollEndFuncId,
new JSONBuilder()
.put("x", DoricUtils.px2dp(offsetX))
.put("y", DoricUtils.px2dp(offsetY))
.toJSONObject());
}
}
}
});
return recyclerView;

View File

@ -15,6 +15,7 @@
*/
package pub.doric.shader.list;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
import android.view.View;
@ -23,6 +24,7 @@ import androidx.annotation.NonNull;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.github.pengfeizhou.jscore.JSONBuilder;
import com.github.pengfeizhou.jscore.JSObject;
import com.github.pengfeizhou.jscore.JSValue;
@ -35,6 +37,7 @@ import pub.doric.IDoricScrollable;
import pub.doric.extension.bridge.DoricPlugin;
import pub.doric.shader.SuperNode;
import pub.doric.shader.ViewNode;
import pub.doric.utils.DoricUtils;
/**
* @Description: com.github.penfeizhou.doric.widget
@ -52,6 +55,8 @@ public class ListNode extends SuperNode<RecyclerView> implements IDoricScrollabl
boolean loadMore = false;
String loadMoreViewId;
private Set<DoricScrollChangeListener> listeners = new HashSet<>();
private String onScrollFuncId;
private String onScrollEndFuncId;
public ListNode(DoricContext doricContext) {
super(doricContext);
@ -82,11 +87,33 @@ public class ListNode extends SuperNode<RecyclerView> implements IDoricScrollabl
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int offsetX = recyclerView.computeHorizontalScrollOffset();
int offsetY = recyclerView.computeVerticalScrollOffset();
for (DoricScrollChangeListener listener : listeners) {
int offsetX = recyclerView.computeHorizontalScrollOffset();
int offsetY = recyclerView.computeVerticalScrollOffset();
listener.onScrollChange(recyclerView, offsetX, offsetY, offsetX - dx, offsetY - dy);
}
if (!TextUtils.isEmpty(onScrollFuncId)) {
callJSResponse(onScrollFuncId, new JSONBuilder()
.put("x", DoricUtils.px2dp(offsetX))
.put("y", DoricUtils.px2dp(offsetY))
.toJSONObject());
}
}
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
if (!TextUtils.isEmpty(onScrollEndFuncId)) {
int offsetX = recyclerView.computeHorizontalScrollOffset();
int offsetY = recyclerView.computeVerticalScrollOffset();
callJSResponse(
onScrollEndFuncId,
new JSONBuilder()
.put("x", DoricUtils.px2dp(offsetX))
.put("y", DoricUtils.px2dp(offsetY))
.toJSONObject());
}
}
}
});
return recyclerView;
@ -134,6 +161,12 @@ public class ListNode extends SuperNode<RecyclerView> implements IDoricScrollabl
case "loadMore":
this.loadMore = prop.asBoolean().value();
break;
case "onScroll":
this.onScrollFuncId = prop.asString().value();
break;
case "onScrollEnd":
this.onScrollEndFuncId = prop.asString().value();
break;
default:
super.blend(view, name, prop);
break;

View File

@ -172,6 +172,8 @@ @interface DoricFlowLayoutNode () <UICollectionViewDataSource, UICollectionViewD
@property(nonatomic, copy) NSString *loadMoreViewId;
@property(nonatomic, assign) BOOL loadMore;
@property(nonatomic, strong) NSMutableSet <DoricDidScrollBlock> *didScrollBlocks;
@property(nonatomic, copy) NSString *onScrollFuncId;
@property(nonatomic, copy) NSString *onScrollEndFuncId;
@end
@implementation DoricFlowLayoutNode
@ -231,6 +233,10 @@ - (void)blendView:(UICollectionView *)view forPropName:(NSString *)name propValu
self.loadMoreViewId = prop;
} else if ([@"loadMore" isEqualToString:name]) {
self.loadMore = [prop boolValue];
} else if ([@"onScroll" isEqualToString:name]) {
self.onScrollFuncId = prop;
} else if ([@"onScrollEnd" isEqualToString:name]) {
self.onScrollEndFuncId = prop;
} else {
[super blendView:view forPropName:name propValue:prop];
}
@ -374,6 +380,38 @@ - (void)scrollViewDidScroll:(UIScrollView *)scrollView {
for (DoricDidScrollBlock block in self.didScrollBlocks) {
block(scrollView);
}
if (self.onScrollFuncId) {
[self callJSResponse:self.onScrollFuncId,
@{
@"x": @(self.view.contentOffset.x),
@"y": @(self.view.contentOffset.y),
},
nil];
}
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
if (self.onScrollEndFuncId) {
[self callJSResponse:self.onScrollEndFuncId,
@{
@"x": @(self.view.contentOffset.x),
@"y": @(self.view.contentOffset.y),
},
nil];
}
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
if (!decelerate) {
if (self.onScrollEndFuncId) {
[self callJSResponse:self.onScrollEndFuncId,
@{
@"x": @(self.view.contentOffset.x),
@"y": @(self.view.contentOffset.y),
},
nil];
}
}
}
- (NSMutableSet<DoricDidScrollBlock> *)didScrollBlocks {

View File

@ -67,6 +67,8 @@ @interface DoricListNode () <UITableViewDataSource, UITableViewDelegate>
@property(nonatomic, copy) NSString *loadMoreViewId;
@property(nonatomic, assign) BOOL loadMore;
@property(nonatomic, strong) NSMutableSet <DoricDidScrollBlock> *didScrollBlocks;
@property(nonatomic, copy) NSString *onScrollFuncId;
@property(nonatomic, copy) NSString *onScrollEndFuncId;
@end
@implementation DoricListNode
@ -116,6 +118,10 @@ - (void)blendView:(UITableView *)view forPropName:(NSString *)name propValue:(id
self.loadMoreViewId = prop;
} else if ([@"loadMore" isEqualToString:name]) {
self.loadMore = [prop boolValue];
} else if ([@"onScroll" isEqualToString:name]) {
self.onScrollFuncId = prop;
} else if ([@"onScrollEnd" isEqualToString:name]) {
self.onScrollEndFuncId = prop;
} else {
[super blendView:view forPropName:name propValue:prop];
}
@ -254,6 +260,38 @@ - (void)scrollViewDidScroll:(UIScrollView *)scrollView {
for (DoricDidScrollBlock block in self.didScrollBlocks) {
block(scrollView);
}
if (self.onScrollFuncId) {
[self callJSResponse:self.onScrollFuncId,
@{
@"x": @(self.view.contentOffset.x),
@"y": @(self.view.contentOffset.y),
},
nil];
}
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
if (self.onScrollEndFuncId) {
[self callJSResponse:self.onScrollEndFuncId,
@{
@"x": @(self.view.contentOffset.x),
@"y": @(self.view.contentOffset.y),
},
nil];
}
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
if (!decelerate) {
if (self.onScrollEndFuncId) {
[self callJSResponse:self.onScrollEndFuncId,
@{
@"x": @(self.view.contentOffset.x),
@"y": @(self.view.contentOffset.y),
},
nil];
}
}
}
- (NSMutableSet<DoricDidScrollBlock> *)didScrollBlocks {

View File

@ -1859,6 +1859,14 @@ var List = /** @class */ (function (_super) {
Property,
__metadata$5("design:type", ListItem)
], List.prototype, "loadMoreView", void 0);
__decorate$5([
Property,
__metadata$5("design:type", Function)
], List.prototype, "onScroll", void 0);
__decorate$5([
Property,
__metadata$5("design:type", Function)
], List.prototype, "onScrollEnd", void 0);
return List;
}(Superview));
function list(config) {
@ -2289,6 +2297,14 @@ var FlowLayout = /** @class */ (function (_super) {
Property,
__metadata$9("design:type", FlowLayoutItem)
], FlowLayout.prototype, "loadMoreView", void 0);
__decorate$9([
Property,
__metadata$9("design:type", Function)
], FlowLayout.prototype, "onScroll", void 0);
__decorate$9([
Property,
__metadata$9("design:type", Function)
], FlowLayout.prototype, "onScrollEnd", void 0);
return FlowLayout;
}(Superview));
function flowlayout(config) {

View File

@ -1381,6 +1381,14 @@ __decorate$5([
Property,
__metadata$5("design:type", ListItem)
], List.prototype, "loadMoreView", void 0);
__decorate$5([
Property,
__metadata$5("design:type", Function)
], List.prototype, "onScroll", void 0);
__decorate$5([
Property,
__metadata$5("design:type", Function)
], List.prototype, "onScrollEnd", void 0);
function list(config) {
const ret = new List;
for (let key in config) {
@ -1708,6 +1716,14 @@ __decorate$9([
Property,
__metadata$9("design:type", FlowLayoutItem)
], FlowLayout.prototype, "loadMoreView", void 0);
__decorate$9([
Property,
__metadata$9("design:type", Function)
], FlowLayout.prototype, "onScroll", void 0);
__decorate$9([
Property,
__metadata$9("design:type", Function)
], FlowLayout.prototype, "onScrollEnd", void 0);
function flowlayout(config) {
const ret = new FlowLayout;
for (let key in config) {

View File

@ -2840,6 +2840,14 @@ __decorate$5([
Property,
__metadata$5("design:type", ListItem)
], List.prototype, "loadMoreView", void 0);
__decorate$5([
Property,
__metadata$5("design:type", Function)
], List.prototype, "onScroll", void 0);
__decorate$5([
Property,
__metadata$5("design:type", Function)
], List.prototype, "onScrollEnd", void 0);
function list(config) {
const ret = new List;
for (let key in config) {
@ -3167,6 +3175,14 @@ __decorate$9([
Property,
__metadata$9("design:type", FlowLayoutItem)
], FlowLayout.prototype, "loadMoreView", void 0);
__decorate$9([
Property,
__metadata$9("design:type", Function)
], FlowLayout.prototype, "onScroll", void 0);
__decorate$9([
Property,
__metadata$9("design:type", Function)
], FlowLayout.prototype, "onScrollEnd", void 0);
function flowlayout(config) {
const ret = new FlowLayout;
for (let key in config) {

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

@ -549,6 +549,14 @@ declare module 'doric/lib/src/widget/list' {
onLoadMore?: () => void;
loadMore?: boolean;
loadMoreView?: ListItem;
onScroll?: (offset: {
x: number;
y: number;
}) => void;
onScrollEnd?: (offset: {
x: number;
y: number;
}) => void;
}
export class List extends Superview implements IList {
allSubviews(): IterableIterator<ListItem> | ListItem[];
@ -558,6 +566,14 @@ declare module 'doric/lib/src/widget/list' {
onLoadMore?: () => void;
loadMore?: boolean;
loadMoreView?: ListItem;
onScroll?: (offset: {
x: number;
y: number;
}) => void;
onScrollEnd?: (offset: {
x: number;
y: number;
}) => void;
reset(): void;
isDirty(): boolean;
toModel(): NativeViewModel;
@ -689,6 +705,14 @@ declare module 'doric/lib/src/widget/flowlayout' {
loadMore?: boolean;
onLoadMore?: () => void;
loadMoreView?: FlowLayoutItem;
onScroll?: (offset: {
x: number;
y: number;
}) => void;
onScrollEnd?: (offset: {
x: number;
y: number;
}) => void;
}
export class FlowLayout extends Superview implements IFlowLayout {
allSubviews(): IterableIterator<FlowLayoutItem> | FlowLayoutItem[];
@ -701,6 +725,14 @@ declare module 'doric/lib/src/widget/flowlayout' {
onLoadMore?: () => void;
loadMore?: boolean;
loadMoreView?: FlowLayoutItem;
onScroll?: (offset: {
x: number;
y: number;
}) => void;
onScrollEnd?: (offset: {
x: number;
y: number;
}) => void;
reset(): void;
isDirty(): boolean;
toModel(): NativeViewModel;

View File

@ -19,6 +19,14 @@ export interface IFlowLayout extends IView {
loadMore?: boolean;
onLoadMore?: () => void;
loadMoreView?: FlowLayoutItem;
onScroll?: (offset: {
x: number;
y: number;
}) => void;
onScrollEnd?: (offset: {
x: number;
y: number;
}) => void;
}
export declare class FlowLayout extends Superview implements IFlowLayout {
private cachedViews;
@ -33,6 +41,14 @@ export declare class FlowLayout extends Superview implements IFlowLayout {
onLoadMore?: () => void;
loadMore?: boolean;
loadMoreView?: FlowLayoutItem;
onScroll?: (offset: {
x: number;
y: number;
}) => void;
onScrollEnd?: (offset: {
x: number;
y: number;
}) => void;
reset(): void;
private getItem;
isDirty(): boolean;

View File

@ -116,6 +116,14 @@ __decorate([
Property,
__metadata("design:type", FlowLayoutItem)
], FlowLayout.prototype, "loadMoreView", void 0);
__decorate([
Property,
__metadata("design:type", Function)
], FlowLayout.prototype, "onScroll", void 0);
__decorate([
Property,
__metadata("design:type", Function)
], FlowLayout.prototype, "onScrollEnd", void 0);
export function flowlayout(config) {
const ret = new FlowLayout;
for (let key in config) {

View File

@ -16,6 +16,14 @@ export interface IList extends IView {
onLoadMore?: () => void;
loadMore?: boolean;
loadMoreView?: ListItem;
onScroll?: (offset: {
x: number;
y: number;
}) => void;
onScrollEnd?: (offset: {
x: number;
y: number;
}) => void;
}
export declare class List extends Superview implements IList {
private cachedViews;
@ -27,6 +35,14 @@ export declare class List extends Superview implements IList {
onLoadMore?: () => void;
loadMore?: boolean;
loadMoreView?: ListItem;
onScroll?: (offset: {
x: number;
y: number;
}) => void;
onScrollEnd?: (offset: {
x: number;
y: number;
}) => void;
reset(): void;
private getItem;
isDirty(): boolean;

View File

@ -106,6 +106,14 @@ __decorate([
Property,
__metadata("design:type", ListItem)
], List.prototype, "loadMoreView", void 0);
__decorate([
Property,
__metadata("design:type", Function)
], List.prototype, "onScroll", void 0);
__decorate([
Property,
__metadata("design:type", Function)
], List.prototype, "onScrollEnd", void 0);
export function list(config) {
const ret = new List;
for (let key in config) {

View File

@ -48,6 +48,10 @@ export interface IFlowLayout extends IView {
onLoadMore?: () => void
loadMoreView?: FlowLayoutItem
onScroll?: (offset: { x: number, y: number }) => void
onScrollEnd?: (offset: { x: number, y: number }) => void
}
export class FlowLayout extends Superview implements IFlowLayout {
@ -89,6 +93,12 @@ export class FlowLayout extends Superview implements IFlowLayout {
@Property
loadMoreView?: FlowLayoutItem
@Property
onScroll?: (offset: { x: number, y: number }) => void
@Property
onScrollEnd?: (offset: { x: number, y: number }) => void
reset() {
this.cachedViews.clear()
this.itemCount = 0

View File

@ -32,11 +32,20 @@ export class ListItem extends Stack implements IListItem {
export interface IList extends IView {
renderItem: (index: number) => ListItem
itemCount: number
batchCount?: number
onLoadMore?: () => void
loadMore?: boolean
loadMoreView?: ListItem
onScroll?: (offset: { x: number, y: number }) => void
onScrollEnd?: (offset: { x: number, y: number }) => void
}
export class List extends Superview implements IList {
@ -69,6 +78,12 @@ export class List extends Superview implements IList {
@Property
loadMoreView?: ListItem
@Property
onScroll?: (offset: { x: number, y: number }) => void
@Property
onScrollEnd?: (offset: { x: number, y: number }) => void
reset() {
this.cachedViews.clear()
this.itemCount = 0

View File

@ -2898,6 +2898,14 @@ __decorate$5([
Property,
__metadata$5("design:type", ListItem)
], List.prototype, "loadMoreView", void 0);
__decorate$5([
Property,
__metadata$5("design:type", Function)
], List.prototype, "onScroll", void 0);
__decorate$5([
Property,
__metadata$5("design:type", Function)
], List.prototype, "onScrollEnd", void 0);
function list(config) {
const ret = new List;
for (let key in config) {
@ -3225,6 +3233,14 @@ __decorate$9([
Property,
__metadata$9("design:type", FlowLayoutItem)
], FlowLayout.prototype, "loadMoreView", void 0);
__decorate$9([
Property,
__metadata$9("design:type", Function)
], FlowLayout.prototype, "onScroll", void 0);
__decorate$9([
Property,
__metadata$9("design:type", Function)
], FlowLayout.prototype, "onScrollEnd", void 0);
function flowlayout(config) {
const ret = new FlowLayout;
for (let key in config) {

File diff suppressed because one or more lines are too long