From 713c043f718394016d1ac642b860859c5d2ae3d0 Mon Sep 17 00:00:00 2001 From: "pengfei.zhou" Date: Mon, 25 Nov 2019 13:50:26 +0800 Subject: [PATCH] feat:add Navbar plugin for Android --- Android/doric/src/main/AndroidManifest.xml | 4 +- .../src/main/java/pub/doric/DoricContext.java | 11 ++ .../java/pub/doric/DoricPanelFragment.java | 8 +- .../main/java/pub/doric/DoricRegistry.java | 3 + .../pub/doric/navbar/BaseDoricNavBar.java | 105 ++++++++++++++++ .../java/pub/doric/navbar/IDoricNavBar.java | 31 +++++ .../java/pub/doric/plugin/NavBarPlugin.java | 115 ++++++++++++++++++ .../res/drawable-xhdpi/doric_icon_back.png | Bin 0 -> 1098 bytes .../main/res/layout/doric_framgent_panel.xml | 19 ++- .../src/main/res/layout/doric_navigator.xml | 63 ++++++++++ demo/index.ts | 1 + demo/src/NavbarDemo.ts | 73 +++++++++++ demo/src/NavigatorDemo.ts | 4 +- js-framework/src/util/nativeModules.ts | 20 ++- 14 files changed, 448 insertions(+), 9 deletions(-) create mode 100644 Android/doric/src/main/java/pub/doric/navbar/BaseDoricNavBar.java create mode 100644 Android/doric/src/main/java/pub/doric/navbar/IDoricNavBar.java create mode 100644 Android/doric/src/main/java/pub/doric/plugin/NavBarPlugin.java create mode 100644 Android/doric/src/main/res/drawable-xhdpi/doric_icon_back.png create mode 100644 Android/doric/src/main/res/layout/doric_navigator.xml create mode 100644 demo/src/NavbarDemo.ts diff --git a/Android/doric/src/main/AndroidManifest.xml b/Android/doric/src/main/AndroidManifest.xml index ec029524..44741555 100644 --- a/Android/doric/src/main/AndroidManifest.xml +++ b/Android/doric/src/main/AndroidManifest.xml @@ -4,7 +4,9 @@ - + diff --git a/Android/doric/src/main/java/pub/doric/DoricContext.java b/Android/doric/src/main/java/pub/doric/DoricContext.java index 63fd5856..fd1971e0 100644 --- a/Android/doric/src/main/java/pub/doric/DoricContext.java +++ b/Android/doric/src/main/java/pub/doric/DoricContext.java @@ -26,6 +26,7 @@ import java.util.HashMap; import java.util.Map; import pub.doric.async.AsyncResult; +import pub.doric.navbar.IDoricNavBar; import pub.doric.navigator.IDoricNavigator; import pub.doric.plugin.DoricJavaPlugin; import pub.doric.shader.RootNode; @@ -159,4 +160,14 @@ public class DoricContext { public IDoricNavigator getDoricNavigator() { return this.doricNavigator; } + + private IDoricNavBar doricNavBar; + + public void setDoricNavBar(IDoricNavBar navBar) { + this.doricNavBar = navBar; + } + + public IDoricNavBar getDoricNavBar() { + return this.doricNavBar; + } } diff --git a/Android/doric/src/main/java/pub/doric/DoricPanelFragment.java b/Android/doric/src/main/java/pub/doric/DoricPanelFragment.java index c25b033f..12653e8d 100644 --- a/Android/doric/src/main/java/pub/doric/DoricPanelFragment.java +++ b/Android/doric/src/main/java/pub/doric/DoricPanelFragment.java @@ -26,6 +26,7 @@ import androidx.fragment.app.Fragment; import pub.doric.async.AsyncResult; import pub.doric.loader.DoricJSLoaderManager; +import pub.doric.navbar.BaseDoricNavBar; import pub.doric.navigator.IDoricNavigator; import pub.doric.utils.DoricLog; @@ -36,6 +37,7 @@ import pub.doric.utils.DoricLog; */ public class DoricPanelFragment extends Fragment { private DoricPanel doricPanel; + private BaseDoricNavBar navBar; public static DoricPanelFragment newInstance(String scheme, String alias) { Bundle args = new Bundle(); @@ -48,14 +50,15 @@ public class DoricPanelFragment extends Fragment { @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - doricPanel = (DoricPanel) inflater.inflate(R.layout.doric_framgent_panel, container, false); - return doricPanel; + return inflater.inflate(R.layout.doric_framgent_panel, container, false); } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); + doricPanel = view.findViewById(R.id.doric_panel); + navBar = view.findViewById(R.id.doric_nav_bar); Bundle argument = getArguments(); if (argument == null) { DoricLog.e("DoricPanelFragment argument is null"); @@ -72,6 +75,7 @@ public class DoricPanelFragment extends Fragment { if (fragment instanceof IDoricNavigator) { context.setDoricNavigator((IDoricNavigator) fragment); } + context.setDoricNavBar(navBar); } @Override diff --git a/Android/doric/src/main/java/pub/doric/DoricRegistry.java b/Android/doric/src/main/java/pub/doric/DoricRegistry.java index 2059d18b..12722dc4 100644 --- a/Android/doric/src/main/java/pub/doric/DoricRegistry.java +++ b/Android/doric/src/main/java/pub/doric/DoricRegistry.java @@ -20,6 +20,7 @@ import android.text.TextUtils; import pub.doric.loader.DoricAssetJSLoader; import pub.doric.loader.DoricHttpJSLoader; import pub.doric.loader.IDoricJSLoader; +import pub.doric.plugin.NavBarPlugin; import pub.doric.plugin.NavigatorPlugin; import pub.doric.plugin.NetworkPlugin; import pub.doric.plugin.ShaderPlugin; @@ -82,6 +83,8 @@ public class DoricRegistry { this.registerNativePlugin(NetworkPlugin.class); this.registerNativePlugin(StoragePlugin.class); this.registerNativePlugin(NavigatorPlugin.class); + this.registerNativePlugin(NavBarPlugin.class); + this.registerViewNode(RootNode.class); this.registerViewNode(TextNode.class); this.registerViewNode(ImageNode.class); diff --git a/Android/doric/src/main/java/pub/doric/navbar/BaseDoricNavBar.java b/Android/doric/src/main/java/pub/doric/navbar/BaseDoricNavBar.java new file mode 100644 index 00000000..c0a5ed8a --- /dev/null +++ b/Android/doric/src/main/java/pub/doric/navbar/BaseDoricNavBar.java @@ -0,0 +1,105 @@ +package pub.doric.navbar; + +import android.app.Activity; +import android.content.Context; +import android.text.Layout; +import android.text.StaticLayout; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.TextView; + +import androidx.annotation.AttrRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import pub.doric.R; + +/** + * @Description: pub.doric.navbar + * @Author: pengfei.zhou + * @CreateDate: 2019-11-25 + */ +public class BaseDoricNavBar extends FrameLayout implements IDoricNavBar { + private ViewGroup mTitleContainer; + private ViewGroup mRightContainer; + private ViewGroup mLeftContainer; + private TextView mTvTitle; + + public BaseDoricNavBar(@NonNull Context context) { + this(context, null); + } + + public BaseDoricNavBar(@NonNull Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public BaseDoricNavBar(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { + super(context, attrs, defStyleAttr); + setup(); + } + + private void setup() { + LayoutInflater.from(getContext()).inflate(R.layout.doric_navigator, this); + mTitleContainer = findViewById(R.id.container_title); + mLeftContainer = findViewById(R.id.container_left); + mRightContainer = findViewById(R.id.container_right); + mTvTitle = findViewById(R.id.tv_title); + findViewById(R.id.tv_back).setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (getContext() instanceof Activity) { + ((Activity) getContext()).finish(); + } + } + }); + } + + @Override + public boolean isHidden() { + return getVisibility() != VISIBLE; + } + + @Override + public void setHidden(boolean b) { + setVisibility(b ? GONE : VISIBLE); + } + + @Override + public void setTitle(String title) { + mTvTitle.setText(title); + } + + private void updateTitleMargins() { + try { + int width = mRightContainer.getRight() - mLeftContainer.getLeft(); + int leftWidth = mLeftContainer.getWidth(); + int rightWidth = mRightContainer.getWidth(); + int margin = Math.max(leftWidth, rightWidth); + if (leftWidth + rightWidth > width) { + mTitleContainer.setVisibility(GONE); + } else { + mTitleContainer.setVisibility(VISIBLE); + StaticLayout staticLayout = new StaticLayout(mTvTitle.getText(), + mTvTitle.getPaint(), Integer.MAX_VALUE, Layout.Alignment.ALIGN_NORMAL, + 1.0f, 0.0f, false); + float textWidth = (staticLayout.getLineCount() > 0 ? staticLayout.getLineWidth(0) : 0.0f); + if (width - 2 * margin >= textWidth) { + mTitleContainer.setPadding(margin, 0, margin, 0); + } else { + mTitleContainer.setPadding(leftWidth, 0, rightWidth, 0); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + updateTitleMargins(); + } +} \ No newline at end of file diff --git a/Android/doric/src/main/java/pub/doric/navbar/IDoricNavBar.java b/Android/doric/src/main/java/pub/doric/navbar/IDoricNavBar.java new file mode 100644 index 00000000..ff35769d --- /dev/null +++ b/Android/doric/src/main/java/pub/doric/navbar/IDoricNavBar.java @@ -0,0 +1,31 @@ +/* + * Copyright [2019] [Doric.Pub] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package pub.doric.navbar; + +/** + * @Description: pub.doric.navbar + * @Author: pengfei.zhou + * @CreateDate: 2019-11-25 + */ +public interface IDoricNavBar { + boolean isHidden(); + + void setHidden(boolean hidden); + + void setTitle(String title); + + void setBackgroundColor(int color); +} diff --git a/Android/doric/src/main/java/pub/doric/plugin/NavBarPlugin.java b/Android/doric/src/main/java/pub/doric/plugin/NavBarPlugin.java new file mode 100644 index 00000000..f9e8ebf9 --- /dev/null +++ b/Android/doric/src/main/java/pub/doric/plugin/NavBarPlugin.java @@ -0,0 +1,115 @@ +/* + * Copyright [2019] [Doric.Pub] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package pub.doric.plugin; + +import android.view.View; +import android.view.ViewGroup; + +import com.github.pengfeizhou.jscore.ArchiveException; +import com.github.pengfeizhou.jscore.JSDecoder; +import com.github.pengfeizhou.jscore.JSObject; +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.navbar.IDoricNavBar; +import pub.doric.utils.DoricUtils; +import pub.doric.utils.ThreadMode; + +/** + * @Description: pub.doric.plugin + * @Author: pengfei.zhou + * @CreateDate: 2019-11-25 + */ +@DoricPlugin(name = "navbar") +public class NavBarPlugin extends DoricJavaPlugin { + public NavBarPlugin(DoricContext doricContext) { + super(doricContext); + } + + @DoricMethod(thread = ThreadMode.UI) + public void isHidden(DoricPromise promise) { + IDoricNavBar navBar = getDoricContext().getDoricNavBar(); + if (navBar == null) { + promise.reject(new JavaValue("Not implement NavBar")); + } else { + promise.resolve(new JavaValue(navBar.isHidden())); + } + } + + @DoricMethod(thread = ThreadMode.UI) + public void setHidden(JSDecoder jsDecoder, DoricPromise promise) { + IDoricNavBar navBar = getDoricContext().getDoricNavBar(); + if (navBar == null) { + promise.reject(new JavaValue("Not implement NavBar")); + } else { + try { + JSObject jsObject = jsDecoder.decode().asObject(); + boolean hidden = jsObject.getProperty("hidden").asBoolean().value(); + navBar.setHidden(hidden); + View v = getDoricContext().getRootNode().getDoricLayer(); + ViewGroup.LayoutParams params = v.getLayoutParams(); + if (params instanceof ViewGroup.MarginLayoutParams) { + ((ViewGroup.MarginLayoutParams) params).topMargin = + hidden ? 0 + : ((View) navBar).getMeasuredHeight(); + } + promise.resolve(); + } catch (ArchiveException e) { + e.printStackTrace(); + promise.reject(new JavaValue(e.getLocalizedMessage())); + } + } + } + + @DoricMethod(thread = ThreadMode.UI) + public void setTitle(JSDecoder jsDecoder, DoricPromise promise) { + IDoricNavBar navBar = getDoricContext().getDoricNavBar(); + if (navBar == null) { + promise.reject(new JavaValue("Not implement NavBar")); + } else { + try { + JSObject jsObject = jsDecoder.decode().asObject(); + String title = jsObject.getProperty("title").asString().value(); + navBar.setTitle(title); + promise.resolve(); + } catch (ArchiveException e) { + e.printStackTrace(); + promise.reject(new JavaValue(e.getLocalizedMessage())); + } + } + } + + @DoricMethod(thread = ThreadMode.UI) + public void setBgColor(JSDecoder jsDecoder, DoricPromise promise) { + IDoricNavBar navBar = getDoricContext().getDoricNavBar(); + if (navBar == null) { + promise.reject(new JavaValue("Not implement NavBar")); + } else { + try { + JSObject jsObject = jsDecoder.decode().asObject(); + int color = jsObject.getProperty("color").asNumber().toInt(); + navBar.setBackgroundColor(color); + promise.resolve(); + } catch (ArchiveException e) { + e.printStackTrace(); + promise.reject(new JavaValue(e.getLocalizedMessage())); + } + } + } +} diff --git a/Android/doric/src/main/res/drawable-xhdpi/doric_icon_back.png b/Android/doric/src/main/res/drawable-xhdpi/doric_icon_back.png new file mode 100644 index 0000000000000000000000000000000000000000..6679febdbe96c991775bbcc24409019685024c18 GIT binary patch literal 1098 zcmV-Q1hxB#P)Px(1W80eRA>e5SNa^nKxz<0b0-x-SOi!R6g^=HC0h z@0|1QJ?D+jSG}qhs7wnqH8u4&Ha5<&MWfMPyDa>6Cpwu2&?n2~@*S)Z;5vT4e{N}M zDPd>L-wW88Xm<|4p9lE6m@l7g+mLb*yO>PRL)Z)f{54FFfQx}Z;Ed@-l!0;~(A?|;m9a&sld@l7?`ys0ntc*{k zQbAb$9_E}-=6!{H2;ko+dds3V4|H^NY?+;%eE<&(D5$cbP^f2NVPQ(q+Y+@9h{xl# zD=RAx0e;i|j*$6`b^w-tZwu`oCb>?axw$z~EEf4vb}7$G*VNP`=jZ1?DSAhutJ`QI zk%+FXt&IUumqZ1t&!Ba>4W7?%%>ykhE!$RCSD#_cb_pK+X;{7o;J+w(S43AlfNe5f zC=^}+(I)V)`b2$w{eE5GX#vL`faQ0>^4!Z?xuCdSVz=qTZu4E}T<<#a04%>7mVXUY ztr8h5KibgH(5o9fpJ|%_cAGueCdbjXE8s`k+S-n$)9Jj_>+0Jg0L$;iR`~*;ViFiE zKb%Y^k4;Wa7NlNh-|{z zBQyEHpviH*a5(%C9!O!lL7Lt>2z@b^%keDuFPCWoNRMYCk;q$+=m*k`LI`pW)9-+R>@VBsZM+Yj??gs882J8qU$0?%Fpy=Tyaqw;KFdg{)ZMr20Rs?I37p1E zpViZtsl;)wPGj2yNCXz&g?C^KP0fc!>+0$TGMP-yAgt@|hyX!VbUIA}EE92{b)wBs z7FQR`OO}~J=X%$%2Mk0NT~d++%SM)u@Wg~cYW?2Ma+77JqIX4f%>xFSivFxZ5-cNG zPQnwT2C4OXE6Y!op^Dy-X!#&B^E8%|EGt1`M2_cni#ER1~l{Kd;|_e$$^AAm+;Fb!{FnhyZAr0l_?nVwpiZ Qe*gdg07*qoM6N<$f?O;2W&i*H literal 0 HcmV?d00001 diff --git a/Android/doric/src/main/res/layout/doric_framgent_panel.xml b/Android/doric/src/main/res/layout/doric_framgent_panel.xml index eab7ed13..237f04c3 100644 --- a/Android/doric/src/main/res/layout/doric_framgent_panel.xml +++ b/Android/doric/src/main/res/layout/doric_framgent_panel.xml @@ -1,5 +1,18 @@ - \ No newline at end of file + android:layout_height="match_parent"> + + + + + + \ No newline at end of file diff --git a/Android/doric/src/main/res/layout/doric_navigator.xml b/Android/doric/src/main/res/layout/doric_navigator.xml new file mode 100644 index 00000000..fbc384af --- /dev/null +++ b/Android/doric/src/main/res/layout/doric_navigator.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/demo/index.ts b/demo/index.ts index 3b1dace6..6d413654 100644 --- a/demo/index.ts +++ b/demo/index.ts @@ -11,4 +11,5 @@ export default [ 'src/NetworkDemo', 'src/StorageDemo', 'src/NavigatorDemo', + 'src/NavbarDemo', ] \ No newline at end of file diff --git a/demo/src/NavbarDemo.ts b/demo/src/NavbarDemo.ts new file mode 100644 index 00000000..5f794790 --- /dev/null +++ b/demo/src/NavbarDemo.ts @@ -0,0 +1,73 @@ +import { 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 } from "doric"; +import { title, label, colors } from "./utils"; + +@Entry +class NavbarDemo extends Panel { + build(rootView: Group): void { + scroller(vlayout([ + title("Navbar Demo"), + label('isHidden').apply({ + width: 200, + height: 50, + bgColor: colors[0], + textSize: 30, + textColor: Color.WHITE, + layoutConfig: layoutConfig().exactly(), + onClick: () => { + navbar(context).isHidden().then(e => modal(context).alert(`Navbar isHidden:${e}`)).catch(e => { + modal(context).alert(e) + }) + } + } as IText), + label('setHidden').apply({ + width: 200, + height: 50, + bgColor: colors[0], + textSize: 30, + textColor: Color.WHITE, + layoutConfig: layoutConfig().exactly(), + onClick: () => { + navbar(context).isHidden() + .then(e => navbar(context).setHidden(!e)) + .catch(e => { + modal(context).alert(e) + }) + } + } as IText), + label('setTitle').apply({ + width: 200, + height: 50, + bgColor: colors[0], + textSize: 30, + textColor: Color.WHITE, + layoutConfig: layoutConfig().exactly(), + onClick: () => { + navbar(context).setTitle('Setted Title') + .catch(e => { + modal(context).alert(e) + }) + } + } as IText), + label('setBgColor').apply({ + width: 200, + height: 50, + bgColor: colors[0], + textSize: 30, + textColor: Color.WHITE, + layoutConfig: layoutConfig().exactly(), + onClick: () => { + navbar(context).setBgColor(Color.YELLOW) + .catch(e => { + modal(context).alert(e) + }) + } + } as IText), + ]).apply({ + layoutConfig: layoutConfig().atmost().h(LayoutSpec.WRAP_CONTENT), + gravity: gravity().center(), + space: 10, + } as IVLayout)).apply({ + layoutConfig: layoutConfig().atmost(), + }).in(rootView) + } +} \ No newline at end of file diff --git a/demo/src/NavigatorDemo.ts b/demo/src/NavigatorDemo.ts index 62d09ccb..dfc1bd60 100644 --- a/demo/src/NavigatorDemo.ts +++ b/demo/src/NavigatorDemo.ts @@ -13,7 +13,9 @@ class NaivgatorDemo extends Panel { textAlignment: gravity().center(), height: 50, }), - ...['Counter', 'EffectsDemo', 'ImageDemo', 'LayoutDemo', + ...[ + 'NavbarDemo', + 'Counter', 'EffectsDemo', 'ImageDemo', 'LayoutDemo', 'ListDemo', 'ModalDemo', 'NavigatorDemo', 'NetworkDemo', 'ScrollerDemo', 'SliderDemo', 'Snake', 'StorageDemo'].map(e => label(e).apply({ diff --git a/js-framework/src/util/nativeModules.ts b/js-framework/src/util/nativeModules.ts index 8e9a5f6e..bd037cc5 100644 --- a/js-framework/src/util/nativeModules.ts +++ b/js-framework/src/util/nativeModules.ts @@ -15,6 +15,8 @@ */ import { BridgeContext } from "../runtime/global"; import { Gravity } from "./gravity"; +import { Panel } from "../ui/panel"; +import { Color } from "./color"; export function modal(context: BridgeContext) { return { @@ -182,16 +184,30 @@ export function navigator(context: BridgeContext) { } export function navbar(context: BridgeContext) { + const entity = context.entity + let panel: Panel | undefined = undefined + if (entity instanceof Panel) { + panel = entity + } + return { + isHidden: () => { + return context.navbar.isHidden() as Promise + }, setHidden: (hidden: boolean) => { - return context.navbar.push({ + return context.navbar.setHidden({ hidden, }) }, setTitle: (title: string) => { - return context.navbar.push({ + return context.navbar.setTitle({ title, }) }, + setBgColor: (color: Color) => { + return context.navbar.setBgColor({ + color: color.toModel(), + }) + }, } } \ No newline at end of file