├── .gitignore ├── .idea ├── caches │ └── build_file_checksums.ser ├── codeStyles │ └── Project.xml ├── gradle.xml ├── inspectionProfiles │ └── Project_Default.xml ├── markdown-navigator.xml ├── markdown-navigator │ └── profiles_settings.xml ├── misc.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── README_CN.md ├── app-databinding ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── zhangyue │ │ └── demo │ │ └── databinding │ │ ├── ActivityDataBinding.java │ │ └── Bean.java │ └── res │ ├── drawable │ ├── head.jpg │ ├── ic_launcher_background.xml │ └── ic_launcher_foreground.xml │ ├── layout │ └── activity_databinding.xml │ ├── mipmap-anydpi-v26 │ ├── ic_launcher.xml │ └── ic_launcher_round.xml │ ├── mipmap-hdpi │ ├── a.jpg │ ├── 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 │ ├── strings.xml │ └── styles.xml ├── app-module ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── zhangyue │ │ └── x2c │ │ └── demo │ │ └── ActivitySubModule.java │ └── res │ ├── layout │ └── sub_activity.xml │ └── values │ └── strings.xml ├── app ├── .gitignore ├── X2C_CONFIG.xml ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── zhangyue │ │ └── we │ │ └── x2c │ │ └── demo │ │ ├── CustomView.java │ │ ├── MyFragment.java │ │ └── act │ │ ├── ActivityX2C.java │ │ ├── ActivityXML.java │ │ └── MainActivity.java │ └── res │ ├── drawable-v24 │ └── ic_launcher_foreground.xml │ ├── drawable │ ├── head.jpg │ ├── ic_launcher_background.xml │ └── ic_launcher_foreground.xml │ ├── layout-land │ └── activity_databinding.xml │ ├── layout-v27 │ └── activity_databinding.xml │ ├── layout │ ├── activity.xml │ ├── activity_databinding.xml │ ├── activity_main_inter.xml │ ├── fragmetn_layout.xml │ ├── include.xml │ └── stub_layout.xml │ ├── mipmap-anydpi-v26 │ ├── ic_launcher.xml │ └── ic_launcher_round.xml │ ├── mipmap-hdpi │ ├── a.jpg │ ├── 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 │ ├── attrs.xml │ ├── colors.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle ├── supportAll.md ├── x2c-apt ├── .gitignore ├── build.gradle └── src │ └── main │ ├── java │ └── com │ │ ├── squareup │ │ └── javapoet │ │ │ └── x2c │ │ │ ├── AnnotationSpec.java │ │ │ ├── ArrayTypeName.java │ │ │ ├── ClassName.java │ │ │ ├── CodeBlock.java │ │ │ ├── CodeWriter.java │ │ │ ├── FieldSpec.java │ │ │ ├── JavaFile.java │ │ │ ├── LineWrapper.java │ │ │ ├── MethodSpec.java │ │ │ ├── NameAllocator.java │ │ │ ├── ParameterSpec.java │ │ │ ├── ParameterizedTypeName.java │ │ │ ├── TypeName.java │ │ │ ├── TypeSpec.java │ │ │ ├── TypeVariableName.java │ │ │ ├── Util.java │ │ │ └── WildcardTypeName.java │ │ └── zhangyue │ │ └── we │ │ ├── anoprocesser │ │ ├── FileFilter.java │ │ ├── Log.java │ │ ├── Util.java │ │ ├── XmlProcessor.java │ │ └── xml │ │ │ ├── Attr.java │ │ │ ├── Attr2FuncReader.java │ │ │ ├── AttrReader.java │ │ │ ├── Func.java │ │ │ ├── LayoutManager.java │ │ │ ├── LayoutReader.java │ │ │ ├── LayoutWriter.java │ │ │ ├── MapWriter.java │ │ │ ├── Style.java │ │ │ └── StyleReader.java │ │ ├── view │ │ ├── ConstraintLayout.java │ │ ├── CustomAttr.java │ │ ├── ITranslator.java │ │ ├── RelativeLayout.java │ │ └── View.java │ │ └── x2c │ │ └── ano │ │ └── Xml.java │ └── resources │ └── META-INF │ └── services │ └── javax.annotation.processing.Processor ├── x2c-binding ├── .gitignore ├── build.gradle ├── libs-provided │ ├── databinding.jar │ └── x2c.jar ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── android │ │ └── databinding │ │ └── DataBindingX2C.java │ └── res │ └── values │ └── strings.xml └── x2c-lib ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src └── main ├── AndroidManifest.xml ├── java └── com │ └── zhangyue │ └── we │ └── x2c │ ├── IViewCreator.java │ ├── X2C.java │ ├── X2CUtils.java │ └── ano │ └── Xml.java └── res └── values ├── ids.xml └── strings.xml /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/libraries 5 | /.idea/modules.xml 6 | /.idea/workspace.xml 7 | .DS_Store 8 | /build 9 | /captures 10 | .externalNativeBuild 11 | -------------------------------------------------------------------------------- /.idea/caches/build_file_checksums.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iReaderAndroid/X2C/9bdf7ea7bc509481ce9fd1d1ea69b6847b5f832e/.idea/caches/build_file_checksums.ser -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 15 | 16 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 23 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 36 | -------------------------------------------------------------------------------- /.idea/markdown-navigator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 36 | 37 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /.idea/markdown-navigator/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 21 | 22 | 35 | 45 | 46 | 47 | 48 | 49 | 50 | 52 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Background 2 | [中文](README_CN.md) 3 | 4 | Generally, when writing a page, everyone writes the layout through xml, and loads the xml layout into memory through set contentView or LayoutInflater.from(context).inflate method. 5 | #### advantage 6 | * Good maintainability 7 | * Support instant preview 8 | * Clear code structure 9 | 10 | #### Disadvantage 11 | * Reading xml is time consuming 12 | * Recursive parsing xml is time consuming 13 | * The time it takes to generate an object is more than three times that of new. 14 | 15 | Our team has also explored many solutions on this issue. Once it reached the other extreme, completely abandoning xml, all controls are new through java, even directly in the canvas, so although the performance is indeed improved, but the code is gone. A little bit of readability and maintainability. 16 | We later reflected on the code to see the machine, or to show it? ? Maybe X2C has given us an answer. 17 | 18 | # X2C 19 | 20 | In order to preserve the advantages of xml and solve the performance problems it brings, we developed the X2C solution. That is, during the compilation and generation of the APK, the translation of the layout that needs to be translated generates the corresponding java file, so that the developer writes the layout or writes the original xml, but for the program, the runtime loads the corresponding java file. 21 | We use APT (Annotation Processor Tool) + JavaPoet technology to complete the operation of the whole process during the compilation [Annotation] -> [Resolve] -> [Translate xml] -> [Generate java]. 22 | 23 | # Performance comparison 24 | After the development integration, we did a simple test, the performance comparison is as follows 25 | 26 | | Loading method|frequency|Average load time| 27 | | ------ | ------ | ------ | 28 | |XML|100|30| 29 | |X2C|100|11| 30 | 31 | # Integrated use 32 | #### 1.Add dependency 33 | Add dependencies in the build.gradle file of the module 34 | ```java 35 | annotationProcessor 'com.zhangyue.we:x2c-apt:1.1.2' 36 | implementation 'com.zhangyue.we:x2c-lib:1.0.6' 37 | ``` 38 | 39 | #### 2.Add annotation 40 | Add annotations to any java class or method that uses the layout. 41 | ```java 42 | @Xml(layouts = "activity_main") 43 | ``` 44 | 45 | 46 | #### 3.Configure custom properties (no or no) 47 | 48 | Create an X2C_CONFIG.xml file under the module, which defines the mapping between attributes and methods. If the receiver is a view, write the view. Otherwise fill in params. 49 | 50 | ```mxl 51 | 52 | 53 | 54 | 55 | ``` 56 | 57 | #### 4.Load layout through X2C 58 | Replace where you originally used set content view or inflate, as follows: 59 | ```java 60 | this.setContentView(R.layout.activity_main); --> X2C.setContentView(this, R.layout.activity_main); 61 | ``` 62 | ```java 63 | LayoutInflater.from(this).inflate(R.layout.activity_main,null); --> X2C.inflate(this,R.layout.activity_main,null); 64 | ``` 65 | 66 | 67 | # Process file 68 | 69 | #### Original xml 70 | 71 | ```xml 72 | 73 | 79 | 80 | 86 | 87 | 91 | 92 | ``` 93 | 94 | #### Generated java file 95 | ```java 96 | 97 | /** 98 | * WARN!!! dont edit this file 99 | * translate from {@link com.zhangyue.we.x2c.demo.R.layout.activity_main} 100 | * autho chengwei 101 | * email chengwei@zhangyue.com 102 | */ 103 | public class X2C_2131296281_Activity_Main implements IViewCreator { 104 | @Override 105 | public View createView(Context ctx, int layoutId) { 106 | Resources res = ctx.getResources(); 107 | 108 | RelativeLayout relativeLayout0 = new RelativeLayout(ctx); 109 | relativeLayout0.setPadding((int)(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,10,res.getDisplayMetrics())),0,0,0); 110 | 111 | View view1 =(View) new X2C_2131296283_Head().createView(ctx,0); 112 | RelativeLayout.LayoutParams layoutParam1 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT); 113 | view1.setLayoutParams(layoutParam1); 114 | relativeLayout0.addView(view1); 115 | view1.setId(R.id.head); 116 | layoutParam1.addRule(RelativeLayout.CENTER_HORIZONTAL,RelativeLayout.TRUE); 117 | 118 | ImageView imageView2 = new ImageView(ctx); 119 | RelativeLayout.LayoutParams layoutParam2 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,(int)(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,1,res.getDisplayMetrics()))); 120 | imageView2.setLayoutParams(layoutParam2); 121 | relativeLayout0.addView(imageView2); 122 | imageView2.setId(R.id.ccc); 123 | layoutParam2.addRule(RelativeLayout.BELOW,R.id.head); 124 | 125 | return relativeLayout0; 126 | } 127 | } 128 | ``` 129 | #### Generated map file 130 | ```java 131 | 132 | /** 133 | * WARN!!! don't edit this file 134 | * 135 | * author chengwei 136 | * email chengwei@zhangyue.com 137 | */ 138 | public class X2C127_activity implements IViewCreator { 139 | @Override 140 | public View createView(Context context) { 141 | View view = null ; 142 | int sdk = Build.VERSION.SDK_INT; 143 | int orientation = context.getResources().getConfiguration().orientation; 144 | boolean isLandscape = orientation == Configuration.ORIENTATION_LANDSCAPE; 145 | if (isLandscape) { 146 | view = new com.zhangyue.we.x2c.layouts.land.X2C127_Activity().createView(context); 147 | } else if (sdk >= 27) { 148 | view = new com.zhangyue.we.x2c.layouts.v27.X2C127_Activity().createView(context); 149 | } else if (sdk >= 21) { 150 | view = new com.zhangyue.we.x2c.layouts.v21.X2C127_Activity().createView(context); 151 | } else { 152 | view = new com.zhangyue.we.x2c.layouts.X2C127_Activity().createView(context); 153 | } 154 | return view; 155 | } 156 | } 157 | 158 | ``` 159 | # not support 160 | * The merge tag cannot determine the parent of the xml during compilation, so it cannot be supported. 161 | * System style, only the style list of the application can be found during compilation, and the system style cannot be queried, so only the in-app style is supported. 162 | 163 | # support 164 | * ButterKnifer 165 | * DataBinding 166 | * android widget 167 | * customView 168 | * include tag 169 | * viewStub tag 170 | * fragment label 171 | * Application style 172 | * Custom attribute 173 | * System attribute 174 | 175 | | Attribute name|Attribute name| 176 | | ------ |------- | 177 | |android:textSize| app:layout_constraintRight_toLeftOf| 178 | |android:textColor| app:layout_constraintBottom_toTopOf| 179 | |android:text| app:layout_constraintTop_toTopOf| 180 | |android:background| app:layout_constrainedHeight| 181 | |[view all](supportAll.md)| 182 | 183 | 184 | 185 | ## There are usage problems and other technical issues, welcome to exchange discussion 186 | 187 | > QQ群:`870956525`,Add please specify from`X2C` 188 | > 189 | > 掌阅X2C交流群 190 | > 191 | > Welcome everyone to use, the project will continue to maintain 192 | > 193 | > 194 | > Another: welcome to join[IReader](http://www.zhangyue.com/jobs) family, study new Android technologies together. Please send your resume`huangjian@zhangyue.com`,Indicate the direction of employment。 195 | > 196 | # LICENSE 197 | 198 | ``` 199 | MIT LICENSE 200 | Copyright (c) 2018 zhangyue 201 | 202 | Permission is hereby granted, free of charge, to any person obtaining 203 | a copy of this software and associated documentation files (the 204 | "Software"), to deal in the Software without restriction, including 205 | without limitation the rights to use, copy, modify, merge, publish, 206 | distribute, sublicense, and/or sell copies of the Software, and to 207 | permit persons to whom the Software is furnished to do so, subject to 208 | the following conditions: 209 | 210 | The above copyright notice and this permission notice shall be 211 | included in all copies or substantial portions of the Software. 212 | 213 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 214 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 215 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 216 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 217 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 218 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 219 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 220 | ``` 221 | -------------------------------------------------------------------------------- /README_CN.md: -------------------------------------------------------------------------------- 1 | # 背景 2 | [English](README.md) 3 | 4 |  一般大家在写页面时都是通过xml写布局,通过setContentView、或LayoutInflater.from(context).inflate方法将xml布局加载到内存中。 5 | 6 | #### 优点 7 | * 可维护性好 8 | * 支持即时预览 9 | * 代码结构清晰 10 | 11 | #### 缺点 12 | * 读取xml很耗时 13 | * 递归解析xml较耗时 14 | * 反射生成对象的耗时是new的3倍以上 15 | 16 |     我们团队在这个问题上也探索过很多解决方案,一度走到了另一个极端,完全废弃xml,所有控件通过java来new,甚至直接在canvas里绘制,这样虽然性能确实提升了,但是代码已经没有了一丁点可读性,可维护性。 17 |     我们后来反思代码到底是给机器看的,还是给人看的??也许X2C已经给了我们一个答案 18 | 19 | # X2C 20 | 21 |     为了即保留xml的优点,又解决它带来的性能问题,我们开发了X2C方案。即在编译生成APK期间,将需要翻译的layout翻译生成对应的java文件,这样对于开发人员来说写布局还是写原来的xml,但对于程序来说,运行时加载的是对应的java文件。 22 |     我们采用APT(Annotation Processor Tool)+ JavaPoet技术来完成编译期间【注解】->【解注解】->【翻译xml】->【生成java】整个流程的操作。 23 | 24 | # 性能对比 25 | 在开发集成完之后我们做了简单的测试,性能对比如下 26 | 27 | | 加载方式|次数|平均加载时间| 28 | | ------ | ------ | ------ | 29 | |XML|100|30| 30 | |X2C|100|11| 31 | 32 | # 集成使用 33 | #### 1.导入依赖 34 | 在module的build.gradle文件添加依赖 35 | ```java 36 | annotationProcessor 'com.zhangyue.we:x2c-apt:1.1.2' 37 | implementation 'com.zhangyue.we:x2c-lib:1.0.6' 38 | ``` 39 | 40 | #### 2.添加注解 41 | 在使用布局的任意java类或方法添加注解即可 42 | ```java 43 | @Xml(layouts = "activity_main") 44 | ``` 45 | 46 | 47 | #### 3.配置自定义属性(没有可不配) 48 | 49 | 在module下建立X2C_CONFIG.xml文件,里面配置定义属性和方法的映射关系,如果接收者是view,则写view.否则填params. 50 | 51 | ```mxl 52 | 53 | 54 | 55 | 56 | ``` 57 | 58 | #### 4.通过X2C加载布局 59 | 在原先使用setContentView或inflate的地方替换,如下: 60 | ```java 61 | this.setContentView(R.layout.activity_main); --> X2C.setContentView(this, R.layout.activity_main); 62 | ``` 63 | ```java 64 | LayoutInflater.from(this).inflate(R.layout.activity_main,null); --> X2C.inflate(this,R.layout.activity_main,null); 65 | ``` 66 | 67 | 68 | # 过程文件 69 | 70 | #### 原始的xml 71 | 72 | ```xml 73 | 74 | 80 | 81 | 87 | 88 | 92 | 93 | ``` 94 | 95 | #### 生成的java文件 96 | ```java 97 | 98 | /** 99 | * WARN!!! dont edit this file 100 | * translate from {@link com.zhangyue.we.x2c.demo.R.layout.activity_main} 101 | * autho chengwei 102 | * email chengwei@zhangyue.com 103 | */ 104 | public class X2C_2131296281_Activity_Main implements IViewCreator { 105 | @Override 106 | public View createView(Context ctx, int layoutId) { 107 | Resources res = ctx.getResources(); 108 | 109 | RelativeLayout relativeLayout0 = new RelativeLayout(ctx); 110 | relativeLayout0.setPadding((int)(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,10,res.getDisplayMetrics())),0,0,0); 111 | 112 | View view1 =(View) new X2C_2131296283_Head().createView(ctx,0); 113 | RelativeLayout.LayoutParams layoutParam1 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT); 114 | view1.setLayoutParams(layoutParam1); 115 | relativeLayout0.addView(view1); 116 | view1.setId(R.id.head); 117 | layoutParam1.addRule(RelativeLayout.CENTER_HORIZONTAL,RelativeLayout.TRUE); 118 | 119 | ImageView imageView2 = new ImageView(ctx); 120 | RelativeLayout.LayoutParams layoutParam2 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,(int)(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,1,res.getDisplayMetrics()))); 121 | imageView2.setLayoutParams(layoutParam2); 122 | relativeLayout0.addView(imageView2); 123 | imageView2.setId(R.id.ccc); 124 | layoutParam2.addRule(RelativeLayout.BELOW,R.id.head); 125 | 126 | return relativeLayout0; 127 | } 128 | } 129 | ``` 130 | #### 生成的映射文件 131 | ```java 132 | 133 | /** 134 | * WARN!!! don't edit this file 135 | * 136 | * author chengwei 137 | * email chengwei@zhangyue.com 138 | */ 139 | public class X2C127_activity implements IViewCreator { 140 | @Override 141 | public View createView(Context context) { 142 | View view = null ; 143 | int sdk = Build.VERSION.SDK_INT; 144 | int orientation = context.getResources().getConfiguration().orientation; 145 | boolean isLandscape = orientation == Configuration.ORIENTATION_LANDSCAPE; 146 | if (isLandscape) { 147 | view = new com.zhangyue.we.x2c.layouts.land.X2C127_Activity().createView(context); 148 | } else if (sdk >= 27) { 149 | view = new com.zhangyue.we.x2c.layouts.v27.X2C127_Activity().createView(context); 150 | } else if (sdk >= 21) { 151 | view = new com.zhangyue.we.x2c.layouts.v21.X2C127_Activity().createView(context); 152 | } else { 153 | view = new com.zhangyue.we.x2c.layouts.X2C127_Activity().createView(context); 154 | } 155 | return view; 156 | } 157 | } 158 | 159 | ``` 160 | # 不支持 161 | * merge标签 ,在编译期间无法确定xml的parent,所以无法支持 162 | * 系统style,在编译期间只能查到应用的style列表,无法查询系统style,所以只支持应用内style 163 | 164 | # 支持 165 | * 兼容ButterKnifer 166 | * 兼容DataBinding 167 | * 各种系统控件、自定义控件 168 | * include标签 169 | * viewStub标签 170 | * fragment标签(感谢[Dreamskya](https://github.com/Dreamskya))提出宝贵意见 171 | * 应用style 172 | * 自定义属性(感谢[Anzhi-Meiying](https://github.com/Anzhi-Meiying)提出的宝贵意见) 173 | * 系统属性 174 | 175 | | 属性名称|属性名称| 176 | | ------ |------- | 177 | |android:textSize| app:layout_constraintRight_toLeftOf| 178 | |android:textColor| app:layout_constraintBottom_toTopOf| 179 | |android:text| app:layout_constraintTop_toTopOf| 180 | |android:background| app:layout_constrainedHeight| 181 | |[查看全部](supportAll.md)| 182 | 183 | 184 | 185 | ## 有使用问题和其他技术问题,欢迎加群交流讨论 186 | 187 | > QQ群:`870956525`,添加请注明来自`X2C` 188 | > 189 | > 掌阅X2C交流群 190 | > 191 | > 欢迎各位使用,该项目会持续维护。 192 | > 193 | > 194 | > 另:欢迎加入[掌阅](http://www.zhangyue.com/jobs)大家庭,一起研究Android新技术。简历请发送`huangjian@zhangyue.com`,注明应聘方向。 195 | > 196 | # LICENSE 197 | 198 | ``` 199 | MIT LICENSE 200 | Copyright (c) 2018 zhangyue 201 | 202 | Permission is hereby granted, free of charge, to any person obtaining 203 | a copy of this software and associated documentation files (the 204 | "Software"), to deal in the Software without restriction, including 205 | without limitation the rights to use, copy, modify, merge, publish, 206 | distribute, sublicense, and/or sell copies of the Software, and to 207 | permit persons to whom the Software is furnished to do so, subject to 208 | the following conditions: 209 | 210 | The above copyright notice and this permission notice shall be 211 | included in all copies or substantial portions of the Software. 212 | 213 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 214 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 215 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 216 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 217 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 218 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 219 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 220 | ``` 221 | -------------------------------------------------------------------------------- /app-databinding/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app-databinding/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 28 5 | defaultConfig { 6 | applicationId "com.zhangyue.we.x2c.demo2" 7 | minSdkVersion 15 8 | targetSdkVersion 28 9 | versionCode 1 10 | versionName "1.0" 11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 12 | javaCompileOptions { 13 | annotationProcessorOptions.includeCompileClasspath = true 14 | } 15 | } 16 | buildTypes { 17 | release { 18 | minifyEnabled false 19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 20 | } 21 | } 22 | dataBinding { 23 | enabled true 24 | } 25 | 26 | } 27 | 28 | dependencies { 29 | implementation fileTree(include: ['*.jar'], dir: 'libs') 30 | implementation 'com.android.support:appcompat-v7:27.1.1' 31 | implementation 'com.android.support.constraint:constraint-layout:2.0.0-alpha2' 32 | implementation 'com.jakewharton:butterknife:8.8.1' 33 | annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1' 34 | 35 | // annotationProcessor project(':x2c-apt') 36 | // implementation project(':x2c-lib') 37 | // if (android.dataBinding.enabled) { 38 | // implementation project(':x2c-binding') 39 | // } 40 | 41 | annotationProcessor 'com.zhangyue.we:x2c-apt:1.0.8' 42 | implementation 'com.zhangyue.we:x2c-lib:1.0.6' 43 | if (android.dataBinding.enabled) { 44 | implementation 'com.zhangyue.we:x2c-binding:1.0.5' 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app-databinding/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app-databinding/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app-databinding/src/main/java/com/zhangyue/demo/databinding/ActivityDataBinding.java: -------------------------------------------------------------------------------- 1 | package com.zhangyue.demo.databinding; 2 | 3 | import android.app.Activity; 4 | import android.databinding.DataBindingX2C; 5 | import android.os.Bundle; 6 | import android.support.annotation.Nullable; 7 | 8 | import com.zhangyue.we.x2c.demo.databinding.ActivityDatabindingBinding; 9 | 10 | import com.zhangyue.we.x2c.ano.Xml; 11 | import com.zhangyue.we.x2c.demo.R; 12 | 13 | /** 14 | * @author:chengwei 2018/9/10 15 | * @description 16 | */ 17 | @Xml(layouts = "activity_databinding") 18 | public class ActivityDataBinding extends Activity { 19 | 20 | 21 | @Override 22 | protected void onCreate(@Nullable Bundle savedInstanceState) { 23 | super.onCreate(savedInstanceState); 24 | ActivityDatabindingBinding binding = DataBindingX2C.setContentView(this, R.layout.activity_databinding); 25 | binding.setBean(new Bean()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app-databinding/src/main/java/com/zhangyue/demo/databinding/Bean.java: -------------------------------------------------------------------------------- 1 | package com.zhangyue.demo.databinding; 2 | 3 | /** 4 | * @author:chengwei 2018/8/31 5 | * @description 6 | */ 7 | public class Bean { 8 | 9 | public String x2c = "X2C"; 10 | public String xml = "XML"; 11 | } 12 | -------------------------------------------------------------------------------- /app-databinding/src/main/res/drawable/head.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iReaderAndroid/X2C/9bdf7ea7bc509481ce9fd1d1ea69b6847b5f832e/app-databinding/src/main/res/drawable/head.jpg -------------------------------------------------------------------------------- /app-databinding/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app-databinding/src/main/res/drawable/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app-databinding/src/main/res/layout/activity_databinding.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 20 | 21 | 22 |