├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── lychee │ │ └── controllerview │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── lychee │ │ │ └── controllerview │ │ │ ├── DemoActivity.java │ │ │ ├── DemoApplication.java │ │ │ └── controllerView │ │ │ ├── AssertUtil.java │ │ │ ├── Controller.java │ │ │ ├── ControllerChange.java │ │ │ ├── ControllerView.java │ │ │ ├── ControllerViewActivity.java │ │ │ ├── ControllerViewFragment.java │ │ │ └── WXAnalyzerDelegate.java │ └── res │ │ ├── layout │ │ ├── activity_controller.xml │ │ ├── activity_controller_weex.xml │ │ ├── activity_splash.xml │ │ ├── fragment_controller.xml │ │ └── fragment_controller_weex.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── lychee │ └── controllerview │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── vue ├── controller.vue ├── fragment1.vue ├── fragment2.vue └── fragment3.vue /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | .idea 9 | /captures 10 | .externalNativeBuild 11 | 将删除 app/libs/ 12 | 将删除 app/src/main/res/drawable/ 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # **DEMO使用** 2 | **本项目假设您有一定基础的原生开发经验** 3 | 4 | # **新特性** 5 | >0.1.0:单页支持最多10个标签., 6 | 使用方式依然为定义`tag`, `lychee1`,`lychee2` ... 7 | 没有**`lychee0`**! 8 | 9 | 提供了 10 | ``` 11 | 12 | ``` 13 | 标签来将vue页面作为Android里的fragment组件灵活配置使用, 14 | 通过动态改变src的值来改变展现的页面内容 15 | 16 | **编译工程之前请先确认** 17 | ``` 18 | Gradle版本:gradle-3.3-all.zip 19 | AS Grable插件:com.android.tools.build:gradle:2.3.1 20 | ``` 21 | 22 | 完成之后打开 23 | ``` 24 | /vue 25 | ``` 26 | 找到 controller.vue 文件 27 | 修改 `_this.src` 指向的 `*.js` 为你需要展示的页面文件路径 28 | ``` 29 | case 1: 30 | _this.src = '编译成*.js的子页面文件路径'; 31 | break; 32 | ``` 33 | (本demo提供了3个内容稍有不同的 `fragmentX.vue` 以供编译) 34 | 35 | 最后将编写好的`controller.vue`编译生成的`*.js`文件作为项目入口路径配置到 36 | ``` 37 | @Override 38 | public void startLoad() { 39 | renderPageByURL("http://192.168.0.119:8080/dist/app.weex.js"); 40 | } 41 | ``` 42 | 43 | 一切配置妥当,就运行项目吧! 44 | 45 | ### 如需单独使用该activity,只需要继承ControllerViewActivity就行 46 | 47 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 25 5 | buildToolsVersion "25.0.2" 6 | defaultConfig { 7 | applicationId "com.lychee.controllerview" 8 | minSdkVersion 16 9 | targetSdkVersion 25 10 | versionCode 1 11 | versionName "1.0" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | compile fileTree(dir: 'libs', include: ['*.jar']) 23 | //official 24 | compile 'com.android.support:support-annotations:25.3.0' 25 | compile 'com.android.support:recyclerview-v7:25.3.0' 26 | compile 'com.android.support:support-v4:25.3.0' 27 | compile 'com.android.support:appcompat-v7:25.3.0' 28 | compile 'com.android.support:design:25.3.0' 29 | //extra 30 | compile 'com.jakewharton:butterknife:8.5.1' 31 | annotationProcessor 'com.jakewharton:butterknife-compiler:8.5.1' 32 | compile 'org.greenrobot:eventbus:3.0.0' 33 | //ali 34 | compile 'com.alibaba:fastjson:1.1.46.android' 35 | compile 'com.taobao.android:weex_sdk:0.11.0' 36 | compile 'com.taobao.android:weex_inspector:0.10.0.5' 37 | compile 'com.aliyun.ams:alicloud-android-ut:5.0.0' 38 | compile 'com.taobao.android.weex_inspection:protocol:1.0.2' 39 | compile 'com.taobao.android:weex_analyzer:0.1.0.5' 40 | //rx 41 | compile 'io.reactivex.rxjava2:rxandroid:2.0.1' 42 | compile 'io.reactivex.rxjava2:rxjava:2.0.1' 43 | } 44 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /home/lychee/android/android-sdk-linux/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/lychee/controllerview/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.lychee.controllerview; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumentation test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.lychee.controllerview", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/lychee/controllerview/DemoActivity.java: -------------------------------------------------------------------------------- 1 | package com.lychee.controllerview; 2 | 3 | import com.lychee.controllerview.controllerView.ControllerViewActivity; 4 | 5 | /** 6 | * Created by lychee on 17-4-25. 7 | */ 8 | 9 | public class DemoActivity extends ControllerViewActivity { 10 | @Override 11 | public void startLoad() { 12 | renderPageByURL("http://192.168.0.119:8080/dist/app.weex.js"); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/lychee/controllerview/DemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.lychee.controllerview; 2 | 3 | import android.app.Application; 4 | 5 | import com.lychee.controllerview.controllerView.Controller; 6 | import com.taobao.weex.InitConfig; 7 | import com.taobao.weex.WXSDKEngine; 8 | import com.taobao.weex.common.WXException; 9 | 10 | /** 11 | * Created by lychee on 17-2-21. 12 | */ 13 | 14 | public class DemoApplication extends Application { 15 | 16 | 17 | @Override 18 | public void onCreate() { 19 | super.onCreate(); 20 | initWeex(); 21 | } 22 | 23 | 24 | private void initWeex() { 25 | InitConfig config = new InitConfig.Builder() 26 | .build(); 27 | WXSDKEngine.initialize(this, config); 28 | try { 29 | WXSDKEngine.registerComponent("controller", Controller.class); 30 | } catch (WXException e) { 31 | e.printStackTrace(); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/lychee/controllerview/controllerView/AssertUtil.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Apache License 4 | * Version 2.0, January 2004 5 | * http://www.apache.org/licenses/ 6 | * 7 | * TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 8 | * 9 | * 1. Definitions. 10 | * 11 | * "License" shall mean the terms and conditions for use, reproduction, 12 | * and distribution as defined by Sections 1 through 9 of this document. 13 | * 14 | * "Licensor" shall mean the copyright owner or entity authorized by 15 | * the copyright owner that is granting the License. 16 | * 17 | * "Legal Entity" shall mean the union of the acting entity and all 18 | * other entities that control, are controlled by, or are under common 19 | * control with that entity. For the purposes of this definition, 20 | * "control" means (i) the power, direct or indirect, to cause the 21 | * direction or management of such entity, whether by contract or 22 | * otherwise, or (ii) ownership of fifty percent (50%) or more of the 23 | * outstanding shares, or (iii) beneficial ownership of such entity. 24 | * 25 | * "You" (or "Your") shall mean an individual or Legal Entity 26 | * exercising permissions granted by this License. 27 | * 28 | * "Source" form shall mean the preferred form for making modifications, 29 | * including but not limited to software source code, documentation 30 | * source, and configuration files. 31 | * 32 | * "Object" form shall mean any form resulting from mechanical 33 | * transformation or translation of a Source form, including but 34 | * not limited to compiled object code, generated documentation, 35 | * and conversions to other media types. 36 | * 37 | * "Work" shall mean the work of authorship, whether in Source or 38 | * Object form, made available under the License, as indicated by a 39 | * copyright notice that is included in or attached to the work 40 | * (an example is provided in the Appendix below). 41 | * 42 | * "Derivative Works" shall mean any work, whether in Source or Object 43 | * form, that is based on (or derived from) the Work and for which the 44 | * editorial revisions, annotations, elaborations, or other modifications 45 | * represent, as a whole, an original work of authorship. For the purposes 46 | * of this License, Derivative Works shall not include works that remain 47 | * separable from, or merely link (or bind by name) to the interfaces of, 48 | * the Work and Derivative Works thereof. 49 | * 50 | * "Contribution" shall mean any work of authorship, including 51 | * the original version of the Work and any modifications or additions 52 | * to that Work or Derivative Works thereof, that is intentionally 53 | * submitted to Licensor for inclusion in the Work by the copyright owner 54 | * or by an individual or Legal Entity authorized to submit on behalf of 55 | * the copyright owner. For the purposes of this definition, "submitted" 56 | * means any form of electronic, verbal, or written communication sent 57 | * to the Licensor or its representatives, including but not limited to 58 | * communication on electronic mailing lists, source code control systems, 59 | * and issue tracking systems that are managed by, or on behalf of, the 60 | * Licensor for the purpose of discussing and improving the Work, but 61 | * excluding communication that is conspicuously marked or otherwise 62 | * designated in writing by the copyright owner as "Not a Contribution." 63 | * 64 | * "Contributor" shall mean Licensor and any individual or Legal Entity 65 | * on behalf of whom a Contribution has been received by Licensor and 66 | * subsequently incorporated within the Work. 67 | * 68 | * 2. Grant of Copyright License. Subject to the terms and conditions of 69 | * this License, each Contributor hereby grants to You a perpetual, 70 | * worldwide, non-exclusive, no-charge, royalty-free, irrevocable 71 | * copyright license to reproduce, prepare Derivative Works of, 72 | * publicly display, publicly perform, sublicense, and distribute the 73 | * Work and such Derivative Works in Source or Object form. 74 | * 75 | * 3. Grant of Patent License. Subject to the terms and conditions of 76 | * this License, each Contributor hereby grants to You a perpetual, 77 | * worldwide, non-exclusive, no-charge, royalty-free, irrevocable 78 | * (except as stated in this section) patent license to make, have made, 79 | * use, offer to sell, sell, import, and otherwise transfer the Work, 80 | * where such license applies only to those patent claims licensable 81 | * by such Contributor that are necessarily infringed by their 82 | * Contribution(s) alone or by combination of their Contribution(s) 83 | * with the Work to which such Contribution(s) was submitted. If You 84 | * institute patent litigation against any entity (including a 85 | * cross-claim or counterclaim in a lawsuit) alleging that the Work 86 | * or a Contribution incorporated within the Work constitutes direct 87 | * or contributory patent infringement, then any patent licenses 88 | * granted to You under this License for that Work shall terminate 89 | * as of the date such litigation is filed. 90 | * 91 | * 4. Redistribution. You may reproduce and distribute copies of the 92 | * Work or Derivative Works thereof in any medium, with or without 93 | * modifications, and in Source or Object form, provided that You 94 | * meet the following conditions: 95 | * 96 | * (a) You must give any other recipients of the Work or 97 | * Derivative Works a copy of this License; and 98 | * 99 | * (b) You must cause any modified files to carry prominent notices 100 | * stating that You changed the files; and 101 | * 102 | * (c) You must retain, in the Source form of any Derivative Works 103 | * that You distribute, all copyright, patent, trademark, and 104 | * attribution notices from the Source form of the Work, 105 | * excluding those notices that do not pertain to any part of 106 | * the Derivative Works; and 107 | * 108 | * (d) If the Work includes a "NOTICE" text file as part of its 109 | * distribution, then any Derivative Works that You distribute must 110 | * include a readable copy of the attribution notices contained 111 | * within such NOTICE file, excluding those notices that do not 112 | * pertain to any part of the Derivative Works, in at least one 113 | * of the following places: within a NOTICE text file distributed 114 | * as part of the Derivative Works; within the Source form or 115 | * documentation, if provided along with the Derivative Works; or, 116 | * within a display generated by the Derivative Works, if and 117 | * wherever such third-party notices normally appear. The contents 118 | * of the NOTICE file are for informational purposes only and 119 | * do not modify the License. You may add Your own attribution 120 | * notices within Derivative Works that You distribute, alongside 121 | * or as an addendum to the NOTICE text from the Work, provided 122 | * that such additional attribution notices cannot be construed 123 | * as modifying the License. 124 | * 125 | * You may add Your own copyright statement to Your modifications and 126 | * may provide additional or different license terms and conditions 127 | * for use, reproduction, or distribution of Your modifications, or 128 | * for any such Derivative Works as a whole, provided Your use, 129 | * reproduction, and distribution of the Work otherwise complies with 130 | * the conditions stated in this License. 131 | * 132 | * 5. Submission of Contributions. Unless You explicitly state otherwise, 133 | * any Contribution intentionally submitted for inclusion in the Work 134 | * by You to the Licensor shall be under the terms and conditions of 135 | * this License, without any additional terms or conditions. 136 | * Notwithstanding the above, nothing herein shall supersede or modify 137 | * the terms of any separate license agreement you may have executed 138 | * with Licensor regarding such Contributions. 139 | * 140 | * 6. Trademarks. This License does not grant permission to use the trade 141 | * names, trademarks, service marks, or product names of the Licensor, 142 | * except as required for reasonable and customary use in describing the 143 | * origin of the Work and reproducing the content of the NOTICE file. 144 | * 145 | * 7. Disclaimer of Warranty. Unless required by applicable law or 146 | * agreed to in writing, Licensor provides the Work (and each 147 | * Contributor provides its Contributions) on an "AS IS" BASIS, 148 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 149 | * implied, including, without limitation, any warranties or conditions 150 | * of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 151 | * PARTICULAR PURPOSE. You are solely responsible for determining the 152 | * appropriateness of using or redistributing the Work and assume any 153 | * risks associated with Your exercise of permissions under this License. 154 | * 155 | * 8. Limitation of Liability. In no event and under no legal theory, 156 | * whether in tort (including negligence), contract, or otherwise, 157 | * unless required by applicable law (such as deliberate and grossly 158 | * negligent acts) or agreed to in writing, shall any Contributor be 159 | * liable to You for damages, including any direct, indirect, special, 160 | * incidental, or consequential damages of any character arising as a 161 | * result of this License or out of the use or inability to use the 162 | * Work (including but not limited to damages for loss of goodwill, 163 | * work stoppage, computer FAILURE or malfunction, or any and all 164 | * other commercial damages or losses), even if such Contributor 165 | * has been advised of the possibility of such damages. 166 | * 167 | * 9. Accepting Warranty or Additional Liability. While redistributing 168 | * the Work or Derivative Works thereof, You may choose to offer, 169 | * and charge a fee for, acceptance of support, warranty, indemnity, 170 | * or other liability obligations and/or rights consistent with this 171 | * License. However, in accepting such obligations, You may act only 172 | * on Your own behalf and on Your sole responsibility, not on behalf 173 | * of any other Contributor, and only if You agree to indemnify, 174 | * defend, and hold each Contributor harmless for any liability 175 | * incurred by, or claims asserted against, such Contributor by reason 176 | * of your accepting any such warranty or additional liability. 177 | * 178 | * END OF TERMS AND CONDITIONS 179 | * 180 | * APPENDIX: How to apply the Apache License to your work. 181 | * 182 | * To apply the Apache License to your work, attach the following 183 | * boilerplate notice, with the fields enclosed by brackets "[]" 184 | * replaced with your own identifying information. (Don't include 185 | * the brackets!) The text should be enclosed in the appropriate 186 | * comment syntax for the file format. We also recommend that a 187 | * file or class name and description of purpose be included on the 188 | * same "printed page" as the copyright notice for easier 189 | * identification within third-party archives. 190 | * 191 | * Copyright 2016 Alibaba Group 192 | * 193 | * Licensed under the Apache License, Version 2.0 (the "License"); 194 | * you may not use this file except in compliance with the License. 195 | * You may obtain a copy of the License at 196 | * 197 | * http://www.apache.org/licenses/LICENSE-2.0 198 | * 199 | * Unless required by applicable law or agreed to in writing, software 200 | * distributed under the License is distributed on an "AS IS" BASIS, 201 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 202 | * See the License for the specific language governing permissions and 203 | * limitations under the License. 204 | */ 205 | package com.lychee.controllerview.controllerView; 206 | 207 | /** 208 | * Created by sospartan on 5/31/16. 209 | */ 210 | public class AssertUtil { 211 | public static void throwIfNull(Object object, T e) throws T { 212 | if(object == null){ 213 | throw e; 214 | } 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /app/src/main/java/com/lychee/controllerview/controllerView/Controller.java: -------------------------------------------------------------------------------- 1 | package com.lychee.controllerview.controllerView; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.NonNull; 5 | import android.view.View; 6 | 7 | import com.taobao.weex.WXSDKInstance; 8 | import com.taobao.weex.dom.WXDomObject; 9 | import com.taobao.weex.ui.component.WXComponent; 10 | import com.taobao.weex.ui.component.WXComponentProp; 11 | import com.taobao.weex.ui.component.WXVContainer; 12 | 13 | import org.greenrobot.eventbus.EventBus; 14 | 15 | 16 | /** 17 | * Created by lychee on 17-4-5. 18 | */ 19 | 20 | public class Controller extends WXComponent { 21 | private String instanceId; 22 | private String tag; 23 | 24 | public Controller(WXSDKInstance instance, WXDomObject dom, WXVContainer parent) { 25 | super(instance, dom, parent); 26 | this.instanceId = instance.getInstanceId(); 27 | } 28 | 29 | @Override 30 | protected View initComponentHostView(@NonNull Context context) { 31 | ControllerView view = new ControllerView(context); 32 | view.setHostId(instanceId); 33 | return view; 34 | } 35 | 36 | @WXComponentProp(name = "src") 37 | public void setSrc(String src) { 38 | ControllerView cv = (ControllerView) getRealView(); 39 | cv.setUrl(src); 40 | EventBus.getDefault().post(new ControllerChange(src, cv.getHostId(), tag)); 41 | } 42 | 43 | 44 | //此tag必须为 "lychee" 45 | @WXComponentProp(name = "tag") 46 | public void setTag(String tag) { 47 | ControllerView cv = (ControllerView) getRealView(); 48 | cv.setTag(tag); 49 | this.tag = tag; 50 | } 51 | 52 | 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/java/com/lychee/controllerview/controllerView/ControllerChange.java: -------------------------------------------------------------------------------- 1 | package com.lychee.controllerview.controllerView; 2 | 3 | 4 | /** 5 | * Created by lychee on 17-4-6. 6 | */ 7 | 8 | public class ControllerChange { 9 | private String url; 10 | private String hostId; 11 | private String tag; 12 | 13 | public ControllerChange(String url, String hostId, String tag) { 14 | this.url = url; 15 | this.hostId = hostId; 16 | this.tag = tag; 17 | } 18 | 19 | public String getUrl() { 20 | return url; 21 | } 22 | 23 | 24 | public String getHostId() { 25 | return hostId; 26 | } 27 | 28 | public String getTag() { 29 | return tag; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/java/com/lychee/controllerview/controllerView/ControllerView.java: -------------------------------------------------------------------------------- 1 | package com.lychee.controllerview.controllerView; 2 | 3 | import android.annotation.TargetApi; 4 | import android.content.Context; 5 | import android.os.Build; 6 | import android.support.annotation.AttrRes; 7 | import android.support.annotation.NonNull; 8 | import android.support.annotation.Nullable; 9 | import android.support.annotation.StyleRes; 10 | import android.util.AttributeSet; 11 | import android.widget.FrameLayout; 12 | 13 | /** 14 | * Created by lychee on 17-4-6. 15 | */ 16 | 17 | public class ControllerView extends FrameLayout { 18 | private String url; 19 | private String hostId; 20 | public final static String TAG = "lychee";//前端页面需要定义的tag 21 | 22 | public ControllerView(@NonNull Context context) { 23 | super(context); 24 | } 25 | 26 | public ControllerView(@NonNull Context context, @Nullable AttributeSet attrs) { 27 | super(context, attrs); 28 | } 29 | 30 | public ControllerView(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { 31 | super(context, attrs, defStyleAttr); 32 | } 33 | 34 | @TargetApi(Build.VERSION_CODES.LOLLIPOP) 35 | public ControllerView(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr, @StyleRes int defStyleRes) { 36 | super(context, attrs, defStyleAttr, defStyleRes); 37 | } 38 | 39 | 40 | public String getUrl() { 41 | return url; 42 | } 43 | 44 | public void setUrl(String url) { 45 | this.url = url; 46 | } 47 | 48 | public String getHostId() { 49 | return hostId; 50 | } 51 | 52 | public void setHostId(String hostId) { 53 | this.hostId = hostId; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/com/lychee/controllerview/controllerView/ControllerViewActivity.java: -------------------------------------------------------------------------------- 1 | package com.lychee.controllerview.controllerView; 2 | 3 | import android.graphics.PixelFormat; 4 | import android.os.Bundle; 5 | import android.support.annotation.CallSuper; 6 | import android.support.annotation.Nullable; 7 | import android.support.v4.app.FragmentTransaction; 8 | import android.support.v7.app.AppCompatActivity; 9 | import android.view.KeyEvent; 10 | import android.view.View; 11 | import android.view.ViewGroup; 12 | import android.widget.FrameLayout; 13 | 14 | import com.lychee.controllerview.R; 15 | import com.taobao.weex.IWXRenderListener; 16 | import com.taobao.weex.WXSDKInstance; 17 | import com.taobao.weex.common.WXRenderStrategy; 18 | 19 | import org.greenrobot.eventbus.EventBus; 20 | import org.greenrobot.eventbus.Subscribe; 21 | import org.greenrobot.eventbus.ThreadMode; 22 | 23 | import java.util.ArrayList; 24 | import java.util.HashMap; 25 | import java.util.Map; 26 | import java.util.concurrent.TimeUnit; 27 | 28 | import butterknife.BindView; 29 | import butterknife.ButterKnife; 30 | import io.reactivex.Completable; 31 | import io.reactivex.android.schedulers.AndroidSchedulers; 32 | import io.reactivex.functions.Action; 33 | 34 | /** 35 | * Created by lychee on 17-4-25. 36 | */ 37 | 38 | public abstract class ControllerViewActivity extends AppCompatActivity implements IWXRenderListener { 39 | 40 | private static final String TAG = "ControllerViewActivity"; 41 | 42 | @BindView(R.id.fl_main) 43 | FrameLayout flMain; 44 | 45 | private ViewGroup mContainer; 46 | private boolean isRenderSuccess = false; 47 | protected WXSDKInstance mInstance; 48 | 49 | protected WXAnalyzerDelegate mWxAnalyzerDelegate; 50 | 51 | private ArrayList mFragments; 52 | 53 | @Override 54 | protected void onCreate(@Nullable Bundle savedInstanceState) { 55 | if (savedInstanceState != null) { 56 | //取消系统自动对fragment的保存,因为fragment会恢复创建 57 | savedInstanceState.putParcelable("android:support:fragments", null); 58 | } 59 | super.onCreate(savedInstanceState); 60 | 61 | createWeexInstance(); 62 | mInstance.onActivityCreate(); 63 | mWxAnalyzerDelegate = new WXAnalyzerDelegate(this); 64 | mWxAnalyzerDelegate.onCreate(); 65 | getWindow().setFormat(PixelFormat.TRANSLUCENT); 66 | 67 | setContentView(R.layout.activity_controller_weex); 68 | ButterKnife.bind(this); 69 | setContainer(flMain); 70 | if (mFragments == null) { 71 | mFragments = new ArrayList<>(); 72 | } else { 73 | mFragments.clear(); 74 | } 75 | EventBus.getDefault().register(this); 76 | startLoad(); 77 | } 78 | 79 | abstract public void startLoad(); 80 | 81 | @Subscribe(threadMode = ThreadMode.MAIN) 82 | public void onControllerChanged(ControllerChange cc) { 83 | if (isRenderSuccess && cc.getHostId().equals(mInstance.getInstanceId())) { 84 | loadControllerView(cc.getUrl(), cc.getTag()); 85 | } 86 | } 87 | 88 | 89 | private synchronized void loadControllerView(String uri, String tag) { 90 | //父视图渲染完成,渲染子视图 91 | ControllerView vg = (ControllerView) getContainer().findViewWithTag(tag); 92 | if (vg != null) { 93 | FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); 94 | for (int i = 0; i < mFragments.size(); i++) { 95 | ControllerViewFragment fragment = mFragments.get(i); 96 | if (fragment.getTag().startsWith(tag + ":") && !fragment.getsUri().equals(uri)) { 97 | fragmentTransaction 98 | .hide(fragment); 99 | } else if (fragment.getTag().startsWith(tag + ":") && fragment.getsUri().equals(uri)) { 100 | fragmentTransaction 101 | .show(fragment); 102 | } 103 | } 104 | fragmentTransaction.commit(); 105 | 106 | if (!searchFragment(uri, tag) || mFragments.size() == 0) { 107 | FragmentTransaction fragmentTransaction2 = getSupportFragmentManager().beginTransaction(); 108 | ControllerViewFragment fragment = ControllerViewFragment.newInstance(vg); 109 | fragmentTransaction2 110 | .add(R.id.fl_main, fragment, tag + ":" + vg.getUrl()) 111 | .commit(); 112 | mFragments.add(fragment); 113 | } 114 | } 115 | } 116 | 117 | private boolean searchFragment(String url, String tag) { 118 | ControllerViewFragment controllerFragment; 119 | for (int i = 0; i < mFragments.size(); i++) { 120 | controllerFragment = mFragments.get(i); 121 | if (controllerFragment.getTag().startsWith(tag + ":") && controllerFragment.getsUri().equals(url)) { 122 | return true; 123 | } 124 | } 125 | return false; 126 | } 127 | 128 | public final void setContainer(ViewGroup container) { 129 | mContainer = container; 130 | } 131 | 132 | public final ViewGroup getContainer() { 133 | return mContainer; 134 | } 135 | 136 | public void destroyWeexInstance() { 137 | if (mInstance != null) { 138 | mInstance.registerRenderListener(null); 139 | mInstance.destroy(); 140 | mInstance = null; 141 | } 142 | } 143 | 144 | public void createWeexInstance() { 145 | destroyWeexInstance(); 146 | 147 | //没太明白这里是干啥的,所以我就注释了... 148 | // Rect outRect = new Rect(); 149 | // getWindow().getDecorView().getWindowVisibleDisplayFrame(outRect); 150 | 151 | mInstance = new WXSDKInstance(this); 152 | mInstance.registerRenderListener(this); 153 | } 154 | 155 | public void renderPage(String template, String source) { 156 | renderPage(template, source, null); 157 | } 158 | 159 | public void renderPage(String template, String source, String jsonInitData) { 160 | AssertUtil.throwIfNull(mContainer, new RuntimeException("Can't render page, container is null")); 161 | Map options = new HashMap<>(); 162 | options.put(WXSDKInstance.BUNDLE_URL, source); 163 | mInstance.setTrackComponent(true); 164 | mInstance.render( 165 | getPageName(), 166 | template, 167 | options, 168 | jsonInitData, 169 | WXRenderStrategy.APPEND_ASYNC); 170 | } 171 | 172 | public void renderPageByURL(String url) { 173 | renderPageByURL(url, null); 174 | } 175 | 176 | public void renderPageByURL(String url, String jsonInitData) { 177 | AssertUtil.throwIfNull(mContainer, new RuntimeException("Can't render page, container is null")); 178 | Map options = new HashMap<>(); 179 | options.put(WXSDKInstance.BUNDLE_URL, url); 180 | mInstance.setTrackComponent(true); 181 | mInstance.renderByUrl( 182 | getPageName(), 183 | url, 184 | options, 185 | jsonInitData, 186 | WXRenderStrategy.APPEND_ASYNC); 187 | } 188 | 189 | public String getPageName() { 190 | return TAG; 191 | } 192 | 193 | @Override 194 | public void onStart() { 195 | super.onStart(); 196 | if (mInstance != null) { 197 | mInstance.onActivityStart(); 198 | } 199 | if (mWxAnalyzerDelegate != null) { 200 | mWxAnalyzerDelegate.onStart(); 201 | } 202 | } 203 | 204 | @Override 205 | public void onResume() { 206 | super.onResume(); 207 | if (mInstance != null) { 208 | mInstance.onActivityResume(); 209 | } 210 | if (mWxAnalyzerDelegate != null) { 211 | mWxAnalyzerDelegate.onResume(); 212 | } 213 | } 214 | 215 | @Override 216 | public void onPause() { 217 | super.onPause(); 218 | if (mInstance != null) { 219 | mInstance.onActivityPause(); 220 | } 221 | if (mWxAnalyzerDelegate != null) { 222 | mWxAnalyzerDelegate.onPause(); 223 | } 224 | } 225 | 226 | @Override 227 | public void onStop() { 228 | super.onStop(); 229 | if (mInstance != null) { 230 | mInstance.onActivityStop(); 231 | } 232 | if (mWxAnalyzerDelegate != null) { 233 | mWxAnalyzerDelegate.onStop(); 234 | } 235 | } 236 | 237 | @Override 238 | public void onDestroy() { 239 | super.onDestroy(); 240 | EventBus.getDefault().unregister(this); 241 | if (mInstance != null) { 242 | mInstance.onActivityDestroy(); 243 | } 244 | if (mWxAnalyzerDelegate != null) { 245 | mWxAnalyzerDelegate.onDestroy(); 246 | } 247 | } 248 | 249 | @Override 250 | public void onViewCreated(WXSDKInstance wxsdkInstance, View view) { 251 | View wrappedView = null; 252 | if (mWxAnalyzerDelegate != null) { 253 | wrappedView = mWxAnalyzerDelegate.onWeexViewCreated(wxsdkInstance, view); 254 | } 255 | if (wrappedView != null) { 256 | view = wrappedView; 257 | } 258 | if (mContainer != null) { 259 | mContainer.removeAllViews(); 260 | mContainer.addView(view); 261 | } 262 | } 263 | 264 | 265 | @Override 266 | public void onRefreshSuccess(WXSDKInstance wxsdkInstance, int i, int i1) { 267 | 268 | } 269 | 270 | @Override 271 | @CallSuper 272 | public void onRenderSuccess(WXSDKInstance instance, int width, int height) { 273 | if (mWxAnalyzerDelegate != null) { 274 | mWxAnalyzerDelegate.onWeexRenderSuccess(instance); 275 | } 276 | isRenderSuccess = true; 277 | ControllerView vg; 278 | String tag; 279 | ViewGroup container = getContainer(); 280 | for (int i = 0; i < 10; i++) { 281 | if (i == 0) { 282 | tag = ControllerView.TAG; 283 | vg = (ControllerView) container.findViewWithTag(tag); 284 | } else { 285 | tag = ControllerView.TAG + i; 286 | vg = (ControllerView) container.findViewWithTag(tag); 287 | } 288 | if (vg != null) { 289 | final ControllerView finalVg = vg; 290 | final String finalTag = tag; 291 | Completable 292 | .timer(50, TimeUnit.MILLISECONDS) 293 | .observeOn(AndroidSchedulers.mainThread()) 294 | .subscribe(new Action() { 295 | @Override 296 | public void run() throws Exception { 297 | EventBus.getDefault().post(new ControllerChange(finalVg.getUrl() 298 | , mInstance.getInstanceId(), finalTag)); 299 | 300 | } 301 | }); 302 | } 303 | 304 | } 305 | } 306 | 307 | @Override 308 | @CallSuper 309 | public void onException(WXSDKInstance instance, String errCode, String msg) { 310 | if (mWxAnalyzerDelegate != null) { 311 | mWxAnalyzerDelegate.onException(instance, errCode, msg); 312 | } 313 | isRenderSuccess = false; 314 | } 315 | 316 | @Override 317 | @CallSuper 318 | public boolean onKeyUp(int keyCode, KeyEvent event) { 319 | return (mWxAnalyzerDelegate != null && mWxAnalyzerDelegate.onKeyUp(keyCode, event)) || super.onKeyUp(keyCode, event); 320 | } 321 | } 322 | -------------------------------------------------------------------------------- /app/src/main/java/com/lychee/controllerview/controllerView/ControllerViewFragment.java: -------------------------------------------------------------------------------- 1 | package com.lychee.controllerview.controllerView; 2 | 3 | import android.content.Context; 4 | import android.os.Bundle; 5 | import android.support.annotation.Nullable; 6 | import android.support.v4.app.Fragment; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.FrameLayout; 11 | 12 | import com.lychee.controllerview.R; 13 | import com.taobao.weex.IWXRenderListener; 14 | import com.taobao.weex.WXSDKInstance; 15 | import com.taobao.weex.common.WXRenderStrategy; 16 | 17 | import java.util.HashMap; 18 | import java.util.Map; 19 | 20 | import butterknife.BindView; 21 | import butterknife.ButterKnife; 22 | import butterknife.Unbinder; 23 | 24 | 25 | /** 26 | * Created by lychee on 17-4-25. 27 | */ 28 | 29 | public class ControllerViewFragment extends Fragment implements IWXRenderListener { 30 | private static final String TAG = "ControllerViewFragment"; 31 | 32 | @BindView(R.id.fragment_fl) 33 | FrameLayout fragmentFl; 34 | Unbinder unbinder; 35 | 36 | protected WXAnalyzerDelegate mWxAnalyzerDelegate; 37 | private ViewGroup mContainer; 38 | protected WXSDKInstance mInstance; 39 | private Context _mActivity; 40 | 41 | private String sUri; 42 | private int width; 43 | private int height; 44 | private int paddingTop; 45 | private int paddingBottom; 46 | private int paddingRight; 47 | private int paddingLeft; 48 | private int leftMargin; 49 | private int rightMargin; 50 | private int topMargin; 51 | private int bottomMargin; 52 | 53 | public ControllerViewFragment() { 54 | 55 | } 56 | 57 | public static ControllerViewFragment newInstance(ControllerView cv) { 58 | Bundle bundle = new Bundle(); 59 | initLayoutParams(bundle, cv); 60 | ControllerViewFragment controllerFragment = new ControllerViewFragment(); 61 | controllerFragment.setArguments(bundle); 62 | return controllerFragment; 63 | } 64 | 65 | private static void initLayoutParams(Bundle bundle, ControllerView cv) { 66 | 67 | bundle.putString("sUri", cv.getUrl()); 68 | bundle.putInt("width", cv.getWidth()); 69 | bundle.putInt("height", cv.getHeight()); 70 | 71 | bundle.putInt("padding-top", cv.getPaddingTop()); 72 | bundle.putInt("padding-left", cv.getPaddingLeft()); 73 | bundle.putInt("padding-right", cv.getPaddingRight()); 74 | bundle.putInt("padding-bottom", cv.getPaddingBottom()); 75 | 76 | FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) cv.getLayoutParams(); 77 | bundle.putInt("leftMargin", layoutParams.leftMargin); 78 | bundle.putInt("rightMargin", layoutParams.rightMargin); 79 | bundle.putInt("topMargin", layoutParams.topMargin); 80 | bundle.putInt("bottomMargin", layoutParams.bottomMargin); 81 | } 82 | 83 | private void loadViewParams(View layout) { 84 | FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(width, height); 85 | layoutParams.leftMargin = leftMargin; 86 | layoutParams.rightMargin = rightMargin; 87 | layoutParams.topMargin = topMargin; 88 | layoutParams.bottomMargin = bottomMargin; 89 | layout.setLayoutParams(layoutParams); 90 | layout.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom); 91 | 92 | } 93 | 94 | @Override 95 | public void onAttach(Context context) { 96 | super.onAttach(context); 97 | _mActivity = context; 98 | } 99 | 100 | @Override 101 | public void onCreate(@Nullable Bundle savedInstanceState) { 102 | super.onCreate(savedInstanceState); 103 | createWeexInstance(); 104 | mInstance.onActivityCreate(); 105 | mWxAnalyzerDelegate = new WXAnalyzerDelegate(_mActivity); 106 | mWxAnalyzerDelegate.onCreate(); 107 | 108 | Bundle bundle = getArguments(); 109 | if (bundle != null) { 110 | this.sUri = bundle.getString("sUri"); 111 | this.width = bundle.getInt("width"); 112 | this.height = bundle.getInt("height"); 113 | this.paddingTop = bundle.getInt("padding-top"); 114 | this.paddingLeft = bundle.getInt("padding-left"); 115 | this.paddingRight = bundle.getInt("padding-right"); 116 | this.paddingBottom = bundle.getInt("padding-bottom"); 117 | 118 | this.leftMargin = bundle.getInt("leftMargin"); 119 | this.rightMargin = bundle.getInt("rightMargin"); 120 | this.topMargin = bundle.getInt("topMargin"); 121 | this.bottomMargin = bundle.getInt("bottomMargin"); 122 | 123 | } 124 | } 125 | 126 | @Nullable 127 | @Override 128 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 129 | View layout = inflater.inflate(R.layout.fragment_controller_weex, container, false); 130 | unbinder = ButterKnife.bind(this, layout); 131 | loadViewParams(layout); 132 | setContainer(fragmentFl); 133 | return layout; 134 | } 135 | 136 | @Override 137 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 138 | renderPageByURL(sUri); 139 | } 140 | 141 | public void createWeexInstance() { 142 | destroyWeexInstance(); 143 | mInstance = new WXSDKInstance(_mActivity); 144 | mInstance.registerRenderListener(this); 145 | } 146 | 147 | public void destroyWeexInstance() { 148 | if (mInstance != null) { 149 | mInstance.registerRenderListener(null); 150 | mInstance.destroy(); 151 | mInstance = null; 152 | } 153 | } 154 | 155 | public String getPageName() { 156 | return TAG; 157 | } 158 | 159 | public void renderPage(String template, String source) { 160 | renderPage(template, source, null); 161 | } 162 | 163 | public void renderPage(String template, String source, String jsonInitData) { 164 | AssertUtil.throwIfNull(mContainer, new RuntimeException("Can't render page, container is null")); 165 | Map options = new HashMap<>(); 166 | options.put(WXSDKInstance.BUNDLE_URL, source); 167 | mInstance.setTrackComponent(true); 168 | mInstance.render( 169 | getPageName(), 170 | template, 171 | options, 172 | jsonInitData, 173 | WXRenderStrategy.APPEND_ASYNC); 174 | } 175 | 176 | public void renderPageByURL(String url) { 177 | renderPageByURL(url, null); 178 | } 179 | 180 | public void renderPageByURL(String url, String jsonInitData) { 181 | AssertUtil.throwIfNull(mContainer, new RuntimeException("Can't render page, container is null")); 182 | Map options = new HashMap<>(); 183 | options.put(WXSDKInstance.BUNDLE_URL, url); 184 | mInstance.setTrackComponent(true); 185 | mInstance.renderByUrl( 186 | getPageName(), 187 | url, 188 | options, 189 | jsonInitData, 190 | WXRenderStrategy.APPEND_ASYNC); 191 | } 192 | 193 | 194 | public final void setContainer(ViewGroup container) { 195 | mContainer = container; 196 | } 197 | 198 | public final ViewGroup getContainer() { 199 | return mContainer; 200 | } 201 | 202 | public String getsUri() { 203 | return sUri == null ? "" : sUri; 204 | } 205 | 206 | @Override 207 | public void onStart() { 208 | super.onStart(); 209 | if (mInstance != null) { 210 | mInstance.onActivityStart(); 211 | } 212 | if (mWxAnalyzerDelegate != null) { 213 | mWxAnalyzerDelegate.onStart(); 214 | } 215 | } 216 | 217 | @Override 218 | public void onResume() { 219 | super.onResume(); 220 | if (mInstance != null) { 221 | mInstance.onActivityResume(); 222 | } 223 | if (mWxAnalyzerDelegate != null) { 224 | mWxAnalyzerDelegate.onResume(); 225 | } 226 | } 227 | 228 | @Override 229 | public void onPause() { 230 | super.onPause(); 231 | if (mInstance != null) { 232 | mInstance.onActivityPause(); 233 | } 234 | if (mWxAnalyzerDelegate != null) { 235 | mWxAnalyzerDelegate.onPause(); 236 | } 237 | } 238 | 239 | @Override 240 | public void onStop() { 241 | super.onStop(); 242 | if (mInstance != null) { 243 | mInstance.onActivityStop(); 244 | } 245 | if (mWxAnalyzerDelegate != null) { 246 | mWxAnalyzerDelegate.onStop(); 247 | } 248 | } 249 | 250 | @Override 251 | public void onDestroyView() { 252 | super.onDestroyView(); 253 | unbinder.unbind(); 254 | } 255 | 256 | @Override 257 | public void onDestroy() { 258 | super.onDestroy(); 259 | if (mInstance != null) { 260 | mInstance.onActivityDestroy(); 261 | } 262 | if (mWxAnalyzerDelegate != null) { 263 | mWxAnalyzerDelegate.onDestroy(); 264 | } 265 | } 266 | 267 | @Override 268 | public void onViewCreated(WXSDKInstance instance, View view) { 269 | 270 | View wrappedView = null; 271 | if (mWxAnalyzerDelegate != null) { 272 | wrappedView = mWxAnalyzerDelegate.onWeexViewCreated(instance, view); 273 | } 274 | if (wrappedView != null) { 275 | view = wrappedView; 276 | } 277 | if (mContainer != null) { 278 | mContainer.removeAllViews(); 279 | mContainer.addView(view); 280 | } 281 | } 282 | 283 | @Override 284 | public void onRenderSuccess(WXSDKInstance instance, int width, int height) { 285 | } 286 | 287 | @Override 288 | public void onRefreshSuccess(WXSDKInstance instance, int width, int height) { 289 | if (mWxAnalyzerDelegate != null) { 290 | mWxAnalyzerDelegate.onWeexRenderSuccess(instance); 291 | } 292 | } 293 | 294 | @Override 295 | public void onException(WXSDKInstance instance, String errCode, String msg) { 296 | if (mWxAnalyzerDelegate != null) { 297 | mWxAnalyzerDelegate.onException(instance, errCode, msg); 298 | } 299 | } 300 | 301 | 302 | } 303 | -------------------------------------------------------------------------------- /app/src/main/java/com/lychee/controllerview/controllerView/WXAnalyzerDelegate.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Apache License 4 | * Version 2.0, January 2004 5 | * http://www.apache.org/licenses/ 6 | * 7 | * TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 8 | * 9 | * 1. Definitions. 10 | * 11 | * "License" shall mean the terms and conditions for use, reproduction, 12 | * and distribution as defined by Sections 1 through 9 of this document. 13 | * 14 | * "Licensor" shall mean the copyright owner or entity authorized by 15 | * the copyright owner that is granting the License. 16 | * 17 | * "Legal Entity" shall mean the union of the acting entity and all 18 | * other entities that control, are controlled by, or are under common 19 | * control with that entity. For the purposes of this definition, 20 | * "control" means (i) the power, direct or indirect, to cause the 21 | * direction or management of such entity, whether by contract or 22 | * otherwise, or (ii) ownership of fifty percent (50%) or more of the 23 | * outstanding shares, or (iii) beneficial ownership of such entity. 24 | * 25 | * "You" (or "Your") shall mean an individual or Legal Entity 26 | * exercising permissions granted by this License. 27 | * 28 | * "Source" form shall mean the preferred form for making modifications, 29 | * including but not limited to software source code, documentation 30 | * source, and configuration files. 31 | * 32 | * "Object" form shall mean any form resulting from mechanical 33 | * transformation or translation of a Source form, including but 34 | * not limited to compiled object code, generated documentation, 35 | * and conversions to other media types. 36 | * 37 | * "Work" shall mean the work of authorship, whether in Source or 38 | * Object form, made available under the License, as indicated by a 39 | * copyright notice that is included in or attached to the work 40 | * (an example is provided in the Appendix below). 41 | * 42 | * "Derivative Works" shall mean any work, whether in Source or Object 43 | * form, that is based on (or derived from) the Work and for which the 44 | * editorial revisions, annotations, elaborations, or other modifications 45 | * represent, as a whole, an original work of authorship. For the purposes 46 | * of this License, Derivative Works shall not include works that remain 47 | * separable from, or merely link (or bind by name) to the interfaces of, 48 | * the Work and Derivative Works thereof. 49 | * 50 | * "Contribution" shall mean any work of authorship, including 51 | * the original version of the Work and any modifications or additions 52 | * to that Work or Derivative Works thereof, that is intentionally 53 | * submitted to Licensor for inclusion in the Work by the copyright owner 54 | * or by an individual or Legal Entity authorized to submit on behalf of 55 | * the copyright owner. For the purposes of this definition, "submitted" 56 | * means any form of electronic, verbal, or written communication sent 57 | * to the Licensor or its representatives, including but not limited to 58 | * communication on electronic mailing lists, source code control systems, 59 | * and issue tracking systems that are managed by, or on behalf of, the 60 | * Licensor for the purpose of discussing and improving the Work, but 61 | * excluding communication that is conspicuously marked or otherwise 62 | * designated in writing by the copyright owner as "Not a Contribution." 63 | * 64 | * "Contributor" shall mean Licensor and any individual or Legal Entity 65 | * on behalf of whom a Contribution has been received by Licensor and 66 | * subsequently incorporated within the Work. 67 | * 68 | * 2. Grant of Copyright License. Subject to the terms and conditions of 69 | * this License, each Contributor hereby grants to You a perpetual, 70 | * worldwide, non-exclusive, no-charge, royalty-free, irrevocable 71 | * copyright license to reproduce, prepare Derivative Works of, 72 | * publicly display, publicly perform, sublicense, and distribute the 73 | * Work and such Derivative Works in Source or Object form. 74 | * 75 | * 3. Grant of Patent License. Subject to the terms and conditions of 76 | * this License, each Contributor hereby grants to You a perpetual, 77 | * worldwide, non-exclusive, no-charge, royalty-free, irrevocable 78 | * (except as stated in this section) patent license to make, have made, 79 | * use, offer to sell, sell, import, and otherwise transfer the Work, 80 | * where such license applies only to those patent claims licensable 81 | * by such Contributor that are necessarily infringed by their 82 | * Contribution(s) alone or by combination of their Contribution(s) 83 | * with the Work to which such Contribution(s) was submitted. If You 84 | * institute patent litigation against any entity (including a 85 | * cross-claim or counterclaim in a lawsuit) alleging that the Work 86 | * or a Contribution incorporated within the Work constitutes direct 87 | * or contributory patent infringement, then any patent licenses 88 | * granted to You under this License for that Work shall terminate 89 | * as of the date such litigation is filed. 90 | * 91 | * 4. Redistribution. You may reproduce and distribute copies of the 92 | * Work or Derivative Works thereof in any medium, with or without 93 | * modifications, and in Source or Object form, provided that You 94 | * meet the following conditions: 95 | * 96 | * (a) You must give any other recipients of the Work or 97 | * Derivative Works a copy of this License; and 98 | * 99 | * (b) You must cause any modified files to carry prominent notices 100 | * stating that You changed the files; and 101 | * 102 | * (c) You must retain, in the Source form of any Derivative Works 103 | * that You distribute, all copyright, patent, trademark, and 104 | * attribution notices from the Source form of the Work, 105 | * excluding those notices that do not pertain to any part of 106 | * the Derivative Works; and 107 | * 108 | * (d) If the Work includes a "NOTICE" text file as part of its 109 | * distribution, then any Derivative Works that You distribute must 110 | * include a readable copy of the attribution notices contained 111 | * within such NOTICE file, excluding those notices that do not 112 | * pertain to any part of the Derivative Works, in at least one 113 | * of the following places: within a NOTICE text file distributed 114 | * as part of the Derivative Works; within the Source form or 115 | * documentation, if provided along with the Derivative Works; or, 116 | * within a display generated by the Derivative Works, if and 117 | * wherever such third-party notices normally appear. The contents 118 | * of the NOTICE file are for informational purposes only and 119 | * do not modify the License. You may add Your own attribution 120 | * notices within Derivative Works that You distribute, alongside 121 | * or as an addendum to the NOTICE text from the Work, provided 122 | * that such additional attribution notices cannot be construed 123 | * as modifying the License. 124 | * 125 | * You may add Your own copyright statement to Your modifications and 126 | * may provide additional or different license terms and conditions 127 | * for use, reproduction, or distribution of Your modifications, or 128 | * for any such Derivative Works as a whole, provided Your use, 129 | * reproduction, and distribution of the Work otherwise complies with 130 | * the conditions stated in this License. 131 | * 132 | * 5. Submission of Contributions. Unless You explicitly state otherwise, 133 | * any Contribution intentionally submitted for inclusion in the Work 134 | * by You to the Licensor shall be under the terms and conditions of 135 | * this License, without any additional terms or conditions. 136 | * Notwithstanding the above, nothing herein shall supersede or modify 137 | * the terms of any separate license agreement you may have executed 138 | * with Licensor regarding such Contributions. 139 | * 140 | * 6. Trademarks. This License does not grant permission to use the trade 141 | * names, trademarks, service marks, or product names of the Licensor, 142 | * except as required for reasonable and customary use in describing the 143 | * origin of the Work and reproducing the content of the NOTICE file. 144 | * 145 | * 7. Disclaimer of Warranty. Unless required by applicable law or 146 | * agreed to in writing, Licensor provides the Work (and each 147 | * Contributor provides its Contributions) on an "AS IS" BASIS, 148 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 149 | * implied, including, without limitation, any warranties or conditions 150 | * of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 151 | * PARTICULAR PURPOSE. You are solely responsible for determining the 152 | * appropriateness of using or redistributing the Work and assume any 153 | * risks associated with Your exercise of permissions under this License. 154 | * 155 | * 8. Limitation of Liability. In no event and under no legal theory, 156 | * whether in tort (including negligence), contract, or otherwise, 157 | * unless required by applicable law (such as deliberate and grossly 158 | * negligent acts) or agreed to in writing, shall any Contributor be 159 | * liable to You for damages, including any direct, indirect, special, 160 | * incidental, or consequential damages of any character arising as a 161 | * result of this License or out of the use or inability to use the 162 | * Work (including but not limited to damages for loss of goodwill, 163 | * work stoppage, computer FAILURE or malfunction, or any and all 164 | * other commercial damages or losses), even if such Contributor 165 | * has been advised of the possibility of such damages. 166 | * 167 | * 9. Accepting Warranty or Additional Liability. While redistributing 168 | * the Work or Derivative Works thereof, You may choose to offer, 169 | * and charge a fee for, acceptance of support, warranty, indemnity, 170 | * or other liability obligations and/or rights consistent with this 171 | * License. However, in accepting such obligations, You may act only 172 | * on Your own behalf and on Your sole responsibility, not on behalf 173 | * of any other Contributor, and only if You agree to indemnify, 174 | * defend, and hold each Contributor harmless for any liability 175 | * incurred by, or claims asserted against, such Contributor by reason 176 | * of your accepting any such warranty or additional liability. 177 | * 178 | * END OF TERMS AND CONDITIONS 179 | * 180 | * APPENDIX: How to apply the Apache License to your work. 181 | * 182 | * To apply the Apache License to your work, attach the following 183 | * boilerplate notice, with the fields enclosed by brackets "[]" 184 | * replaced with your own identifying information. (Don't include 185 | * the brackets!) The text should be enclosed in the appropriate 186 | * comment syntax for the file format. We also recommend that a 187 | * file or class name and description of purpose be included on the 188 | * same "printed page" as the copyright notice for easier 189 | * identification within third-party archives. 190 | * 191 | * Copyright 2016 Alibaba Group 192 | * 193 | * Licensed under the Apache License, Version 2.0 (the "License"); 194 | * you may not use this file except in compliance with the License. 195 | * You may obtain a copy of the License at 196 | * 197 | * http://www.apache.org/licenses/LICENSE-2.0 198 | * 199 | * Unless required by applicable law or agreed to in writing, software 200 | * distributed under the License is distributed on an "AS IS" BASIS, 201 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 202 | * See the License for the specific language governing permissions and 203 | * limitations under the License. 204 | */ 205 | package com.lychee.controllerview.controllerView; 206 | 207 | import android.content.Context; 208 | import android.support.annotation.Nullable; 209 | import android.text.TextUtils; 210 | import android.view.KeyEvent; 211 | import android.view.View; 212 | 213 | import com.taobao.weex.WXSDKInstance; 214 | 215 | import java.lang.reflect.Constructor; 216 | import java.lang.reflect.Method; 217 | 218 | /** 219 | * Description: 220 | *

