Merge branch 'android_master' into combine

This commit is contained in:
pengfei.zhou 2019-12-21 21:35:28 +08:00
commit 55334a11b2
59 changed files with 1206 additions and 246 deletions

View File

@ -6,3 +6,6 @@
/build /build
/captures /captures
.externalNativeBuild .externalNativeBuild
.project
.classpath
.settings/

201
doric-android/LICENSE Normal file
View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
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.

3
doric-android/README.md Normal file
View File

@ -0,0 +1,3 @@
# Doric Android SDK
## Usages

View File

@ -23,7 +23,8 @@ dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar']) implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'androidx.appcompat:appcompat:1.1.0'
implementation "com.google.android.material:material:1.0.0" implementation "com.google.android.material:material:1.0.0"
implementation project(':devkit') implementation "pub.doric:core:${rootProject.ext.Version}"
implementation "pub.doric:devkit:${rootProject.ext.Version}"
implementation 'com.github.bumptech.glide:glide:4.10.0' implementation 'com.github.bumptech.glide:glide:4.10.0'
implementation 'com.github.bumptech.glide:annotations:4.10.0' implementation 'com.github.bumptech.glide:annotations:4.10.0'
implementation 'com.github.penfeizhou.android.animation:glide-plugin:1.3.1' implementation 'com.github.penfeizhou.android.animation:glide-plugin:1.3.1'

View File

@ -21,15 +21,6 @@
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity
android:name=".DemoActivity"
android:theme="@style/Theme.Design.Light.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application> </application>
</manifest> </manifest>

View File

@ -1 +0,0 @@
../../../../../demo/bundle/src

View File

@ -0,0 +1 @@
*.js

View File

@ -33,7 +33,6 @@ import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import pub.doric.DoricActivity;
import pub.doric.devkit.ui.DemoDebugActivity; import pub.doric.devkit.ui.DemoDebugActivity;
import pub.doric.refresh.DoricSwipeLayout; import pub.doric.refresh.DoricSwipeLayout;
import pub.doric.utils.DoricUtils; import pub.doric.utils.DoricUtils;
@ -63,7 +62,6 @@ public class MainActivity extends AppCompatActivity {
try { try {
String[] demos = getAssets().list("demo"); String[] demos = getAssets().list("demo");
List<String> ret = new ArrayList<>(); List<String> ret = new ArrayList<>();
ret.add("Test");
for (String str : demos) { for (String str : demos) {
if (str.endsWith("js")) { if (str.endsWith("js")) {
ret.add(str); ret.add(str);
@ -107,21 +105,10 @@ public class MainActivity extends AppCompatActivity {
tv.setOnClickListener(new View.OnClickListener() { tv.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
if (data[position].contains("Test")) { Intent intent = new Intent(tv.getContext(), DemoDebugActivity.class);
Intent intent = new Intent(tv.getContext(), PullableActivity.class);
tv.getContext().startActivity(intent);
return;
}
if (data[position].contains("NavigatorDemo")) {
Intent intent = new Intent(tv.getContext(), DoricActivity.class);
intent.putExtra("scheme", "assets://demo/" + data[position]); intent.putExtra("scheme", "assets://demo/" + data[position]);
intent.putExtra("alias", data[position]); intent.putExtra("alias", data[position]);
tv.getContext().startActivity(intent); tv.getContext().startActivity(intent);
return;
}
Intent intent = new Intent(tv.getContext(), DemoDebugActivity.class);
intent.putExtra("source", data[position]);
tv.getContext().startActivity(intent);
} }
}); });
} }

View File

@ -7,7 +7,7 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.5.2' classpath 'com.android.tools.build:gradle:3.5.3'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files
@ -23,8 +23,41 @@ allprojects {
} }
maven { url 'https://jitpack.io' } maven { url 'https://jitpack.io' }
} }
def needReplaceLocal = true
gradle.startParameter.taskNames.each {
if (it.contains('uploadArchives')) {
needReplaceLocal = false
}
}
if (needReplaceLocal) {
configurations.all {
resolutionStrategy {
dependencySubstitution {
substitute module('pub.doric:core') with project(":doric")
substitute module('pub.doric:devkit') with project(":devkit")
}
}
}
}
} }
task clean(type: Delete) { task clean(type: Delete) {
delete rootProject.buildDir delete rootProject.buildDir
} }
Properties properties = new Properties()
properties.load(project.rootProject.file('version.properties').newDataInputStream())
ext {
Version = properties.version
}
task publisCore dependsOn(":doric:uploadArchives") {
println "doric published"
}
task publishDevKit dependsOn(publisCore, ":devkit:uploadArchives") {
println "devkit published"
}
task PublishAll dependsOn(publisCore, publishDevKit) {
println "All published"
}

View File

@ -1,7 +1,5 @@
apply plugin: 'com.android.library' apply plugin: 'com.android.library'
def projectHome = project.rootDir.getParent() + "/demo"
android { android {
compileSdkVersion 29 compileSdkVersion 29
buildToolsVersion "29.0.2" buildToolsVersion "29.0.2"
@ -22,10 +20,6 @@ android {
minifyEnabled false minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
} }
debug {
buildConfigField "String", "PROJECT_HOME", "\"${projectHome}\""
}
} }
} }
@ -33,7 +27,7 @@ android {
dependencies { dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar']) implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.github.pengfeizhou:jsc4a:0.1.0' implementation "pub.doric:core:${rootProject.ext.Version}"
implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'androidx.appcompat:appcompat:1.1.0'
implementation "com.google.android.material:material:1.0.0" implementation "com.google.android.material:material:1.0.0"
implementation 'com.squareup.okhttp3:okhttp:4.2.2' implementation 'com.squareup.okhttp3:okhttp:4.2.2'
@ -42,11 +36,10 @@ dependencies {
implementation 'com.github.tbruyelle:rxpermissions:0.10.2' implementation 'com.github.tbruyelle:rxpermissions:0.10.2'
implementation "io.reactivex.rxjava2:rxjava:2.2.15" implementation "io.reactivex.rxjava2:rxjava:2.2.15"
api 'org.greenrobot:eventbus:3.1.1' api 'org.greenrobot:eventbus:3.1.1'
implementation 'com.lahm.library:easy-protector-release:1.1.0' implementation 'com.lahm.library:easy-protector-release:1.1.1'
api 'org.nanohttpd:nanohttpd:2.3.1'
api project(':doric')
testImplementation 'junit:junit:4.12' testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
} }
apply from: rootProject.file('scripts/upload.gradle')

View File

@ -0,0 +1,3 @@
name=DoricDevKit
groupId=pub.doric
artifactId=devkit

View File

@ -2,9 +2,12 @@
package="pub.doric.devkit"> package="pub.doric.devkit">
<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />
<application> <application>
<activity android:name=".ui.ScanQRCodeActivity" /> <activity android:name=".ui.ScanQRCodeActivity" />
<activity android:name=".ui.DemoDebugActivity" /> <activity
android:name=".ui.DemoDebugActivity"
android:theme="@style/Theme.Design.Light.NoActionBar" />
</application> </application>
</manifest> </manifest>

View File

@ -1,14 +1,17 @@
package pub.doric.devkit; package pub.doric.devkit;
import pub.doric.DoricContext; import pub.doric.DoricContext;
import pub.doric.DoricContextManager;
import pub.doric.DoricNativeDriver; import pub.doric.DoricNativeDriver;
public class DoricContextDebuggable { public class DoricContextDebuggable {
private DoricContext doricContext; private DoricContext doricContext;
private DoricDebugDriver doricDebugDriver; private DoricDebugDriver doricDebugDriver;
public boolean isDebugging = false;
public DoricContextDebuggable(DoricContext doricContext) { public DoricContextDebuggable(String contextId) {
this.doricContext = doricContext; this.doricContext = DoricContextManager.getContext(contextId);
isDebugging = true;
} }
public void startDebug() { public void startDebug() {
@ -22,8 +25,13 @@ public class DoricContextDebuggable {
} }
public void stopDebug() { public void stopDebug() {
isDebugging = false;
doricDebugDriver.destroy(); doricDebugDriver.destroy();
doricContext.setDriver(DoricNativeDriver.getInstance()); doricContext.setDriver(DoricNativeDriver.getInstance());
doricContext.reInit(); doricContext.reInit();
} }
public DoricContext getContext() {
return doricContext;
}
} }

View File

@ -79,6 +79,7 @@ public class WSClient extends WebSocketListener {
} }
break; break;
case "SWITCH_TO_DEBUG": { case "SWITCH_TO_DEBUG": {
String contextId = jsonObject.optString("contextId");
EventBus.getDefault().post(new EnterDebugEvent()); EventBus.getDefault().post(new EnterDebugEvent());
} }
break; break;

View File

@ -1,4 +1,5 @@
package pub.doric.devkit.event; package pub.doric.devkit.event;
public class EnterDebugEvent { public class EnterDebugEvent {
} }

View File

@ -0,0 +1,13 @@
package pub.doric.devkit.event;
public class StartDebugEvent {
private String contextId;
public StartDebugEvent(String contextId) {
this.contextId = contextId;
}
public String getContextId() {
return contextId;
}
}

View File

@ -0,0 +1,5 @@
package pub.doric.devkit.event;
public class StopDebugEvent {
}

View File

@ -25,7 +25,7 @@ import okhttp3.WebSocket;
import okhttp3.WebSocketListener; import okhttp3.WebSocketListener;
import pub.doric.devkit.DevKit; import pub.doric.devkit.DevKit;
import pub.doric.devkit.IStatusCallback; import pub.doric.devkit.IStatusCallback;
import pub.doric.devkit.event.QuitDebugEvent; import pub.doric.devkit.event.StopDebugEvent;
public class RemoteJSExecutor { public class RemoteJSExecutor {
private final WebSocket webSocket; private final WebSocket webSocket;
@ -59,7 +59,7 @@ public class RemoteJSExecutor {
System.out.println("remote js executor eof"); System.out.println("remote js executor eof");
LockSupport.unpark(current); LockSupport.unpark(current);
EventBus.getDefault().post(new QuitDebugEvent()); EventBus.getDefault().post(new StopDebugEvent());
} }
} }

View File

