feat:add RefreshableDemo for Android
This commit is contained in:
parent
c766e57c83
commit
362ec833c9
@ -29,6 +29,8 @@ import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import org.w3c.dom.Text;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -54,7 +56,9 @@ public class MainActivity extends AppCompatActivity {
|
||||
});
|
||||
swipeLayout.setBackgroundColor(Color.YELLOW);
|
||||
swipeLayout.getRefreshView().setBackgroundColor(Color.RED);
|
||||
swipeLayout.setPullDownHeight(300);
|
||||
TextView textView = new TextView(this);
|
||||
textView.setText("This is header");
|
||||
swipeLayout.getRefreshView().setContent(textView);
|
||||
RecyclerView recyclerView = findViewById(R.id.root);
|
||||
recyclerView.setBackgroundColor(Color.WHITE);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(this));
|
||||
|
@ -25,6 +25,7 @@ import pub.doric.plugin.NavigatorPlugin;
|
||||
import pub.doric.plugin.NetworkPlugin;
|
||||
import pub.doric.plugin.ShaderPlugin;
|
||||
import pub.doric.plugin.StoragePlugin;
|
||||
import pub.doric.pullable.RefreshableNode;
|
||||
import pub.doric.shader.HLayoutNode;
|
||||
import pub.doric.shader.ImageNode;
|
||||
import pub.doric.shader.ScrollerNode;
|
||||
@ -96,6 +97,7 @@ public class DoricRegistry {
|
||||
this.registerViewNode(ScrollerNode.class);
|
||||
this.registerViewNode(SliderNode.class);
|
||||
this.registerViewNode(SlideItemNode.class);
|
||||
this.registerViewNode(RefreshableNode.class);
|
||||
initRegistry(this);
|
||||
}
|
||||
|
||||
|
@ -287,7 +287,7 @@ public class DoricSwipeLayout extends ViewGroup implements NestedScrollingParent
|
||||
|
||||
private void createProgressView() {
|
||||
mRefreshView = new DoricRefreshView(getContext());
|
||||
ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, 0);
|
||||
ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
|
||||
addView(mRefreshView, layoutParams);
|
||||
}
|
||||
|
||||
@ -441,8 +441,16 @@ public class DoricSwipeLayout extends ViewGroup implements NestedScrollingParent
|
||||
getMeasuredWidth() - getPaddingLeft() - getPaddingRight(),
|
||||
MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(
|
||||
getMeasuredHeight() - getPaddingTop() - getPaddingBottom(), MeasureSpec.EXACTLY));
|
||||
mRefreshView.measure(MeasureSpec.makeMeasureSpec(getMeasuredWidth() - getPaddingLeft() - getPaddingRight(), MeasureSpec.EXACTLY),
|
||||
MeasureSpec.makeMeasureSpec(mPullDownHeight, MeasureSpec.EXACTLY));
|
||||
mRefreshView.measure(
|
||||
MeasureSpec.makeMeasureSpec(
|
||||
getMeasuredWidth() - getPaddingLeft() - getPaddingRight(),
|
||||
MeasureSpec.EXACTLY),
|
||||
MeasureSpec.makeMeasureSpec(
|
||||
(getMeasuredHeight() - getPaddingTop() - getPaddingBottom()) / 3,
|
||||
MeasureSpec.UNSPECIFIED));
|
||||
if (mPullDownHeight != mRefreshView.getMeasuredHeight()) {
|
||||
setPullDownHeight(mRefreshView.getMeasuredHeight());
|
||||
}
|
||||
mCircleViewIndex = -1;
|
||||
// Get the index of the circleview.
|
||||
for (int index = 0; index < getChildCount(); index++) {
|
||||
|
@ -0,0 +1,165 @@
|
||||
package pub.doric.pullable;
|
||||
|
||||
import com.github.pengfeizhou.jscore.JSObject;
|
||||
import com.github.pengfeizhou.jscore.JSValue;
|
||||
import com.github.pengfeizhou.jscore.JavaValue;
|
||||
|
||||
import pub.doric.DoricContext;
|
||||
import pub.doric.extension.bridge.DoricMethod;
|
||||
import pub.doric.extension.bridge.DoricPlugin;
|
||||
import pub.doric.extension.bridge.DoricPromise;
|
||||
import pub.doric.shader.SuperNode;
|
||||
import pub.doric.shader.ViewNode;
|
||||
|
||||
/**
|
||||
* @Description: pub.doric.pullable
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-11-26
|
||||
*/
|
||||
@DoricPlugin(name = "Refreshable")
|
||||
public class RefreshableNode extends SuperNode<DoricSwipeLayout> {
|
||||
|
||||
private String mContentViewId;
|
||||
private ViewNode mContentNode;
|
||||
|
||||
private String mHeaderViewId;
|
||||
private ViewNode mHeaderNode;
|
||||
|
||||
public RefreshableNode(DoricContext doricContext) {
|
||||
super(doricContext);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected DoricSwipeLayout build() {
|
||||
return new DoricSwipeLayout(getContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void blend(DoricSwipeLayout view, String name, JSValue prop) {
|
||||
if ("content".equals(name)) {
|
||||
mContentViewId = prop.asString().value();
|
||||
} else if ("header".equals(name)) {
|
||||
mHeaderViewId = prop.asString().value();
|
||||
} else {
|
||||
super.blend(view, name, prop);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void blend(JSObject jsObject) {
|
||||
super.blend(jsObject);
|
||||
blendContentNode();
|
||||
blendHeadNode();
|
||||
}
|
||||
|
||||
|
||||
private void blendContentNode() {
|
||||
JSObject contentModel = getSubModel(mContentViewId);
|
||||
if (contentModel == null) {
|
||||
return;
|
||||
}
|
||||
String viewId = contentModel.getProperty("id").asString().value();
|
||||
String type = contentModel.getProperty("type").asString().value();
|
||||
JSObject props = contentModel.getProperty("props").asObject();
|
||||
if (mContentNode != null) {
|
||||
if (mContentNode.getId().equals(viewId)) {
|
||||
//skip
|
||||
} else {
|
||||
if (mReusable && type.equals(mContentNode.getType())) {
|
||||
mContentNode.setId(viewId);
|
||||
mContentNode.blend(props);
|
||||
} else {
|
||||
mView.removeAllViews();
|
||||
mContentNode = ViewNode.create(getDoricContext(), type);
|
||||
mContentNode.setId(viewId);
|
||||
mContentNode.init(this);
|
||||
mContentNode.blend(props);
|
||||
mView.addView(mContentNode.getDoricLayer());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mContentNode = ViewNode.create(getDoricContext(), type);
|
||||
mContentNode.setId(viewId);
|
||||
mContentNode.init(this);
|
||||
mContentNode.blend(props);
|
||||
mView.addView(mContentNode.getDoricLayer());
|
||||
}
|
||||
}
|
||||
|
||||
private void blendHeadNode() {
|
||||
JSObject headerModel = getSubModel(mHeaderViewId);
|
||||
if (headerModel == null) {
|
||||
return;
|
||||
}
|
||||
String viewId = headerModel.getProperty("id").asString().value();
|
||||
String type = headerModel.getProperty("type").asString().value();
|
||||
JSObject props = headerModel.getProperty("props").asObject();
|
||||
if (mHeaderNode != null) {
|
||||
if (mHeaderNode.getId().equals(viewId)) {
|
||||
//skip
|
||||
} else {
|
||||
if (mReusable && type.equals(mHeaderNode.getType())) {
|
||||
mHeaderNode.setId(viewId);
|
||||
mHeaderNode.blend(props);
|
||||
} else {
|
||||
mHeaderNode = ViewNode.create(getDoricContext(), type);
|
||||
mHeaderNode.setId(viewId);
|
||||
mHeaderNode.init(this);
|
||||
mHeaderNode.blend(props);
|
||||
mView.getRefreshView().setContent(mHeaderNode.getDoricLayer());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mHeaderNode = ViewNode.create(getDoricContext(), type);
|
||||
mHeaderNode.setId(viewId);
|
||||
mHeaderNode.init(this);
|
||||
mHeaderNode.blend(props);
|
||||
mView.getRefreshView().setContent(mHeaderNode.getDoricLayer());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewNode getSubNodeById(String id) {
|
||||
if (id.equals(mContentViewId)) {
|
||||
return mContentNode;
|
||||
}
|
||||
if (id.equals(mHeaderViewId)) {
|
||||
return mHeaderNode;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void blendSubNode(JSObject subProperties) {
|
||||
String viewId = subProperties.getProperty("id").asString().value();
|
||||
ViewNode node = getSubNodeById(viewId);
|
||||
if (node != null) {
|
||||
node.blend(subProperties.getProperty("props").asObject());
|
||||
}
|
||||
}
|
||||
|
||||
@DoricMethod
|
||||
public void setRefreshable(JSValue jsValue, DoricPromise doricPromise) {
|
||||
boolean refreshable = jsValue.asBoolean().value();
|
||||
this.mView.setEnabled(refreshable);
|
||||
doricPromise.resolve();
|
||||
}
|
||||
|
||||
@DoricMethod
|
||||
public void setRefreshing(JSValue jsValue, DoricPromise doricPromise) {
|
||||
boolean refreshing = jsValue.asBoolean().value();
|
||||
this.mView.setRefreshing(refreshing);
|
||||
doricPromise.resolve();
|
||||
}
|
||||
|
||||
@DoricMethod
|
||||
public void isRefreshable(DoricPromise doricPromise) {
|
||||
doricPromise.resolve(new JavaValue(this.mView.isEnabled()));
|
||||
}
|
||||
|
||||
@DoricMethod
|
||||
public void isRefreshing(DoricPromise doricPromise) {
|
||||
doricPromise.resolve(new JavaValue(this.mView.isRefreshing()));
|
||||
}
|
||||
}
|
@ -12,4 +12,5 @@ export default [
|
||||
'src/StorageDemo',
|
||||
'src/NavigatorDemo',
|
||||
'src/NavbarDemo',
|
||||
'src/RefreshableDemo',
|
||||
]
|
72
demo/src/RefreshableDemo.ts
Normal file
72
demo/src/RefreshableDemo.ts
Normal file
@ -0,0 +1,72 @@
|
||||
import { refreshable, Group, Panel, navbar, text, gravity, Color, Stack, LayoutSpec, list, NativeCall, listItem, log, vlayout, Gravity, hlayout, Text, scroller, layoutConfig, image, IView, IVLayout, ScaleType, modal, IText, network, navigator } from "doric";
|
||||
import { title, label, colors } from "./utils";
|
||||
|
||||
@Entry
|
||||
class RefreshableDemo extends Panel {
|
||||
build(rootView: Group): void {
|
||||
let refreshView = refreshable({
|
||||
layoutConfig: layoutConfig().atmost(),
|
||||
header: text({
|
||||
text: "This is Header",
|
||||
width: 100,
|
||||
height: 100,
|
||||
layoutConfig: layoutConfig().exactly(),
|
||||
}),
|
||||
content: scroller(vlayout([
|
||||
title("Refreshable Demo"),
|
||||
label('start Refresh').apply({
|
||||
width: 300,
|
||||
height: 50,
|
||||
bgColor: colors[0],
|
||||
textSize: 30,
|
||||
textColor: Color.WHITE,
|
||||
layoutConfig: layoutConfig().exactly(),
|
||||
onClick: () => {
|
||||
refreshView.setRefreshing(context, true)
|
||||
}
|
||||
} as IText),
|
||||
label('stop Refresh').apply({
|
||||
width: 300,
|
||||
height: 50,
|
||||
bgColor: colors[0],
|
||||
textSize: 30,
|
||||
textColor: Color.WHITE,
|
||||
layoutConfig: layoutConfig().exactly(),
|
||||
onClick: () => {
|
||||
refreshView.setRefreshing(context, false)
|
||||
}
|
||||
} as IText),
|
||||
|
||||
label('Enable Refresh').apply({
|
||||
width: 300,
|
||||
height: 50,
|
||||
bgColor: colors[0],
|
||||
textSize: 30,
|
||||
textColor: Color.WHITE,
|
||||
layoutConfig: layoutConfig().exactly(),
|
||||
onClick: () => {
|
||||
refreshView.setRefreshable(context, true)
|
||||
}
|
||||
} as IText),
|
||||
|
||||
label('Disable Refresh').apply({
|
||||
width: 300,
|
||||
height: 50,
|
||||
bgColor: colors[0],
|
||||
textSize: 30,
|
||||
textColor: Color.WHITE,
|
||||
layoutConfig: layoutConfig().exactly(),
|
||||
onClick: () => {
|
||||
refreshView.setRefreshable(context, false)
|
||||
}
|
||||
} as IText),
|
||||
]).apply({
|
||||
layoutConfig: layoutConfig().atmost().h(LayoutSpec.WRAP_CONTENT),
|
||||
gravity: gravity().center(),
|
||||
space: 10,
|
||||
} as IVLayout)).apply({
|
||||
layoutConfig: layoutConfig().atmost(),
|
||||
})
|
||||
}).in(rootView)
|
||||
}
|
||||
}
|
@ -21,6 +21,7 @@ export * from "./src/ui/scroller"
|
||||
export * from "./src/ui/widgets"
|
||||
export * from "./src/ui/panel"
|
||||
export * from "./src/ui/declarative"
|
||||
export * from "./src/ui/refreshable"
|
||||
export * from "./src/util/color"
|
||||
export * from './src/util/log'
|
||||
export * from './src/util/types'
|
||||
|
60
js-framework/src/ui/refreshable.ts
Normal file
60
js-framework/src/ui/refreshable.ts
Normal file
@ -0,0 +1,60 @@
|
||||
import { View, Property, Superview, IView } from "./view";
|
||||
import { List } from "./list";
|
||||
import { Scroller } from "./scroller";
|
||||
import { BridgeContext } from "../runtime/global";
|
||||
import { layoutConfig } from "./declarative";
|
||||
|
||||
export interface IRefreshable extends IView {
|
||||
content: List | Scroller
|
||||
header?: View
|
||||
onRefresh?: () => void
|
||||
}
|
||||
|
||||
export class Refreshable extends Superview implements IRefreshable {
|
||||
|
||||
content!: List | Scroller
|
||||
|
||||
header?: View
|
||||
|
||||
@Property
|
||||
onRefresh?: () => void
|
||||
|
||||
allSubviews() {
|
||||
const ret: View[] = [this.content]
|
||||
if (this.header) {
|
||||
ret.push(this.header)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
setRefreshable(context: BridgeContext, refreshable: boolean) {
|
||||
return this.nativeChannel(context, 'setRefreshable')(refreshable)
|
||||
}
|
||||
|
||||
setRefreshing(context: BridgeContext, refreshing: boolean) {
|
||||
return this.nativeChannel(context, 'setRefreshing')(refreshing)
|
||||
}
|
||||
|
||||
isRefreshable(context: BridgeContext) {
|
||||
return this.nativeChannel(context, 'isRefreshable')() as Promise<boolean>
|
||||
}
|
||||
|
||||
isRefreshing(context: BridgeContext) {
|
||||
return this.nativeChannel(context, 'isRefreshing')() as Promise<boolean>
|
||||
}
|
||||
|
||||
toModel() {
|
||||
this.dirtyProps.content = this.content.viewId
|
||||
this.dirtyProps.header = (this.header || {}).viewId
|
||||
return super.toModel()
|
||||
}
|
||||
}
|
||||
|
||||
export function refreshable(config: IRefreshable) {
|
||||
const ret = new Refreshable
|
||||
ret.layoutConfig = layoutConfig().wrap()
|
||||
for (let key in config) {
|
||||
Reflect.set(ret, key, Reflect.get(config, key, config), ret)
|
||||
}
|
||||
return ret
|
||||
}
|
@ -266,7 +266,7 @@ export abstract class View implements Modeling, IView {
|
||||
|
||||
nativeChannel(context: any, name: string) {
|
||||
let thisView: View | undefined = this
|
||||
return function (...args: any) {
|
||||
return function (args: any = undefined) {
|
||||
const func = context.shader.command
|
||||
const viewIds = []
|
||||
while (thisView != undefined) {
|
||||
|
Reference in New Issue
Block a user