221 | * Created by rowandjj(chuyi)
222 | * Date: 2016/10/27
223 | * Time: 下午7:01
224 | */ 225 | 226 | public final class WXAnalyzerDelegate { 227 | private Object mWXAnalyzer; 228 | 229 | private static boolean ENABLE = false; 230 | 231 | @SuppressWarnings("unchecked") 232 | public WXAnalyzerDelegate(@Nullable Context context) { 233 | if(!ENABLE){ 234 | return; 235 | } 236 | if(context == null){ 237 | return; 238 | } 239 | try { 240 | Class clazz = Class.forName("com.taobao.weex.analyzer.WeexDevOptions"); 241 | Constructor constructor = clazz.getDeclaredConstructor(Context.class); 242 | mWXAnalyzer = constructor.newInstance(context); 243 | } catch (Exception e) { 244 | e.printStackTrace(); 245 | } 246 | } 247 | 248 | public void onCreate() { 249 | if (mWXAnalyzer == null) { 250 | return; 251 | } 252 | try { 253 | Method method = mWXAnalyzer.getClass().getDeclaredMethod("onCreate"); 254 | method.invoke(mWXAnalyzer); 255 | } catch (Exception e) { 256 | e.printStackTrace(); 257 | } 258 | } 259 | 260 | 261 | public void onStart() { 262 | if (mWXAnalyzer == null) { 263 | return; 264 | } 265 | try { 266 | Method method = mWXAnalyzer.getClass().getDeclaredMethod("onStart"); 267 | method.invoke(mWXAnalyzer); 268 | } catch (Exception e) { 269 | e.printStackTrace(); 270 | } 271 | } 272 | 273 | public void onResume() { 274 | if (mWXAnalyzer == null) { 275 | return; 276 | } 277 | try { 278 | Method method = mWXAnalyzer.getClass().getDeclaredMethod("onResume"); 279 | method.invoke(mWXAnalyzer); 280 | } catch (Exception e) { 281 | e.printStackTrace(); 282 | } 283 | } 284 | 285 | 286 | public void onPause() { 287 | if (mWXAnalyzer == null) { 288 | return; 289 | } 290 | try { 291 | Method method = mWXAnalyzer.getClass().getDeclaredMethod("onPause"); 292 | method.invoke(mWXAnalyzer); 293 | } catch (Exception e) { 294 | e.printStackTrace(); 295 | } 296 | } 297 | 298 | public void onStop() { 299 | if (mWXAnalyzer == null) { 300 | return; 301 | } 302 | try { 303 | Method method = mWXAnalyzer.getClass().getDeclaredMethod("onStop"); 304 | method.invoke(mWXAnalyzer); 305 | } catch (Exception e) { 306 | e.printStackTrace(); 307 | } 308 | } 309 | 310 | public void onDestroy() { 311 | if (mWXAnalyzer == null) { 312 | return; 313 | } 314 | try { 315 | Method method = mWXAnalyzer.getClass().getDeclaredMethod("onDestroy"); 316 | method.invoke(mWXAnalyzer); 317 | } catch (Exception e) { 318 | e.printStackTrace(); 319 | } 320 | } 321 | 322 | 323 | public void onWeexRenderSuccess(@Nullable WXSDKInstance instance) { 324 | if (mWXAnalyzer == null || instance == null) { 325 | return; 326 | } 327 | try { 328 | Method method = mWXAnalyzer.getClass().getDeclaredMethod("onWeexRenderSuccess", WXSDKInstance.class); 329 | method.invoke(mWXAnalyzer, instance); 330 | } catch (Exception e) { 331 | e.printStackTrace(); 332 | } 333 | 334 | } 335 | 336 | 337 | public boolean onKeyUp(int keyCode, KeyEvent event) { 338 | if (mWXAnalyzer == null) { 339 | return false; 340 | } 341 | try { 342 | Method method = mWXAnalyzer.getClass().getDeclaredMethod("onKeyUp", int.class, KeyEvent.class); 343 | return (boolean) method.invoke(mWXAnalyzer, keyCode, event); 344 | } catch (Exception e) { 345 | e.printStackTrace(); 346 | return false; 347 | } 348 | } 349 | 350 | public void onException(WXSDKInstance instance, String errCode, String msg) { 351 | if (mWXAnalyzer == null) { 352 | return; 353 | } 354 | if (TextUtils.isEmpty(errCode) && TextUtils.isEmpty(msg)) { 355 | return; 356 | } 357 | try { 358 | Method method = mWXAnalyzer.getClass().getDeclaredMethod("onException", WXSDKInstance.class, String.class, String.class); 359 | method.invoke(mWXAnalyzer, instance, errCode, msg); 360 | } catch (Exception e) { 361 | e.printStackTrace(); 362 | } 363 | } 364 | 365 | public View onWeexViewCreated(WXSDKInstance instance, View view) { 366 | if (mWXAnalyzer == null || instance == null || view == null) { 367 | return null; 368 | } 369 | try { 370 | Method method = mWXAnalyzer.getClass().getDeclaredMethod("onWeexViewCreated", WXSDKInstance.class, View.class); 371 | View retView = (View) method.invoke(mWXAnalyzer, instance, view); 372 | return retView; 373 | } catch (Exception e) { 374 | e.printStackTrace(); 375 | return view; 376 | } 377 | } 378 | 379 | } 380 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_controller.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | 13 | 17 | 18 |