@ -15,12 +15,14 @@ import androidx.fragment.app.DialogFragment;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import org.greenrobot.eventbus.EventBus;
import pub.doric.DoricContext; import pub.doric.DoricContext;
import pub.doric.DoricContextManager; import pub.doric.DoricContextManager;
import pub.doric.devkit.BuildConfig;
import pub.doric.devkit.DoricDev; import pub.doric.devkit.DoricDev;
import pub.doric.devkit.IDevKit; import pub.doric.devkit.IDevKit;
import pub.doric.devkit.R; import pub.doric.devkit.R;
import pub.doric.devkit.event.StartDebugEvent;
public class DebugContextPanel extends DialogFragment { public class DebugContextPanel extends DialogFragment {
@ -69,9 +71,9 @@ public class DebugContextPanel extends DialogFragment {
cell.findViewById(R.id.debug_text_view).setOnClickListener(new View.OnClickListener() { cell.findViewById(R.id.debug_text_view).setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
EventBus.getDefault().post(new StartDebugEvent(doricContext.getContextId()));
JsonObject jsonObject = new JsonObject(); JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("contextId", doricContext.getContextId()); jsonObject.addProperty("contextId", doricContext.getContextId());
jsonObject.addProperty("projectHome", BuildConfig.PROJECT_HOME);
jsonObject.addProperty("source", doricContext.getSource().replace(".js", ".ts")); jsonObject.addProperty("source", doricContext.getSource().replace(".js", ".ts"));
DoricDev.sendDevCommand(IDevKit.Command.DEBUG, jsonObject); DoricDev.sendDevCommand(IDevKit.Command.DEBUG, jsonObject);
dismissAllowingStateLoss(); dismissAllowingStateLoss();

View File

@ -17,46 +17,36 @@ package pub.doric.devkit.ui;
import android.os.Bundle; import android.os.Bundle;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.ViewGroup;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode; import org.greenrobot.eventbus.ThreadMode;
import pub.doric.DoricActivity;
import pub.doric.DoricContext; import pub.doric.DoricContext;
import pub.doric.DoricContextManager; import pub.doric.DoricContextManager;
import pub.doric.DoricPanel;
import pub.doric.devkit.DoricContextDebuggable; import pub.doric.devkit.DoricContextDebuggable;
import pub.doric.devkit.event.EnterDebugEvent; import pub.doric.devkit.event.EnterDebugEvent;
import pub.doric.devkit.event.QuitDebugEvent;
import pub.doric.devkit.event.ReloadEvent; import pub.doric.devkit.event.ReloadEvent;
import pub.doric.devkit.event.StartDebugEvent;
import pub.doric.devkit.event.StopDebugEvent;
import pub.doric.devkit.util.SensorManagerHelper; import pub.doric.devkit.util.SensorManagerHelper;
import pub.doric.utils.DoricUtils;
/** /**
* @Description: pub.doric.demo * @Description: pub.doric.demo
* @Author: pengfei.zhou * @Author: pengfei.zhou
* @CreateDate: 2019-11-19 * @CreateDate: 2019-11-19
*/ */
public class DemoDebugActivity extends AppCompatActivity { public class DemoDebugActivity extends DoricActivity {
private DoricContext doricContext;
private SensorManagerHelper sensorHelper; private SensorManagerHelper sensorHelper;
private DoricContextDebuggable doricContextDebuggable; private DoricContextDebuggable doricContextDebuggable;
@Override @Override
protected void onCreate(@Nullable Bundle savedInstanceState) { protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
String source = getIntent().getStringExtra("source");
DoricPanel doricPanel = new DoricPanel(this);
addContentView(doricPanel, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
doricPanel.config(DoricUtils.readAssetFile("demo/" + source), source);
doricContext = doricPanel.getDoricContext();
doricContextDebuggable = new DoricContextDebuggable(doricContext);
sensorHelper = new SensorManagerHelper(this); sensorHelper = new SensorManagerHelper(this);
sensorHelper.setOnShakeListener(new SensorManagerHelper.OnShakeListener() { sensorHelper.setOnShakeListener(new SensorManagerHelper.OnShakeListener() {
@Override @Override
@ -73,34 +63,49 @@ public class DemoDebugActivity extends AppCompatActivity {
@Override @Override
public void onAttachedToWindow() { public void onAttachedToWindow() {
super.onAttachedToWindow(); super.onAttachedToWindow();
EventBus.getDefault().register(this); EventBus.getDefault().register(this);
} }
@Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
EventBus.getDefault().unregister(this);
}
@Override @Override
protected void onDestroy() { protected void onDestroy() {
super.onDestroy(); super.onDestroy();
EventBus.getDefault().unregister(this);
sensorHelper.stop(); sensorHelper.stop();
} }
@Subscribe(threadMode = ThreadMode.MAIN)
public void onStartDebugEvent(StartDebugEvent startDebugEvent) {
doricContextDebuggable = new DoricContextDebuggable(startDebugEvent.getContextId());
}
@Subscribe(threadMode = ThreadMode.MAIN) @Subscribe(threadMode = ThreadMode.MAIN)
public void onEnterDebugEvent(EnterDebugEvent enterDebugEvent) { public void onEnterDebugEvent(EnterDebugEvent enterDebugEvent) {
doricContextDebuggable.startDebug(); doricContextDebuggable.startDebug();
} }
@Subscribe(threadMode = ThreadMode.MAIN)
public void onQuitDebugEvent(StopDebugEvent quitDebugEvent) {
doricContextDebuggable.stopDebug();
}
@Subscribe(threadMode = ThreadMode.MAIN) @Subscribe(threadMode = ThreadMode.MAIN)
public void onReloadEvent(ReloadEvent reloadEvent) { public void onReloadEvent(ReloadEvent reloadEvent) {
for (DoricContext context : DoricContextManager.aliveContexts()) { for (DoricContext context : DoricContextManager.aliveContexts()) {
if (reloadEvent.source.contains(context.getSource())) { if (reloadEvent.source.contains(context.getSource())) {
if (doricContextDebuggable != null &&
doricContextDebuggable.isDebugging &&
doricContextDebuggable.getContext().getContextId().equals(context.getContextId())) {
System.out.println("is debugging context id: " + context.getContextId());
} else {
context.reload(reloadEvent.script); context.reload(reloadEvent.script);
} }
} }
} }
@Subscribe(threadMode = ThreadMode.MAIN)
public void onQuitDebugEvent(QuitDebugEvent quitDebugEvent) {
doricContextDebuggable.stopDebug();
} }
@Override @Override

View File

@ -25,35 +25,31 @@ android {
afterEvaluate { afterEvaluate {
buildJSBundle.exec() buildJSBundle.exec()
buildDemo.exec()
//buildDebugger.exec()
} }
task buildJSBundle(type: Exec) { task buildJSBundle(type: Exec) {
workingDir project.rootDir.getParent() + "/js-framework" commandLine 'sh', project.rootDir.getParent() + "/bundle.sh"
commandLine 'npm', 'run', 'build'
} }
task buildDemo(type: Exec) {
workingDir project.rootDir.getParent() + "/demo"
commandLine 'npm', 'run', 'build'
}
task buildDebugger(type: Exec) {
workingDir project.rootDir.getParent() + "/debugger"
commandLine 'npm', 'run', 'build'
}
dependencies { dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar']) implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'androidx.appcompat:appcompat:1.1.0'
api 'com.github.pengfeizhou:jsc4a:0.1.0' api 'com.github.penfeizhou:jsc4a:0.1.0'
implementation 'com.squareup.okhttp3:okhttp:4.2.2' implementation 'com.squareup.okhttp3:okhttp:4.2.2'
implementation 'com.github.penfeizhou.android.animation:glide-plugin:1.3.1' implementation 'com.github.penfeizhou.android.animation:glide-plugin:1.3.1'
implementation 'jp.wasabeef:glide-transformations:4.1.0'
implementation 'com.google.code.gson:gson:2.8.6' implementation 'com.google.code.gson:gson:2.8.6'
implementation "com.google.android.material:material:1.0.0" implementation "com.google.android.material:material:1.0.0"
testImplementation 'junit:junit:4.12' testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
def nav_version = "2.1.0"
implementation "androidx.navigation:navigation-fragment:$nav_version"
implementation "androidx.navigation:navigation-ui:$nav_version"
} }
apply from: rootProject.file('scripts/upload.gradle')

View File

@ -0,0 +1,4 @@
name=Doric
groupId=pub.doric
artifactId=core
version=0.1.0

View File

@ -1,7 +1,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="pub.doric"> package="pub.doric">
<uses-permission android:name="android.permission.CAMERA" />
<application> <application>
<activity <activity

View File

@ -1 +0,0 @@
../../../../../js-framework/bundle

View File

@ -0,0 +1 @@
*.js

View File

@ -26,8 +26,6 @@ import androidx.appcompat.app.AppCompatActivity;
* @CreateDate: 2019-11-19 * @CreateDate: 2019-11-19
*/ */
public class DoricActivity extends AppCompatActivity { public class DoricActivity extends AppCompatActivity {
private DoricFragment doricFragment;
@Override @Override
protected void onCreate(@Nullable Bundle savedInstanceState) { protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -35,19 +33,10 @@ public class DoricActivity extends AppCompatActivity {
if (savedInstanceState == null) { if (savedInstanceState == null) {
String scheme = getIntent().getStringExtra("scheme"); String scheme = getIntent().getStringExtra("scheme");
String alias = getIntent().getStringExtra("alias"); String alias = getIntent().getStringExtra("alias");
doricFragment = DoricFragment.newInstance(scheme, alias); DoricFragment doricFragment = DoricFragment.newInstance(scheme, alias);
getSupportFragmentManager().beginTransaction() getSupportFragmentManager().beginTransaction()
.add(R.id.container, doricFragment) .add(R.id.container, doricFragment)
.commit(); .commit();
} }
} }
@Override
public void onBackPressed() {
if (doricFragment.canPop()) {
doricFragment.pop();
} else {
super.onBackPressed();
}
}
} }

View File

@ -15,7 +15,6 @@
*/ */
package pub.doric; package pub.doric;
import android.animation.Animator;
import android.animation.AnimatorSet; import android.animation.AnimatorSet;
import android.content.Context; import android.content.Context;
@ -49,6 +48,7 @@ public class DoricContext {
private RootNode mRootNode = new RootNode(this); private RootNode mRootNode = new RootNode(this);
private final String source; private final String source;
private String script; private String script;
private String extra;
private JSONObject initParams; private JSONObject initParams;
private IDoricDriver doricDriver; private IDoricDriver doricDriver;
private final Map<String, ViewNode> mHeadNodes = new HashMap<>(); private final Map<String, ViewNode> mHeadNodes = new HashMap<>();
@ -72,10 +72,11 @@ public class DoricContext {
return mHeadNodes.get(id); return mHeadNodes.get(id);
} }
protected DoricContext(Context context, String contextId, String source) { protected DoricContext(Context context, String contextId, String source, String extra) {
this.mContext = context; this.mContext = context;
this.mContextId = contextId; this.mContextId = contextId;
this.source = source; this.source = source;
this.extra = extra;
} }
public String getSource() { public String getSource() {
@ -86,22 +87,25 @@ public class DoricContext {
return script; return script;
} }
public static DoricContext create(Context context, String script, String source) { public static DoricContext create(Context context, String script, String source, String extra) {
DoricContext doricContext = DoricContextManager.getInstance().createContext(context, script, source); DoricContext doricContext = DoricContextManager.getInstance().createContext(context, script, source, extra);
doricContext.script = script; doricContext.script = script;
doricContext.extra = extra;
return doricContext; return doricContext;
} }
public void init(float width, float height) { public void init(float width, float height) {
this.initParams = new JSONBuilder() this.initParams = new JSONBuilder()
.put("width", width) .put("width", width)
.put("height", height).toJSONObject(); .put("height", height)
callEntity(DoricConstant.DORIC_ENTITY_INIT, this.initParams); .toJSONObject();
callEntity(DoricConstant.DORIC_ENTITY_INIT, this.initParams, extra);
callEntity(DoricConstant.DORIC_ENTITY_CREATE); callEntity(DoricConstant.DORIC_ENTITY_CREATE);
} }
public void reInit() { public void reInit() {
callEntity(DoricConstant.DORIC_ENTITY_INIT, this.initParams); this.mRootNode.setId("");
callEntity(DoricConstant.DORIC_ENTITY_INIT, this.initParams, extra);
callEntity(DoricConstant.DORIC_ENTITY_CREATE); callEntity(DoricConstant.DORIC_ENTITY_CREATE);
} }
@ -165,7 +169,8 @@ public class DoricContext {
this.script = script; this.script = script;
this.mRootNode.setId(""); this.mRootNode.setId("");
getDriver().createContext(mContextId, script, source); getDriver().createContext(mContextId, script, source);
callEntity(DoricConstant.DORIC_ENTITY_INIT, this.initParams); callEntity(DoricConstant.DORIC_ENTITY_INIT, this.initParams, extra);
onShow();
} }
public void onShow() { public void onShow() {

View File

@ -48,9 +48,9 @@ public class DoricContextManager {
return Inner.sInstance; return Inner.sInstance;
} }
DoricContext createContext(Context context, final String script, final String source) { DoricContext createContext(Context context, final String script, final String source, String extra) {
final String contextId = String.valueOf(counter.incrementAndGet()); final String contextId = String.valueOf(counter.incrementAndGet());
final DoricContext doricContext = new DoricContext(context, contextId, source); final DoricContext doricContext = new DoricContext(context, contextId, source, extra);
doricContextMap.put(contextId, doricContext); doricContextMap.put(contextId, doricContext);
doricContext.getDriver().createContext(contextId, script, source); doricContext.getDriver().createContext(contextId, script, source);
return doricContext; return doricContext;

View File

@ -20,18 +20,19 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import androidx.activity.OnBackPressedCallback;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.navigation.NavController;
import pub.doric.navigator.IDoricNavigator; import androidx.navigation.Navigation;
/** /**
* @Description: pub.doric * @Description: pub.doric
* @Author: pengfei.zhou * @Author: pengfei.zhou
* @CreateDate: 2019-11-23 * @CreateDate: 2019-11-23
*/ */
public class DoricFragment extends Fragment implements IDoricNavigator { public class DoricFragment extends Fragment {
public static DoricFragment newInstance(String scheme, String alias) { public static DoricFragment newInstance(String scheme, String alias) {
Bundle args = new Bundle(); Bundle args = new Bundle();
@ -42,6 +43,23 @@ public class DoricFragment extends Fragment implements IDoricNavigator {
return fragment; return fragment;
} }
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
OnBackPressedCallback callback = new OnBackPressedCallback(true) {
@Override
public void handleOnBackPressed() {
NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host);
if (!navController.popBackStack()) {
if (getActivity() != null) {
getActivity().finish();
}
}
}
};
requireActivity().getOnBackPressedDispatcher().addCallback(this, callback);
}
@Nullable @Nullable
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
@ -51,34 +69,6 @@ public class DoricFragment extends Fragment implements IDoricNavigator {
@Override @Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
Bundle argument = getArguments();
if (argument != null) {
String alias = argument.getString("alias");
String scheme = argument.getString("scheme");
push(scheme, alias);
}
} }
@Override
public void push(String scheme, String alias) {
getChildFragmentManager().beginTransaction()
.add(R.id.root, DoricPanelFragment.newInstance(scheme, alias))
.addToBackStack(scheme)
.commit();
}
@Override
public void pop() {
if (canPop()) {
getChildFragmentManager().popBackStack();
} else {
if (getActivity() != null) {
getActivity().finish();
}
}
}
public boolean canPop() {
return getChildFragmentManager().getBackStackEntryCount() > 1;
}
} }

View File

@ -54,8 +54,8 @@ public class DoricPanel extends FrameLayout implements LifecycleObserver {
} }
public void config(String script, String alias) { public void config(String script, String alias, String extra) {
DoricContext doricContext = DoricContext.create(getContext(), script, alias); DoricContext doricContext = DoricContext.create(getContext(), script, alias, extra);
config(doricContext); config(doricContext);
} }

View File

@ -23,6 +23,8 @@ import android.view.ViewGroup;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import pub.doric.async.AsyncResult; import pub.doric.async.AsyncResult;
import pub.doric.loader.DoricJSLoaderManager; import pub.doric.loader.DoricJSLoaderManager;
@ -35,18 +37,8 @@ import pub.doric.utils.DoricLog;
* @Author: pengfei.zhou * @Author: pengfei.zhou
* @CreateDate: 2019-11-23 * @CreateDate: 2019-11-23
*/ */
public class DoricPanelFragment extends Fragment { public class DoricPanelFragment extends Fragment implements IDoricNavigator {
private DoricPanel doricPanel; private DoricPanel doricPanel;
private BaseDoricNavBar navBar;
public static DoricPanelFragment newInstance(String scheme, String alias) {
Bundle args = new Bundle();
args.putString("scheme", scheme);
args.putString("alias", alias);
DoricPanelFragment fragment = new DoricPanelFragment();
fragment.setArguments(args);
return fragment;
}
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
@ -58,23 +50,26 @@ public class DoricPanelFragment extends Fragment {
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
doricPanel = view.findViewById(R.id.doric_panel); doricPanel = view.findViewById(R.id.doric_panel);
navBar = view.findViewById(R.id.doric_nav_bar);
Bundle argument = getArguments(); Bundle argument = getArguments();
if (argument == null) {
if (getActivity() != null && getActivity().getIntent() != null) {
argument = getActivity().getIntent().getExtras();
}
}
if (argument == null) { if (argument == null) {
DoricLog.e("DoricPanelFragment argument is null"); DoricLog.e("DoricPanelFragment argument is null");
return; return;
} }
final String alias = argument.getString("alias"); final String alias = argument.getString("alias");
String scheme = argument.getString("scheme"); String scheme = argument.getString("scheme");
final String extra = argument.getString("extra");
DoricJSLoaderManager.getInstance().loadJSBundle(scheme).setCallback(new AsyncResult.Callback<String>() { DoricJSLoaderManager.getInstance().loadJSBundle(scheme).setCallback(new AsyncResult.Callback<String>() {
@Override @Override
public void onResult(String result) { public void onResult(String result) {
doricPanel.config(result, alias); doricPanel.config(result, alias, extra);
DoricContext context = doricPanel.getDoricContext(); DoricContext context = doricPanel.getDoricContext();
Fragment fragment = getParentFragment(); context.setDoricNavigator(DoricPanelFragment.this);
if (fragment instanceof IDoricNavigator) { BaseDoricNavBar navBar = requireActivity().getWindow().getDecorView().findViewById(R.id.doric_nav_bar);
context.setDoricNavigator((IDoricNavigator) fragment);
}
context.setDoricNavBar(navBar); context.setDoricNavBar(navBar);
} }
@ -89,4 +84,41 @@ public class DoricPanelFragment extends Fragment {
} }
}); });
} }
@Override
public void push(String scheme, String alias, String extra) {
Bundle argument = new Bundle();
argument.putString("scheme", scheme);
argument.putString("alias", alias);
argument.putString("extra", extra);
getNavController()
.navigate(R.id.action_doricPanelFragment_to_doricPanelFragment, argument);
}
@Override
public void pop() {
getNavController().popBackStack();
}
private NavController getNavController() {
return Navigation.findNavController(getView());
}
@Override
public void onResume() {
super.onResume();
doricPanel.onActivityResume();
}
@Override
public void onPause() {
super.onPause();
doricPanel.onActivityPause();
}
@Override
public void onDestroy() {
super.onDestroy();
doricPanel.onActivityDestroy();
}
} }

View File

@ -30,6 +30,7 @@ import pub.doric.plugin.StoragePlugin;
import pub.doric.refresh.RefreshableNode; import pub.doric.refresh.RefreshableNode;
import pub.doric.shader.HLayoutNode; import pub.doric.shader.HLayoutNode;
import pub.doric.shader.ImageNode; import pub.doric.shader.ImageNode;
import pub.doric.shader.InputNode;
import pub.doric.shader.ScrollerNode; import pub.doric.shader.ScrollerNode;
import pub.doric.shader.flowlayout.FlowLayoutItemNode; import pub.doric.shader.flowlayout.FlowLayoutItemNode;
import pub.doric.shader.flowlayout.FlowLayoutNode; import pub.doric.shader.flowlayout.FlowLayoutNode;
@ -40,6 +41,7 @@ import pub.doric.shader.StackNode;
import pub.doric.shader.TextNode; import pub.doric.shader.TextNode;
import pub.doric.shader.VLayoutNode; import pub.doric.shader.VLayoutNode;
import pub.doric.shader.ViewNode; import pub.doric.shader.ViewNode;
import pub.doric.shader.slider.NestedSliderNode;
import pub.doric.shader.slider.SlideItemNode; import pub.doric.shader.slider.SlideItemNode;
import pub.doric.shader.slider.SliderNode; import pub.doric.shader.slider.SliderNode;
import pub.doric.utils.DoricMetaInfo; import pub.doric.utils.DoricMetaInfo;
@ -106,6 +108,8 @@ public class DoricRegistry {
this.registerViewNode(RefreshableNode.class); this.registerViewNode(RefreshableNode.class);
this.registerViewNode(FlowLayoutNode.class); this.registerViewNode(FlowLayoutNode.class);
this.registerViewNode(FlowLayoutItemNode.class); this.registerViewNode(FlowLayoutItemNode.class);
this.registerViewNode(InputNode.class);
this.registerViewNode(NestedSliderNode.class);
initRegistry(this); initRegistry(this);
} }

View File

@ -15,6 +15,9 @@
*/ */
package pub.doric.engine; package pub.doric.engine;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Handler; import android.os.Handler;
import android.os.HandlerThread; import android.os.HandlerThread;
import android.os.Looper; import android.os.Looper;
@ -22,11 +25,13 @@ import android.os.Message;
import android.text.TextUtils; import android.text.TextUtils;
import com.github.pengfeizhou.jscore.JSDecoder; import com.github.pengfeizhou.jscore.JSDecoder;
import com.github.pengfeizhou.jscore.JSONBuilder;
import com.github.pengfeizhou.jscore.JavaFunction; import com.github.pengfeizhou.jscore.JavaFunction;
import com.github.pengfeizhou.jscore.JavaValue; import com.github.pengfeizhou.jscore.JavaValue;
import java.util.ArrayList; import java.util.ArrayList;
import pub.doric.Doric;
import pub.doric.DoricRegistry; import pub.doric.DoricRegistry;
import pub.doric.extension.bridge.DoricBridgeExtension; import pub.doric.extension.bridge.DoricBridgeExtension;
import pub.doric.extension.timer.DoricTimerExtension; import pub.doric.extension.timer.DoricTimerExtension;
@ -73,6 +78,27 @@ public class DoricJSEngine implements Handler.Callback, DoricTimerExtension.Time
} }
private void injectGlobal() { private void injectGlobal() {
String appName = "";
String appVersion = "";
Context context = Doric.application();
try {
PackageManager packageManager = context.getPackageManager();
PackageInfo packageInfo = packageManager.getPackageInfo(
context.getPackageName(), 0);
int labelRes = packageInfo.applicationInfo.labelRes;
appName = context.getResources().getString(labelRes);
appVersion = packageInfo.versionName;
} catch (Exception e) {
e.printStackTrace();
}
mDoricJSE.injectGlobalJSObject(DoricConstant.INJECT_ENVIRONMENT, new JavaValue(new JSONBuilder()
.put("platform", "Android")
.put("platformVersion", String.valueOf(android.os.Build.VERSION.SDK_INT))
.put("appName", appName)
.put("appVersion", appVersion)
.put("screenWidth", DoricUtils.px2dp(DoricUtils.getScreenWidth()))
.put("screenHeight", DoricUtils.px2dp(DoricUtils.getScreenHeight()))
.toJSONObject()));
mDoricJSE.injectGlobalJSFunction(DoricConstant.INJECT_LOG, new JavaFunction() { mDoricJSE.injectGlobalJSFunction(DoricConstant.INJECT_LOG, new JavaFunction() {
@Override @Override
public JavaValue exec(JSDecoder[] args) { public JavaValue exec(JSDecoder[] args) {

View File

@ -21,7 +21,7 @@ package pub.doric.navigator;
* @CreateDate: 2019-11-23 * @CreateDate: 2019-11-23
*/ */
public interface IDoricNavigator { public interface IDoricNavigator {
void push(String scheme, String alias); void push(String scheme, String alias, String extra);
void pop(); void pop();
} }

View File

@ -61,13 +61,6 @@ public class NavBarPlugin extends DoricJavaPlugin {
JSObject jsObject = jsDecoder.decode().asObject(); JSObject jsObject = jsDecoder.decode().asObject();
boolean hidden = jsObject.getProperty("hidden").asBoolean().value(); boolean hidden = jsObject.getProperty("hidden").asBoolean().value();
navBar.setHidden(hidden); navBar.setHidden(hidden);
View v = getDoricContext().getRootNode().getNodeView();
ViewGroup.LayoutParams params = v.getLayoutParams();
if (params instanceof ViewGroup.MarginLayoutParams) {
((ViewGroup.MarginLayoutParams) params).topMargin =
hidden ? 0
: ((View) navBar).getMeasuredHeight();
}
promise.resolve(); promise.resolve();
} catch (ArchiveException e) { } catch (ArchiveException e) {
e.printStackTrace(); e.printStackTrace();

View File

@ -18,10 +18,14 @@ package pub.doric.plugin;
import com.github.pengfeizhou.jscore.ArchiveException; import com.github.pengfeizhou.jscore.ArchiveException;
import com.github.pengfeizhou.jscore.JSDecoder; import com.github.pengfeizhou.jscore.JSDecoder;
import com.github.pengfeizhou.jscore.JSObject; import com.github.pengfeizhou.jscore.JSObject;
import com.github.pengfeizhou.jscore.JSValue;
import com.github.pengfeizhou.jscore.JavaValue;
import pub.doric.Doric;
import pub.doric.DoricContext; import pub.doric.DoricContext;
import pub.doric.extension.bridge.DoricMethod; import pub.doric.extension.bridge.DoricMethod;
import pub.doric.extension.bridge.DoricPlugin; import pub.doric.extension.bridge.DoricPlugin;
import pub.doric.extension.bridge.DoricPromise;
import pub.doric.navigator.IDoricNavigator; import pub.doric.navigator.IDoricNavigator;
import pub.doric.utils.ThreadMode; import pub.doric.utils.ThreadMode;
@ -37,25 +41,47 @@ public class NavigatorPlugin extends DoricJavaPlugin {
} }
@DoricMethod(thread = ThreadMode.UI) @DoricMethod(thread = ThreadMode.UI)
public void push(JSDecoder jsDecoder) { public void push(JSDecoder jsDecoder, DoricPromise promise) {
IDoricNavigator navigator = getDoricContext().getDoricNavigator(); IDoricNavigator navigator = getDoricContext().getDoricNavigator();
if (navigator != null) { if (navigator != null) {
try { try {
JSObject jsObject = jsDecoder.decode().asObject(); JSObject jsObject = jsDecoder.decode().asObject();
String scheme = jsObject.getProperty("scheme").asString().value();
String alias = scheme;
String extra = "";
JSValue config = jsObject.getProperty("config");
if (config.isObject()) {
JSValue aliasJS = config.asObject().getProperty("alias");
if (aliasJS.isString()) {
alias = aliasJS.asString().value();
}
JSValue extraJS = config.asObject().getProperty("extra");
if (extraJS.isString()) {
extra = extraJS.asString().value();
}
}
navigator.push(jsObject.getProperty("scheme").asString().value(), navigator.push(jsObject.getProperty("scheme").asString().value(),
jsObject.getProperty("alias").asString().value() alias,
extra
); );
promise.resolve();
} catch (ArchiveException e) { } catch (ArchiveException e) {
e.printStackTrace(); e.printStackTrace();
promise.reject(new JavaValue(e.getLocalizedMessage()));
} }
} else {
promise.reject(new JavaValue("Navigator not implemented"));
} }
} }
@DoricMethod(thread = ThreadMode.UI) @DoricMethod(thread = ThreadMode.UI)
public void pop() { public void pop(DoricPromise promise) {
IDoricNavigator navigator = getDoricContext().getDoricNavigator(); IDoricNavigator navigator = getDoricContext().getDoricNavigator();
if (navigator != null) { if (navigator != null) {
navigator.pop(); navigator.pop();
promise.resolve();
} else {
promise.reject(new JavaValue("Navigator not implemented"));
} }
} }
} }

View File

@ -17,7 +17,6 @@ package pub.doric.plugin;
import android.text.TextUtils; import android.text.TextUtils;
import com.github.pengfeizhou.jscore.JSDecoder;
import com.github.pengfeizhou.jscore.JSONBuilder; import com.github.pengfeizhou.jscore.JSONBuilder;
import com.github.pengfeizhou.jscore.JSObject; import com.github.pengfeizhou.jscore.JSObject;
import com.github.pengfeizhou.jscore.JSValue; import com.github.pengfeizhou.jscore.JSValue;
@ -51,7 +50,8 @@ import pub.doric.extension.bridge.DoricPromise;
*/ */
@DoricPlugin(name = "network") @DoricPlugin(name = "network")
public class NetworkPlugin extends DoricJavaPlugin { public class NetworkPlugin extends DoricJavaPlugin {
private OkHttpClient okHttpClient = new OkHttpClient(); private OkHttpClient okHttpClient = new OkHttpClient.Builder()
.build();
public NetworkPlugin(DoricContext doricContext) { public NetworkPlugin(DoricContext doricContext) {
super(doricContext); super(doricContext);
@ -79,9 +79,10 @@ public class NetworkPlugin extends DoricJavaPlugin {
MediaType mediaType = MediaType.parse(TextUtils.isEmpty(contentType) ? "application/json; charset=utf-8" : contentType); MediaType mediaType = MediaType.parse(TextUtils.isEmpty(contentType) ? "application/json; charset=utf-8" : contentType);
RequestBody requestBody = HttpMethod.permitsRequestBody(method) ? RequestBody.create(mediaType, dataVal.isString() ? dataVal.asString().value() : "") : null; RequestBody requestBody = HttpMethod.permitsRequestBody(method) ? RequestBody.create(mediaType, dataVal.isString() ? dataVal.asString().value() : "") : null;
Request.Builder requestBuilder = new Request.Builder(); Request.Builder requestBuilder = new Request.Builder();
requestBuilder.url(url) requestBuilder = requestBuilder.url(url).headers(headers);
.headers(headers) if (HttpMethod.permitsRequestBody(method.toUpperCase())) {
.method(method, requestBody); requestBuilder = requestBuilder.method(method, requestBody);
}
if (timeoutVal.isNumber() && okHttpClient.connectTimeoutMillis() != timeoutVal.asNumber().toLong()) { if (timeoutVal.isNumber() && okHttpClient.connectTimeoutMillis() != timeoutVal.asNumber().toLong()) {
okHttpClient = okHttpClient.newBuilder().connectTimeout(timeoutVal.asNumber().toLong(), TimeUnit.MILLISECONDS).build(); okHttpClient = okHttpClient.newBuilder().connectTimeout(timeoutVal.asNumber().toLong(), TimeUnit.MILLISECONDS).build();
} }

View File

@ -31,8 +31,8 @@ import java.util.ArrayList;
* @CreateDate: 2019-07-20 * @CreateDate: 2019-07-20
*/ */
public abstract class GroupNode<F extends ViewGroup> extends SuperNode<F> { public abstract class GroupNode<F extends ViewGroup> extends SuperNode<F> {
private ArrayList<ViewNode> mChildNodes = new ArrayList<>(); protected ArrayList<ViewNode> mChildNodes = new ArrayList<>();
private ArrayList<String> mChildViewIds = new ArrayList<>(); protected ArrayList<String> mChildViewIds = new ArrayList<>();
public GroupNode(DoricContext doricContext) { public GroupNode(DoricContext doricContext) {
super(doricContext); super(doricContext);
@ -57,7 +57,7 @@ public abstract class GroupNode<F extends ViewGroup> extends SuperNode<F> {
configChildNode(); configChildNode();
} }
private void configChildNode() { protected void configChildNode() {
for (int idx = 0; idx < mChildViewIds.size(); idx++) { for (int idx = 0; idx < mChildViewIds.size(); idx++) {
String id = mChildViewIds.get(idx); String id = mChildViewIds.get(idx);
JSObject model = getSubModel(id); JSObject model = getSubModel(id);

View File

@ -17,11 +17,7 @@ package pub.doric.shader;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import androidx.annotation.Nullable;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Base64; import android.util.Base64;
import android.widget.ImageView; import android.widget.ImageView;
@ -30,18 +26,21 @@ import com.bumptech.glide.Glide;
import com.bumptech.glide.load.DataSource; import com.bumptech.glide.load.DataSource;
import com.bumptech.glide.load.engine.GlideException; import com.bumptech.glide.load.engine.GlideException;
import com.bumptech.glide.request.RequestListener; import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.Target; import com.bumptech.glide.request.target.Target;
import pub.doric.DoricContext;
import pub.doric.extension.bridge.DoricPlugin;
import pub.doric.utils.DoricUtils;
import com.github.pengfeizhou.jscore.JSONBuilder; import com.github.pengfeizhou.jscore.JSONBuilder;
import com.github.pengfeizhou.jscore.JSObject;
import com.github.pengfeizhou.jscore.JSValue; import com.github.pengfeizhou.jscore.JSValue;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import androidx.annotation.Nullable;
import jp.wasabeef.glide.transformations.BlurTransformation;
import pub.doric.DoricContext;
import pub.doric.extension.bridge.DoricPlugin;
import pub.doric.utils.DoricUtils;
/** /**
* @Description: com.github.penfeizhou.doric.widget * @Description: com.github.penfeizhou.doric.widget
* @Author: pengfei.zhou * @Author: pengfei.zhou
@ -50,6 +49,7 @@ import java.util.regex.Pattern;
@DoricPlugin(name = "Image") @DoricPlugin(name = "Image")
public class ImageNode extends ViewNode<ImageView> { public class ImageNode extends ViewNode<ImageView> {
private String loadCallbackId = ""; private String loadCallbackId = "";
private boolean isBlur;
public ImageNode(DoricContext doricContext) { public ImageNode(DoricContext doricContext) {
super(doricContext); super(doricContext);
@ -60,11 +60,29 @@ public class ImageNode extends ViewNode<ImageView> {
return new ImageView(getContext()); return new ImageView(getContext());
} }
@Override
public void blend(JSObject jsObject) {
if(jsObject != null) {
JSValue jsValue = jsObject.getProperty("isBlur");
if(jsValue.isBoolean()) {
isBlur = jsValue.asBoolean().value();
}
}
super.blend(jsObject);
}
@Override @Override
protected void blend(ImageView view, String name, JSValue prop) { protected void blend(ImageView view, String name, JSValue prop) {
switch (name) { switch (name) {
case "imageUrl": case "imageUrl":
RequestOptions options;
if(isBlur) {
options = RequestOptions.bitmapTransform(new BlurTransformation(25, 3));
} else {
options = new RequestOptions();
}
Glide.with(getContext()).load(prop.asString().value()) Glide.with(getContext()).load(prop.asString().value())
.apply(options)
.listener(new RequestListener<Drawable>() { .listener(new RequestListener<Drawable>() {
@Override @Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) { public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {

View File

@ -0,0 +1,153 @@
/*
* 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.shader;
import android.text.Editable;
import android.text.InputType;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.widget.EditText;
import com.github.pengfeizhou.jscore.JSObject;
import com.github.pengfeizhou.jscore.JSValue;
import pub.doric.DoricContext;
import pub.doric.extension.bridge.DoricMethod;
import pub.doric.extension.bridge.DoricPlugin;
import pub.doric.extension.bridge.DoricPromise;
/**
* @Description: pub.doric.shader
* @Author: pengfei.zhou
* @CreateDate: 2019-12-06
*/
@DoricPlugin(name = "Input")
public class InputNode extends ViewNode<EditText> implements TextWatcher, View.OnFocusChangeListener {
private String onTextChangeId;
private String onFocusChangeId;
public InputNode(DoricContext doricContext) {
super(doricContext);
}
@Override
protected EditText build() {
EditText editText = new EditText(getContext());
editText.addTextChangedListener(this);
editText.setOnFocusChangeListener(this);
return editText;
}
@Override
protected void blend(EditText view, String name, JSValue prop) {
switch (name) {
case "text":
view.setText(prop.asString().toString());
break;
case "textSize":
view.setTextSize(TypedValue.COMPLEX_UNIT_DIP, prop.asNumber().toFloat());
break;
case "textColor":
view.setTextColor(prop.asNumber().toInt());
break;
case "textAlignment":
view.setGravity(prop.asNumber().toInt() | Gravity.CENTER_VERTICAL);
break;
case "hintText":
view.setHint(prop.asString().toString());
break;
case "hintTextColor":
view.setHintTextColor(prop.asNumber().toInt());
break;
case "multiline":
if (prop.asBoolean().value()) {
view.setInputType(view.getInputType() | InputType.TYPE_TEXT_FLAG_MULTI_LINE);
} else {
view.setInputType(view.getInputType() & ~InputType.TYPE_TEXT_FLAG_MULTI_LINE);
}
break;
case "onTextChange":
if (prop.isString()) {
onTextChangeId = prop.asString().value();
} else {
onTextChangeId = null;
}
break;
case "onFocusChange":
if (prop.isString()) {
onFocusChangeId = prop.asString().value();
} else {
onFocusChangeId = null;
}
break;
default:
super.blend(view, name, prop);
break;
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
if (!TextUtils.isEmpty(onTextChangeId)) {
callJSResponse(onTextChangeId, s.toString());
}
}
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!TextUtils.isEmpty(onFocusChangeId)) {
callJSResponse(onFocusChangeId, hasFocus);
}
}
@DoricMethod
public String getText() {
return mView.getText().toString();
}
@DoricMethod
public void setSelection(JSObject jsObject, DoricPromise doricPromise) {
int start = jsObject.getProperty("start").asNumber().toInt();
int end = jsObject.getProperty("end").asNumber().toInt();
mView.setSelection(start, end);
doricPromise.resolve();
}
@DoricMethod
public void requestFocus(DoricPromise promise) {
mView.requestFocus();
promise.resolve();
}
@DoricMethod
public void releaseFocus(DoricPromise promise) {
mView.clearFocus();
promise.resolve();
}
}

View File

@ -85,6 +85,10 @@ public abstract class SuperNode<V extends View> extends ViewNode<V> {
subNodes.clear(); subNodes.clear();
} }
public void removeSubModel(String id) {
subNodes.remove(id);
}
protected abstract void blendSubNode(JSObject subProperties); protected abstract void blendSubNode(JSObject subProperties);
protected void blendSubLayoutConfig(ViewNode viewNode, JSObject jsObject) { protected void blendSubLayoutConfig(ViewNode viewNode, JSObject jsObject) {

View File

@ -39,6 +39,7 @@ public class TextNode extends ViewNode<TextView> {
protected TextView build() { protected TextView build() {
TextView tv = new TextView(getContext()); TextView tv = new TextView(getContext());
tv.setGravity(Gravity.CENTER); tv.setGravity(Gravity.CENTER);
tv.setMaxLines(1);
return tv; return tv;
} }
@ -57,7 +58,8 @@ public class TextNode extends ViewNode<TextView> {
case "textAlignment": case "textAlignment":
view.setGravity(prop.asNumber().toInt() | Gravity.CENTER_VERTICAL); view.setGravity(prop.asNumber().toInt() | Gravity.CENTER_VERTICAL);
break; break;
case "numberOfLines": case "maxLines":
view.setMaxLines(prop.asNumber().toInt());
break; break;
default: default:
super.blend(view, name, prop); super.blend(view, name, prop);

View File

@ -37,6 +37,7 @@ import androidx.annotation.NonNull;
import androidx.interpolator.view.animation.FastOutSlowInInterpolator; import androidx.interpolator.view.animation.FastOutSlowInInterpolator;
import androidx.interpolator.view.animation.LinearOutSlowInInterpolator; import androidx.interpolator.view.animation.LinearOutSlowInInterpolator;
import pub.doric.Doric;
import pub.doric.DoricContext; import pub.doric.DoricContext;
import pub.doric.DoricRegistry; import pub.doric.DoricRegistry;
import pub.doric.async.AsyncResult; import pub.doric.async.AsyncResult;
@ -55,6 +56,8 @@ import com.github.pengfeizhou.jscore.JSObject;
import com.github.pengfeizhou.jscore.JSValue; import com.github.pengfeizhou.jscore.JSValue;
import com.github.pengfeizhou.jscore.JavaValue; import com.github.pengfeizhou.jscore.JavaValue;
import org.json.JSONObject;
import java.util.LinkedList; import java.util.LinkedList;
/** /**
@ -214,6 +217,7 @@ public abstract class ViewNode<T extends View> extends DoricContextHolder {
if (prop.isObject()) { if (prop.isObject()) {
requireDoricLayer().setBorder(DoricUtils.dp2px(prop.asObject().getProperty("width").asNumber().toFloat()), requireDoricLayer().setBorder(DoricUtils.dp2px(prop.asObject().getProperty("width").asNumber().toFloat()),
prop.asObject().getProperty("color").asNumber().toInt()); prop.asObject().getProperty("color").asNumber().toInt());
requireDoricLayer().invalidate();
} }
break; break;
case "alpha": case "alpha":
@ -339,6 +343,16 @@ public abstract class ViewNode<T extends View> extends DoricContextHolder {
setRotation(prop.asNumber().toFloat()); setRotation(prop.asNumber().toFloat());
} }
break; break;
case "padding":
if (prop.isObject()) {
setPadding(prop.asObject());
}
break;
case "hidden":
if (prop.isBoolean()) {
getNodeView().setVisibility(prop.asBoolean().value() ? View.GONE : View.VISIBLE);
}
break;
default: default:
break; break;
} }
@ -409,6 +423,19 @@ public abstract class ViewNode<T extends View> extends DoricContextHolder {
} }
} }
protected void setPadding(JSObject paddings) {
JSValue left = paddings.getProperty("left");
JSValue right = paddings.getProperty("right");
JSValue top = paddings.getProperty("top");
JSValue bottom = paddings.getProperty("bottom");
mView.setPadding(
left.isNumber() ? DoricUtils.dp2px(left.asNumber().toFloat()) : 0,
top.isNumber() ? DoricUtils.dp2px(top.asNumber().toFloat()) : 0,
right.isNumber() ? DoricUtils.dp2px(right.asNumber().toFloat()) : 0,
bottom.isNumber() ? DoricUtils.dp2px(bottom.asNumber().toFloat()) : 0
);
}
private void blendLayoutConfig(JSObject jsObject) { private void blendLayoutConfig(JSObject jsObject) {
JSValue margin = jsObject.getProperty("margin"); JSValue margin = jsObject.getProperty("margin");
JSValue widthSpec = jsObject.getProperty("widthSpec"); JSValue widthSpec = jsObject.getProperty("widthSpec");
@ -478,7 +505,7 @@ public abstract class ViewNode<T extends View> extends DoricContextHolder {
if (mLayoutParams.width >= 0) { if (mLayoutParams.width >= 0) {
return DoricUtils.px2dp(mLayoutParams.width); return DoricUtils.px2dp(mLayoutParams.width);
} else { } else {
return mView.getMeasuredWidth(); return DoricUtils.px2dp(mView.getMeasuredWidth());
} }
} }
@ -487,7 +514,7 @@ public abstract class ViewNode<T extends View> extends DoricContextHolder {
if (mLayoutParams.width >= 0) { if (mLayoutParams.width >= 0) {
return DoricUtils.px2dp(mLayoutParams.height); return DoricUtils.px2dp(mLayoutParams.height);
} else { } else {
return mView.getMeasuredHeight(); return DoricUtils.px2dp(mView.getMeasuredHeight());
} }
} }
@ -826,4 +853,14 @@ public abstract class ViewNode<T extends View> extends DoricContextHolder {
return 0; return 0;
} }
} }
@DoricMethod
public JSONObject getLocationOnScreen() {
int[] position = new int[2];
getNodeView().getLocationOnScreen(position);
return new JSONBuilder()
.put("x", DoricUtils.px2dp(position[0]))
.put("y", DoricUtils.px2dp(position[1]))
.toJSONObject();
}
} }

View File

@ -22,6 +22,7 @@ import android.view.ViewGroup;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
import com.github.pengfeizhou.jscore.JSArray; import com.github.pengfeizhou.jscore.JSArray;
import com.github.pengfeizhou.jscore.JSDecoder; import com.github.pengfeizhou.jscore.JSDecoder;
@ -65,15 +66,28 @@ class FlowAdapter extends RecyclerView.Adapter<FlowAdapter.DoricViewHolder> {
holder.flowLayoutItemNode.setId(jsObject.getProperty("id").asString().value()); holder.flowLayoutItemNode.setId(jsObject.getProperty("id").asString().value());
holder.flowLayoutItemNode.blend(jsObject.getProperty("props").asObject()); holder.flowLayoutItemNode.blend(jsObject.getProperty("props").asObject());
} }
if (position >= this.itemCount) {
this.flowLayoutNode.callJSResponse(this.flowLayoutNode.onLoadMoreFuncId);
StaggeredGridLayoutManager.LayoutParams layoutParams = new StaggeredGridLayoutManager.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
holder.itemView.getLayoutParams().height
);
layoutParams.setFullSpan(true);
holder.itemView.setLayoutParams(layoutParams);
}
} }
@Override @Override
public int getItemCount() { public int getItemCount() {
return itemCount; return this.itemCount + (this.flowLayoutNode.loadMore ? 1 : 0);
} }
@Override @Override
public int getItemViewType(int position) { public int getItemViewType(int position) {
if (position >= itemCount) {
return Integer.MAX_VALUE;
}
JSValue value = getItemModel(position); JSValue value = getItemModel(position);
if (value.isObject()) { if (value.isObject()) {
if (value.asObject().getProperty("identifier").isString()) { if (value.asObject().getProperty("identifier").isString()) {
@ -84,6 +98,9 @@ class FlowAdapter extends RecyclerView.Adapter<FlowAdapter.DoricViewHolder> {
} }
private JSValue getItemModel(final int position) { private JSValue getItemModel(final int position) {
if (position >= this.itemCount) {
return this.flowLayoutNode.getSubModel(this.flowLayoutNode.loadMoreViewId);
}
String id = itemValues.get(position); String id = itemValues.get(position);
if (TextUtils.isEmpty(id)) { if (TextUtils.isEmpty(id)) {
AsyncResult<JSDecoder> asyncResult = flowLayoutNode.callJSResponse( AsyncResult<JSDecoder> asyncResult = flowLayoutNode.callJSResponse(

View File

@ -41,15 +41,38 @@ public class FlowLayoutNode extends SuperNode<RecyclerView> {
private final FlowAdapter flowAdapter; private final FlowAdapter flowAdapter;
private final StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager( private final StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(
2, 2,
StaggeredGridLayoutManager.VERTICAL); StaggeredGridLayoutManager.VERTICAL) {
@Override
public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) {
try {
return super.scrollVerticallyBy(dy, recycler, state);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
@Override
public void onScrollStateChanged(int state) {
try {
super.onScrollStateChanged(state);
} catch (Exception e) {
e.printStackTrace();
}
}
};
private int columnSpace = 0; private int columnSpace = 0;
private int rowSpace = 0; private int rowSpace = 0;
private Rect padding = new Rect();
private final RecyclerView.ItemDecoration spacingItemDecoration = new RecyclerView.ItemDecoration() { private final RecyclerView.ItemDecoration spacingItemDecoration = new RecyclerView.ItemDecoration() {
@Override @Override
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
outRect.set(columnSpace / 2, rowSpace / 2, columnSpace / 2, rowSpace / 2); outRect.set(columnSpace / 2, rowSpace / 2, columnSpace / 2, rowSpace / 2);
} }
}; };
String onLoadMoreFuncId;
boolean loadMore = false;
String loadMoreViewId;
public FlowLayoutNode(DoricContext doricContext) { public FlowLayoutNode(DoricContext doricContext) {
super(doricContext); super(doricContext);
@ -80,11 +103,9 @@ public class FlowLayoutNode extends SuperNode<RecyclerView> {
switch (name) { switch (name) {
case "columnSpace": case "columnSpace":
columnSpace = DoricUtils.dp2px(prop.asNumber().toFloat()); columnSpace = DoricUtils.dp2px(prop.asNumber().toFloat());
mView.setPadding(-columnSpace / 2, mView.getPaddingTop(), -columnSpace / 2, mView.getPaddingBottom());
break; break;
case "rowSpace": case "rowSpace":
rowSpace = DoricUtils.dp2px(prop.asNumber().toFloat()); rowSpace = DoricUtils.dp2px(prop.asNumber().toFloat());
mView.setPadding(mView.getPaddingLeft(), -rowSpace / 2, mView.getPaddingRight(), -rowSpace / 2);
break; break;
case "columnCount": case "columnCount":
staggeredGridLayoutManager.setSpanCount(prop.asNumber().toInt()); staggeredGridLayoutManager.setSpanCount(prop.asNumber().toInt());
@ -93,23 +114,54 @@ public class FlowLayoutNode extends SuperNode<RecyclerView> {
this.flowAdapter.itemCount = prop.asNumber().toInt(); this.flowAdapter.itemCount = prop.asNumber().toInt();
break; break;
case "renderItem": case "renderItem":
this.flowAdapter.renderItemFuncId = prop.asString().value(); String funcId = prop.asString().value();
if (!funcId.equals(this.flowAdapter.renderItemFuncId)) {
this.flowAdapter.renderItemFuncId = funcId;
// If reset renderItem,should reset native cache. // If reset renderItem,should reset native cache.
for (int index = 0; index < this.flowAdapter.itemValues.size(); index++) {
removeSubModel(this.flowAdapter.itemValues.valueAt(index));
}
this.flowAdapter.itemValues.clear(); this.flowAdapter.itemValues.clear();
clearSubModel(); }
break; break;
case "batchCount": case "batchCount":
this.flowAdapter.batchCount = prop.asNumber().toInt(); this.flowAdapter.batchCount = prop.asNumber().toInt();
break; break;
case "onLoadMore":
this.onLoadMoreFuncId = prop.asString().value();
break;
case "loadMoreView":
this.loadMoreViewId = prop.asString().value();
break;
case "loadMore":
this.loadMore = prop.asBoolean().value();
break;
default: default:
super.blend(view, name, prop); super.blend(view, name, prop);
break; break;
} }
} }
@Override
protected void setPadding(JSObject jsObject) {
JSValue left = jsObject.getProperty("left");
JSValue right = jsObject.getProperty("right");
JSValue top = jsObject.getProperty("top");
JSValue bottom = jsObject.getProperty("bottom");
padding.left = left.isNumber() ? DoricUtils.dp2px(left.asNumber().toFloat()) : 0;
padding.top = top.isNumber() ? DoricUtils.dp2px(top.asNumber().toFloat()) : 0;
padding.right = right.isNumber() ? DoricUtils.dp2px(right.asNumber().toFloat()) : 0;
padding.bottom = bottom.isNumber() ? DoricUtils.dp2px(bottom.asNumber().toFloat()) : 0;
}
@Override @Override
public void blend(JSObject jsObject) { public void blend(JSObject jsObject) {
super.blend(jsObject); super.blend(jsObject);
mView.setPadding(
padding.left - columnSpace / 2,
padding.top - rowSpace / 2,
padding.right - columnSpace / 2,
padding.bottom - rowSpace / 2);
if (mView != null) { if (mView != null) {
mView.post(new Runnable() { mView.post(new Runnable() {
@Override @Override

View File

@ -16,7 +16,6 @@
package pub.doric.shader.list; package pub.doric.shader.list;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.SparseArray;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -40,10 +39,6 @@ import pub.doric.shader.ViewNode;
class ListAdapter extends RecyclerView.Adapter<ListAdapter.DoricViewHolder> { class ListAdapter extends RecyclerView.Adapter<ListAdapter.DoricViewHolder> {
private final ListNode listNode; private final ListNode listNode;
String renderItemFuncId;
int itemCount = 0;
int batchCount = 15;
SparseArray<String> itemValues = new SparseArray<>();
ListAdapter(ListNode listNode) { ListAdapter(ListNode listNode) {
this.listNode = listNode; this.listNode = listNode;
@ -60,22 +55,28 @@ class ListAdapter extends RecyclerView.Adapter<ListAdapter.DoricViewHolder> {
@Override @Override
public void onBindViewHolder(@NonNull DoricViewHolder holder, int position) { public void onBindViewHolder(@NonNull DoricViewHolder holder, int position) {
JSValue jsValue = getItemModel(position); JSValue jsValue = getItemModel(position);
if (jsValue.isObject()) { if (jsValue != null && jsValue.isObject()) {
JSObject jsObject = jsValue.asObject(); JSObject jsObject = jsValue.asObject();
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) {
this.listNode.callJSResponse(this.listNode.onLoadMoreFuncId);
}
} }
@Override @Override
public int getItemCount() { public int getItemCount() {
return itemCount; return this.listNode.itemCount + (this.listNode.loadMore ? 1 : 0);
} }
@Override @Override
public int getItemViewType(int position) { public int getItemViewType(int position) {
if (position >= this.listNode.itemCount) {
return Integer.MAX_VALUE;
}
JSValue value = getItemModel(position); JSValue value = getItemModel(position);
if (value.isObject()) { if (value != null && value.isObject()) {
if (value.asObject().getProperty("identifier").isString()) { if (value.asObject().getProperty("identifier").isString()) {
return value.asObject().getProperty("identifier").asString().value().hashCode(); return value.asObject().getProperty("identifier").asString().value().hashCode();
} }
@ -84,12 +85,15 @@ class ListAdapter extends RecyclerView.Adapter<ListAdapter.DoricViewHolder> {
} }
private JSValue getItemModel(final int position) { private JSValue getItemModel(final int position) {
String id = itemValues.get(position); if (position >= this.listNode.itemCount) {
return this.listNode.getSubModel(this.listNode.loadMoreViewId);
}
String id = listNode.itemValues.get(position);
if (TextUtils.isEmpty(id)) { if (TextUtils.isEmpty(id)) {
AsyncResult<JSDecoder> asyncResult = listNode.callJSResponse( AsyncResult<JSDecoder> asyncResult = listNode.callJSResponse(
"renderBunchedItems", "renderBunchedItems",
position, position,
batchCount); listNode.batchCount);
try { try {
JSDecoder jsDecoder = asyncResult.synchronous().get(); JSDecoder jsDecoder = asyncResult.synchronous().get();
JSValue result = jsDecoder.decode(); JSValue result = jsDecoder.decode();
@ -98,10 +102,10 @@ class ListAdapter extends RecyclerView.Adapter<ListAdapter.DoricViewHolder> {
for (int i = 0; i < jsArray.size(); i++) { for (int i = 0; i < jsArray.size(); i++) {
JSObject itemModel = jsArray.get(i).asObject(); JSObject itemModel = jsArray.get(i).asObject();
String itemId = itemModel.getProperty("id").asString().value(); String itemId = itemModel.getProperty("id").asString().value();
itemValues.put(i + position, itemId); listNode.itemValues.put(i + position, itemId);
listNode.setSubModel(itemId, itemModel); listNode.setSubModel(itemId, itemModel);
} }
return listNode.getSubModel(itemValues.get(position)); return listNode.getSubModel(listNode.itemValues.get(position));
} }
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
@ -119,8 +123,8 @@ class ListAdapter extends RecyclerView.Adapter<ListAdapter.DoricViewHolder> {
void blendSubNode(JSObject subProperties) { void blendSubNode(JSObject subProperties) {
for (int i = 0; i < itemValues.size(); i++) { for (int i = 0; i < listNode.itemValues.size(); i++) {
if (subProperties.getProperty("id").asString().value().equals(itemValues.valueAt(i))) { if (subProperties.getProperty("id").asString().value().equals(listNode.itemValues.valueAt(i))) {
notifyItemChanged(i); notifyItemChanged(i);
} }
} }

View File

@ -15,6 +15,7 @@
*/ */
package pub.doric.shader.list; package pub.doric.shader.list;
import android.util.SparseArray;
import android.view.View; import android.view.View;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
@ -36,6 +37,13 @@ import pub.doric.shader.ViewNode;
@DoricPlugin(name = "List") @DoricPlugin(name = "List")
public class ListNode extends SuperNode<RecyclerView> { public class ListNode extends SuperNode<RecyclerView> {
private final ListAdapter listAdapter; private final ListAdapter listAdapter;
private String renderItemFuncId;
String onLoadMoreFuncId;
int itemCount = 0;
int batchCount = 15;
SparseArray<String> itemValues = new SparseArray<>();
boolean loadMore = false;
String loadMoreViewId;
public ListNode(DoricContext doricContext) { public ListNode(DoricContext doricContext) {
super(doricContext); super(doricContext);
@ -82,16 +90,30 @@ public class ListNode extends SuperNode<RecyclerView> {
protected void blend(RecyclerView view, String name, JSValue prop) { protected void blend(RecyclerView view, String name, JSValue prop) {
switch (name) { switch (name) {
case "itemCount": case "itemCount":
this.listAdapter.itemCount = prop.asNumber().toInt(); this.itemCount = prop.asNumber().toInt();
break; break;
case "renderItem": case "renderItem":
this.listAdapter.renderItemFuncId = prop.asString().value(); String funcId = prop.asString().value();
if (!funcId.equals(this.renderItemFuncId)) {
this.renderItemFuncId = funcId;
// If reset renderItem,should reset native cache. // If reset renderItem,should reset native cache.
this.listAdapter.itemValues.clear(); for (int index = 0; index < this.itemValues.size(); index++) {
clearSubModel(); removeSubModel(this.itemValues.valueAt(index));
}
this.itemValues.clear();
}
break;
case "onLoadMore":
this.onLoadMoreFuncId = prop.asString().value();
break;
case "loadMoreView":
this.loadMoreViewId = prop.asString().value();
break; break;
case "batchCount": case "batchCount":
this.listAdapter.batchCount = prop.asNumber().toInt(); this.batchCount = prop.asNumber().toInt();
break;
case "loadMore":
this.loadMore = prop.asBoolean().value();
break; break;
default: default:
super.blend(view, name, prop); super.blend(view, name, prop);

View File

@ -0,0 +1,207 @@
/*
* 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.shader.slider;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
import com.github.pengfeizhou.jscore.JSObject;
import com.github.pengfeizhou.jscore.JSValue;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
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.GroupNode;
import pub.doric.shader.ViewNode;
/**
* @Description: pub.doric.shader.slider
* @Author: pengfei.zhou
* @CreateDate: 2019-12-07
*/
@DoricPlugin(name = "NestedSlider")
public class NestedSliderNode extends GroupNode<ViewPager> implements ViewPager.OnPageChangeListener {
private ArrayList<View> slideItems = new ArrayList<>();
private String onPageSlidedFuncId;
public NestedSliderNode(DoricContext doricContext) {
super(doricContext);
}
@Override
protected ViewPager build() {
ViewPager viewPager = new ViewPager(getContext());
viewPager.setAdapter(new PagerAdapter() {
@Override
public int getCount() {
return slideItems.size();
}
@Override
public boolean isViewFromObject(@NonNull View view, @NotNull Object object) {
return view == object;
}
@Override
public void destroyItem(@NotNull ViewGroup container, int position, @NotNull Object object) {
container.removeView(slideItems.get(position));
}
@NotNull
@Override
public Object instantiateItem(@NotNull ViewGroup container, int position) {
container.addView(slideItems.get(position), 0);
return slideItems.get(position);
}
});
viewPager.addOnPageChangeListener(this);
return viewPager;
}
@Override
protected void blend(ViewPager view, String name, JSValue prop) {
switch (name) {
case "onPageSlided":
this.onPageSlidedFuncId = prop.asString().toString();
break;
default:
super.blend(view, name, prop);
break;
}
}
@Override
protected void configChildNode() {
for (int idx = 0; idx < mChildViewIds.size(); idx++) {
String id = mChildViewIds.get(idx);
JSObject model = getSubModel(id);
String type = model.getProperty("type").asString().value();
if (idx < mChildNodes.size()) {
ViewNode oldNode = mChildNodes.get(idx);
if (id.equals(oldNode.getId())) {
//The same,skip
} else {
if (mReusable) {
if (oldNode.getType().equals(type)) {
//Same type,can be reused
oldNode.setId(id);
oldNode.blend(model.getProperty("props").asObject());
} else {
//Replace this view
mChildNodes.remove(idx);
slideItems.remove(oldNode.getNodeView());
ViewNode newNode = ViewNode.create(getDoricContext(), type);
newNode.setId(id);
newNode.init(this);
newNode.blend(model.getProperty("props").asObject());
mChildNodes.add(idx, newNode);
slideItems.add(idx, newNode.getNodeView());
}
} else {
//Find in remain nodes
int position = -1;
for (int start = idx + 1; start < mChildNodes.size(); start++) {
ViewNode node = mChildNodes.get(start);
if (id.equals(node.getId())) {
//Found
position = start;
break;
}
}
if (position >= 0) {
//Found swap idx,position
ViewNode reused = mChildNodes.remove(position);
ViewNode abandoned = mChildNodes.remove(idx);
mChildNodes.set(idx, reused);
mChildNodes.set(position, abandoned);
//View swap index
slideItems.remove(reused.getNodeView());
slideItems.add(idx, reused.getNodeView());
slideItems.remove(abandoned.getNodeView());
slideItems.add(position, abandoned.getNodeView());
} else {
//Not found,insert
ViewNode newNode = ViewNode.create(getDoricContext(), type);
newNode.setId(id);
newNode.init(this);
newNode.blend(model.getProperty("props").asObject());
mChildNodes.add(idx, newNode);
slideItems.add(idx, newNode.getNodeView());
}
}
}
} else {
//Insert
ViewNode newNode = ViewNode.create(getDoricContext(), type);
newNode.setId(id);
newNode.init(this);
newNode.blend(model.getProperty("props").asObject());
mChildNodes.add(newNode);
slideItems.add(idx, newNode.getNodeView());
}
}
int size = mChildNodes.size();
for (int idx = mChildViewIds.size(); idx < size; idx++) {
ViewNode viewNode = mChildNodes.remove(mChildViewIds.size());
slideItems.remove(viewNode.getNodeView());
}
mView.getAdapter().notifyDataSetChanged();
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
if (!TextUtils.isEmpty(onPageSlidedFuncId)) {
callJSResponse(onPageSlidedFuncId, position);
}
}
@Override
public void onPageScrollStateChanged(int state) {
}
@DoricMethod
public void slidePage(JSObject params, DoricPromise promise) {
int page = params.getProperty("page").asNumber().toInt();
boolean smooth = params.getProperty("smooth").asBoolean().value();
mView.setCurrentItem(page, smooth);
if (!TextUtils.isEmpty(onPageSlidedFuncId)) {
callJSResponse(onPageSlidedFuncId, page);
}
promise.resolve();
}
@DoricMethod
public int getSlidedPage() {
return mView.getCurrentItem();
}
}

View File

@ -43,7 +43,7 @@ class SlideAdapter extends RecyclerView.Adapter<SlideAdapter.DoricViewHolder> {
int itemCount = 0; int itemCount = 0;
int batchCount = 3; int batchCount = 3;
SparseArray<String> itemValues = new SparseArray<>(); SparseArray<String> itemValues = new SparseArray<>();
String renderPageFuncId;
SlideAdapter(SliderNode sliderNode) { SlideAdapter(SliderNode sliderNode) {
this.sliderNode = sliderNode; this.sliderNode = sliderNode;
} }

View File

@ -15,6 +15,7 @@
*/ */
package pub.doric.shader.slider; package pub.doric.shader.slider;
import android.view.ViewGroup;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import com.github.pengfeizhou.jscore.JSObject; import com.github.pengfeizhou.jscore.JSObject;
@ -50,7 +51,7 @@ public class SlideItemNode extends StackNode {
@Override @Override
public void blend(JSObject jsObject) { public void blend(JSObject jsObject) {
super.blend(jsObject); super.blend(jsObject);
getNodeView().getLayoutParams().width = getLayoutParams().width; getNodeView().getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT;
getNodeView().getLayoutParams().height = getLayoutParams().height; getNodeView().getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;
} }
} }

View File

@ -15,8 +15,10 @@
*/ */
package pub.doric.shader.slider; package pub.doric.shader.slider;
import android.text.TextUtils;
import android.view.View; import android.view.View;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.PagerSnapHelper; import androidx.recyclerview.widget.PagerSnapHelper;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
@ -25,7 +27,9 @@ import com.github.pengfeizhou.jscore.JSObject;
import com.github.pengfeizhou.jscore.JSValue; import com.github.pengfeizhou.jscore.JSValue;
import pub.doric.DoricContext; import pub.doric.DoricContext;
import pub.doric.extension.bridge.DoricMethod;
import pub.doric.extension.bridge.DoricPlugin; import pub.doric.extension.bridge.DoricPlugin;
import pub.doric.extension.bridge.DoricPromise;
import pub.doric.shader.SuperNode; import pub.doric.shader.SuperNode;
import pub.doric.shader.ViewNode; import pub.doric.shader.ViewNode;
@ -37,6 +41,8 @@ import pub.doric.shader.ViewNode;
@DoricPlugin(name = "Slider") @DoricPlugin(name = "Slider")
public class SliderNode extends SuperNode<RecyclerView> { public class SliderNode extends SuperNode<RecyclerView> {
private final SlideAdapter slideAdapter; private final SlideAdapter slideAdapter;
private String onPageSlidedFuncId;
private int lastPosition = 0;
public SliderNode(DoricContext doricContext) { public SliderNode(DoricContext doricContext) {
super(doricContext); super(doricContext);
@ -47,12 +53,32 @@ public class SliderNode extends SuperNode<RecyclerView> {
protected RecyclerView build() { protected RecyclerView build() {
RecyclerView recyclerView = new RecyclerView(getContext()); RecyclerView recyclerView = new RecyclerView(getContext());
LinearLayoutManager layoutManager = new LinearLayoutManager(getContext()); final LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
recyclerView.setLayoutManager(layoutManager); recyclerView.setLayoutManager(layoutManager);
PagerSnapHelper mPagerSnapHelper = new PagerSnapHelper(); final PagerSnapHelper snapHelper = new PagerSnapHelper();
mPagerSnapHelper.attachToRecyclerView(recyclerView); snapHelper.attachToRecyclerView(recyclerView);
recyclerView.setAdapter(this.slideAdapter); recyclerView.setAdapter(this.slideAdapter);
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
View view = snapHelper.findSnapView(layoutManager);
if (view != null && !TextUtils.isEmpty(onPageSlidedFuncId)) {
int position = layoutManager.getPosition(view);
if (position != lastPosition) {
callJSResponse(onPageSlidedFuncId, position);
}
lastPosition = position;
}
}
}
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
}
});
return recyclerView; return recyclerView;
} }
@ -109,17 +135,46 @@ public class SliderNode extends SuperNode<RecyclerView> {
case "itemCount": case "itemCount":
this.slideAdapter.itemCount = prop.asNumber().toInt(); this.slideAdapter.itemCount = prop.asNumber().toInt();
break; break;
case "renderItem": case "renderPage":
// If reset renderItem,should reset native cache. // If reset renderItem,should reset native cache.
String funcId = prop.asString().value();
if (!funcId.equals(this.slideAdapter.renderPageFuncId)) {
this.slideAdapter.itemValues.clear(); this.slideAdapter.itemValues.clear();
clearSubModel(); clearSubModel();
this.slideAdapter.renderPageFuncId = funcId;
}
break; break;
case "batchCount": case "batchCount":
this.slideAdapter.batchCount = prop.asNumber().toInt(); this.slideAdapter.batchCount = prop.asNumber().toInt();
break; break;
case "onPageSlided":
this.onPageSlidedFuncId = prop.asString().toString();
break;
default: default:
super.blend(view, name, prop); super.blend(view, name, prop);
break; break;
} }
} }
@DoricMethod
public void slidePage(JSObject params, DoricPromise promise) {
int page = params.getProperty("page").asNumber().toInt();
boolean smooth = params.getProperty("smooth").asBoolean().value();
if (smooth) {
mView.smoothScrollToPosition(page);
} else {
mView.scrollToPosition(page);
}
if (!TextUtils.isEmpty(onPageSlidedFuncId)) {
callJSResponse(onPageSlidedFuncId, page);
lastPosition = page;
}
promise.resolve();
}
@DoricMethod
public int getSlidedPage() {
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) mView.getLayoutManager();
return linearLayoutManager != null ? linearLayoutManager.findFirstVisibleItemPosition() : 0;
}
} }

View File

@ -26,6 +26,8 @@ public class DoricConstant {
public static final String DORIC_MODULE_LIB = "doric"; public static final String DORIC_MODULE_LIB = "doric";
public static final String INJECT_ENVIRONMENT = "Environment";
public static final String INJECT_LOG = "nativeLog"; public static final String INJECT_LOG = "nativeLog";
public static final String INJECT_REQUIRE = "nativeRequire"; public static final String INJECT_REQUIRE = "nativeRequire";
public static final String INJECT_TIMER_SET = "nativeSetTimer"; public static final String INJECT_TIMER_SET = "nativeSetTimer";

View File

@ -669,6 +669,11 @@ public class HVScrollView extends FrameLayout implements NestedScrollingParent,
super.requestDisallowInterceptTouchEvent(disallowIntercept); super.requestDisallowInterceptTouchEvent(disallowIntercept);
} }
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
return super.dispatchTouchEvent(ev);
}
@Override @Override
public boolean onInterceptTouchEvent(MotionEvent ev) { public boolean onInterceptTouchEvent(MotionEvent ev) {
/* /*
@ -715,8 +720,12 @@ public class HVScrollView extends FrameLayout implements NestedScrollingParent,
final int y = (int) ev.getY(pointerIndex); final int y = (int) ev.getY(pointerIndex);
final int xDiff = Math.abs(x - mLastMotionX); final int xDiff = Math.abs(x - mLastMotionX);
final int yDiff = Math.abs(y - mLastMotionY); final int yDiff = Math.abs(y - mLastMotionY);
if ((xDiff > mTouchSlop && (getNestedScrollAxes() & ViewCompat.SCROLL_AXIS_HORIZONTAL) == 0) if ((xDiff > mTouchSlop
|| (yDiff > mTouchSlop && (getNestedScrollAxes() & ViewCompat.SCROLL_AXIS_VERTICAL) == 0)) { && (getNestedScrollAxes() & ViewCompat.SCROLL_AXIS_HORIZONTAL) == 0
&& canScrollHorizontally())
|| (yDiff > mTouchSlop
&& (getNestedScrollAxes() & ViewCompat.SCROLL_AXIS_VERTICAL) == 0
&& canScrollVertically())) {
mIsBeingDragged = true; mIsBeingDragged = true;
mLastMotionX = x; mLastMotionX = x;
mLastMotionY = y; mLastMotionY = y;

View File

@ -1,7 +1,21 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent"
android:orientation="vertical">
</FrameLayout> <pub.doric.navbar.BaseDoricNavBar
android:id="@+id/doric_nav_bar"
android:layout_width="match_parent"
android:layout_height="44dp" />
<fragment
android:id="@+id/nav_host"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/doric_navigation" />
</LinearLayout>

View File

@ -1,18 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <pub.doric.DoricPanel xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/doric_panel"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<pub.doric.DoricPanel </pub.doric.DoricPanel>
android:id="@+id/doric_panel"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"
android:layout_marginTop="44dp" />
<pub.doric.navbar.BaseDoricNavBar
android:id="@+id/doric_nav_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</FrameLayout>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/doric_navigation"
app:startDestination="@id/doricPanelFragment">
<fragment
android:id="@+id/doricPanelFragment"
android:name="pub.doric.DoricPanelFragment"
android:label="DoricPanelFragment">
<action
android:id="@+id/action_doricPanelFragment_to_doricPanelFragment"
app:destination="@id/doricPanelFragment" />
</fragment>
</navigation>

View File

@ -0,0 +1,2 @@
git=https://github.com/doric-pub/doric
site=https://github.com/doric-pub/doric

View File

@ -0,0 +1,39 @@
apply plugin: 'maven'
Properties properties = new Properties()
properties.load(project.rootProject.file('scripts/maven.properties').newDataInputStream())
properties.load(new FileInputStream("${projectDir}/pom.properties"))
properties.load(project.rootProject.file('local.properties').newDataInputStream())
apply plugin: 'maven'
uploadArchives {
repositories {
mavenDeployer {
pom.groupId = properties.groupId
pom.artifactId = properties.artifactId
pom.version = rootProject.ext.Version
pom.project {
description 'git rev-parse HEAD'.execute([], projectDir).text.trim()
}
repository(url: properties.releasesRepository + properties.name) {
authentication(userName: properties.user, password: properties.apiKey)
}
}
}
}
task uploadAar {
dependsOn clean, uploadArchives
}
//task androidSourcesJar(type: Jar) {
// classifier = "sources"
// from android.sourceSets.main.java.sourceFiles
//}
//
//artifacts {
// archives androidSourcesJar
//}

View File

@ -0,0 +1 @@
version=0.1.2