├── app ├── .gitignore ├── src │ ├── main │ │ ├── res │ │ │ ├── values │ │ │ │ ├── strings.xml │ │ │ │ ├── colors.xml │ │ │ │ └── styles.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 │ │ │ │ └── order_ic_shipper_default.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-anydpi-v26 │ │ │ │ ├── ic_launcher.xml │ │ │ │ └── ic_launcher_round.xml │ │ │ ├── drawable-v24 │ │ │ │ └── ic_launcher_foreground.xml │ │ │ ├── layout │ │ │ │ └── activity_main.xml │ │ │ └── drawable │ │ │ │ └── ic_launcher_background.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── zhangzheng │ │ │ │ └── superxml │ │ │ │ └── demo │ │ │ │ ├── MApplication.kt │ │ │ │ └── MainActivity.kt │ │ └── AndroidManifest.xml │ ├── test │ │ └── java │ │ │ └── com │ │ │ └── zhangzheng │ │ │ └── superxml │ │ │ └── demo │ │ │ └── ExampleUnitTest.kt │ └── androidTest │ │ └── java │ │ └── com │ │ └── zhangzheng │ │ └── superxml │ │ └── demo │ │ └── ExampleInstrumentedTest.kt ├── proguard-rules.pro └── build.gradle ├── library ├── consumer-rules.pro ├── .gitignore ├── src │ ├── main │ │ ├── res │ │ │ └── values │ │ │ │ ├── strings.xml │ │ │ │ ├── ids.xml │ │ │ │ └── styles.xml │ │ ├── AndroidManifest.xml │ │ └── java │ │ │ └── com │ │ │ └── zhangzheng │ │ │ └── superxml │ │ │ └── library │ │ │ ├── decorate │ │ │ ├── wrap │ │ │ │ ├── IWrapDecorateView.kt │ │ │ │ ├── coverchildren │ │ │ │ │ ├── ImageViewCoverParse.kt │ │ │ │ │ ├── TextViewCoverParse.kt │ │ │ │ │ ├── CoverChildrenLayout.kt │ │ │ │ │ └── AbsChildViewParse.kt │ │ │ │ ├── CoverChildrenWrapDecorate.kt │ │ │ │ ├── DottedLineWrapDecorate.kt │ │ │ │ └── ScrollWrapDecorate.kt │ │ │ ├── IDecorateView.kt │ │ │ ├── RadiusDecorate.kt │ │ │ ├── SrcRadiusDecorate.kt │ │ │ ├── BorderDecorate.kt │ │ │ ├── TextColorEnableDecorate.kt │ │ │ ├── TextColorPresenterDecorate.kt │ │ │ ├── TextColorSelectedDecorate.kt │ │ │ ├── BackgroundEnableDecorate.kt │ │ │ ├── BackgroundPressedDecorate.kt │ │ │ └── BackgroundSelectedDecorate.kt │ │ │ ├── ext │ │ │ ├── ViewBorderExt.kt │ │ │ └── ViewRadiusExt.kt │ │ │ ├── view │ │ │ └── DottedLineView.kt │ │ │ ├── SuperXml.kt │ │ │ ├── ViewDecorateManager.kt │ │ │ └── LayoutInflateFactoryProxy.kt │ ├── test │ │ └── java │ │ │ └── com │ │ │ └── zhangzheng │ │ │ └── superxml │ │ │ └── library │ │ │ └── ExampleUnitTest.kt │ └── androidTest │ │ └── java │ │ └── com │ │ └── zhangzheng │ │ └── superxml │ │ └── library │ │ └── ExampleInstrumentedTest.kt ├── proguard-rules.pro └── build.gradle ├── settings.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .idea ├── codeStyles │ ├── codeStyleConfig.xml │ └── Project.xml ├── vcs.xml ├── misc.xml ├── runConfigurations.xml └── gradle.xml ├── .gitignore ├── gradle.properties ├── gradlew.bat ├── gradlew └── README.md /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /library/consumer-rules.pro: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /library/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':library' 2 | rootProject.name='SuperXml' 3 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | SuperXml 3 | 4 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/long8313002/SuperXml/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /library/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | library 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/long8313002/SuperXml/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/long8313002/SuperXml/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/long8313002/SuperXml/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/long8313002/SuperXml/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/long8313002/SuperXml/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/long8313002/SuperXml/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/long8313002/SuperXml/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/long8313002/SuperXml/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /library/src/main/res/values/ids.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/long8313002/SuperXml/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/long8313002/SuperXml/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /library/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/order_ic_shipper_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/long8313002/SuperXml/HEAD/app/src/main/res/mipmap-xhdpi/order_ic_shipper_default.png -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #008577 4 | #00574B 5 | #D81B60 6 | 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Sep 16 13:39:55 CST 2020 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip 7 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangzheng/superxml/demo/MApplication.kt: -------------------------------------------------------------------------------- 1 | package com.zhangzheng.superxml.demo 2 | 3 | import android.app.Application 4 | import com.zhangzheng.superxml.library.SuperXml 5 | 6 | class MApplication : Application() { 7 | override fun onCreate() { 8 | super.onCreate() 9 | SuperXml.init(this) 10 | } 11 | } -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /library/src/main/java/com/zhangzheng/superxml/library/decorate/wrap/IWrapDecorateView.kt: -------------------------------------------------------------------------------- 1 | package com.zhangzheng.superxml.library.decorate.wrap 2 | 3 | import android.view.View 4 | import com.zhangzheng.superxml.library.decorate.IDecorateView 5 | 6 | abstract class IWrapDecorateView : 7 | IDecorateView(){ 8 | 9 | override fun decorate(view: View) =Unit 10 | 11 | abstract fun decorateView(view: View):View 12 | } -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/test/java/com/zhangzheng/superxml/demo/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.zhangzheng.superxml.demo 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /library/src/test/java/com/zhangzheng/superxml/library/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.zhangzheng.superxml.library 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /library/src/main/java/com/zhangzheng/superxml/library/decorate/IDecorateView.kt: -------------------------------------------------------------------------------- 1 | package com.zhangzheng.superxml.library.decorate 2 | 3 | import android.content.res.TypedArray 4 | import android.util.AttributeSet 5 | import android.view.View 6 | 7 | 8 | abstract class IDecorateView { 9 | 10 | var hasExtraInfo: Boolean = false 11 | var attributeSet: AttributeSet? = null 12 | 13 | /** 14 | * 初始化解析额外添加的信息 15 | * @return 是否包含额外信息 16 | */ 17 | abstract fun initExtraInfo(typedArray: TypedArray): Boolean 18 | 19 | abstract fun decorate(view: View) 20 | } -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /library/src/main/java/com/zhangzheng/superxml/library/decorate/RadiusDecorate.kt: -------------------------------------------------------------------------------- 1 | package com.zhangzheng.superxml.library.decorate 2 | 3 | import android.content.res.TypedArray 4 | import android.view.View 5 | import com.zhangzheng.superxml.library.R 6 | import com.zhangzheng.superxml.library.ext.setRadius 7 | 8 | internal class RadiusDecorate(var radius: Float = 0f) : IDecorateView() { 9 | 10 | override fun initExtraInfo(typedArray: TypedArray): Boolean { 11 | radius = typedArray.getDimension(R.styleable.decorate_view_layout_radius,0f) 12 | return radius > 0 13 | } 14 | 15 | override fun decorate(view: View)= view.setRadius(radius) 16 | 17 | } -------------------------------------------------------------------------------- /app/src/main/java/com/zhangzheng/superxml/demo/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.zhangzheng.superxml.demo 2 | 3 | import android.graphics.Color 4 | import android.os.Bundle 5 | import android.util.Log 6 | import android.view.LayoutInflater 7 | import android.view.View 8 | import androidx.appcompat.app.AppCompatActivity 9 | import com.zhangzheng.superxml.library.ext.setBorder 10 | import kotlinx.android.synthetic.main.activity_main.* 11 | 12 | class MainActivity : AppCompatActivity() { 13 | 14 | override fun onCreate(savedInstanceState: Bundle?) { 15 | super.onCreate(savedInstanceState) 16 | setContentView(R.layout.activity_main) 17 | 18 | 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /library/src/main/java/com/zhangzheng/superxml/library/decorate/SrcRadiusDecorate.kt: -------------------------------------------------------------------------------- 1 | package com.zhangzheng.superxml.library.decorate 2 | 3 | import android.content.res.TypedArray 4 | import android.view.View 5 | import com.zhangzheng.superxml.library.R 6 | import com.zhangzheng.superxml.library.ext.setRadius 7 | import com.zhangzheng.superxml.library.ext.setSrcRadius 8 | 9 | internal class SrcRadiusDecorate(var radius: Float = 0f) : IDecorateView() { 10 | 11 | override fun initExtraInfo(typedArray: TypedArray): Boolean { 12 | radius = typedArray.getDimension(R.styleable.decorate_view_layout_src_radius,0f) 13 | return radius > 0 14 | } 15 | 16 | override fun decorate(view: View)= view.setSrcRadius(radius) 17 | 18 | } -------------------------------------------------------------------------------- /library/src/main/java/com/zhangzheng/superxml/library/decorate/wrap/coverchildren/ImageViewCoverParse.kt: -------------------------------------------------------------------------------- 1 | package com.zhangzheng.superxml.library.decorate.wrap.coverchildren 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import android.widget.ImageView 6 | 7 | class ImageViewCoverParse : AbsChildViewParse() { 8 | 9 | override fun createInfoView(context: Context, attributeSet: AttributeSet?) = ImageView(context,attributeSet) 10 | 11 | override fun coverAttribute(): MutableList<*> = mutableListOf( 12 | AttributeInfo("src",{ drawable }) { drawable -> setImageDrawable(drawable) }, 13 | AttributeInfo("scaleType",{ scaleType }) { scaleType -> setScaleType(scaleType) } 14 | ) 15 | 16 | } -------------------------------------------------------------------------------- /library/src/main/java/com/zhangzheng/superxml/library/decorate/wrap/CoverChildrenWrapDecorate.kt: -------------------------------------------------------------------------------- 1 | package com.zhangzheng.superxml.library.decorate.wrap 2 | 3 | import android.content.res.TypedArray 4 | import android.view.View 5 | import android.view.ViewGroup 6 | import com.zhangzheng.superxml.library.R 7 | import com.zhangzheng.superxml.library.decorate.wrap.coverchildren.CoverChildrenLayout 8 | 9 | class CoverChildrenWrapDecorate : IWrapDecorateView() { 10 | 11 | override fun initExtraInfo(typedArray: TypedArray) = 12 | typedArray.getBoolean(R.styleable.decorate_view_layout_cover_children, false) 13 | 14 | override fun decorateView(view: View) = 15 | if (view !is ViewGroup) { 16 | view 17 | } else { 18 | CoverChildrenLayout(view, attributeSet) 19 | } 20 | 21 | 22 | } -------------------------------------------------------------------------------- /library/src/main/java/com/zhangzheng/superxml/library/decorate/wrap/DottedLineWrapDecorate.kt: -------------------------------------------------------------------------------- 1 | package com.zhangzheng.superxml.library.decorate.wrap 2 | 3 | import android.content.res.TypedArray 4 | import android.view.View 5 | import com.zhangzheng.superxml.library.R 6 | import com.zhangzheng.superxml.library.view.DottedLineView 7 | 8 | class DottedLineWrapDecorate : IWrapDecorateView() { 9 | 10 | override fun initExtraInfo(typedArray: TypedArray)= 11 | typedArray.getDimension(R.styleable.decorate_view_layout_dash_height, 0f) > 0 12 | && typedArray.getDimension(R.styleable.decorate_view_layout_dash_width, 0f) > 0 13 | 14 | 15 | override fun decorateView(view: View): View { 16 | return DottedLineView(view.context, attributeSet).also { 17 | it.id = view.id 18 | } 19 | } 20 | 21 | 22 | } -------------------------------------------------------------------------------- /app/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 | -------------------------------------------------------------------------------- /library/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/src/androidTest/java/com/zhangzheng/superxml/demo/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.zhangzheng.superxml.demo 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("com.zhangzheng.superxml.demo", appContext.packageName) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /library/src/androidTest/java/com/zhangzheng/superxml/library/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.zhangzheng.superxml.library 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("com.zhangzheng.superxml.library.test", appContext.packageName) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 21 | 22 | -------------------------------------------------------------------------------- /library/src/main/java/com/zhangzheng/superxml/library/decorate/BorderDecorate.kt: -------------------------------------------------------------------------------- 1 | package com.zhangzheng.superxml.library.decorate 2 | 3 | import android.content.res.TypedArray 4 | import android.view.View 5 | import com.zhangzheng.superxml.library.R 6 | import com.zhangzheng.superxml.library.ext.setBorder 7 | 8 | internal class BorderDecorate : IDecorateView() { 9 | 10 | private var borderColor = 0 11 | private var borderWidth = 0 12 | 13 | override fun initExtraInfo(typedArray: TypedArray): Boolean { 14 | borderWidth = typedArray.getDimension( 15 | R.styleable.decorate_view_layout_border_width, 0f 16 | ).toInt() 17 | 18 | borderColor = typedArray.getColor( 19 | R.styleable.decorate_view_layout_border_color, 0 20 | ) 21 | 22 | return borderWidth != 0 && borderColor != 0 23 | } 24 | 25 | override fun decorate(view: View) { 26 | 27 | view.setBorder(borderWidth,borderColor) 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /library/src/main/java/com/zhangzheng/superxml/library/ext/ViewBorderExt.kt: -------------------------------------------------------------------------------- 1 | package com.zhangzheng.superxml.library.ext 2 | 3 | import android.content.res.ColorStateList 4 | import android.graphics.drawable.ColorDrawable 5 | import android.graphics.drawable.Drawable 6 | import android.graphics.drawable.GradientDrawable 7 | import android.view.View 8 | 9 | fun View.setBorder(width: Int, color: Int) { 10 | background = getBorderBg(this, width, color) 11 | } 12 | 13 | 14 | private fun getBorderBg(view: View, width: Int, color: Int): Drawable { 15 | if (view.background !is ColorDrawable && view.background !is GradientDrawable) { 16 | return view.background 17 | } 18 | 19 | val drawable = if (view.background is GradientDrawable) { 20 | view.background as GradientDrawable 21 | } else GradientDrawable().also { 22 | it.color = ColorStateList.valueOf((view.background as ColorDrawable).color) 23 | } 24 | 25 | return drawable.also { 26 | it.setStroke(width, color) 27 | } 28 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx1536m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app's APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Automatically convert third-party libraries to use AndroidX 19 | android.enableJetifier=true 20 | # Kotlin code style for this project: "official" or "obsolete": 21 | kotlin.code.style=official 22 | -------------------------------------------------------------------------------- /library/src/main/java/com/zhangzheng/superxml/library/decorate/TextColorEnableDecorate.kt: -------------------------------------------------------------------------------- 1 | package com.zhangzheng.superxml.library.decorate 2 | 3 | import android.content.res.ColorStateList 4 | import android.content.res.TypedArray 5 | import android.view.View 6 | import android.widget.TextView 7 | import com.zhangzheng.superxml.library.R 8 | 9 | 10 | internal class TextColorEnableDecorate(var color: ColorStateList? = null) : IDecorateView() { 11 | 12 | override fun initExtraInfo(typedArray: TypedArray): Boolean { 13 | val enable = typedArray.getColor( 14 | R.styleable.decorate_view_layout_textColor_enableTrue,0) 15 | val normal = typedArray.getColor( 16 | R.styleable.decorate_view_layout_textColor_enableFalse,0) 17 | if (enable == 0 || normal == 0) { 18 | return false 19 | } 20 | 21 | val states = arrayOfNulls(2) 22 | states[0] = intArrayOf(android.R.attr.state_enabled) 23 | states[1] = intArrayOf(-android.R.attr.state_enabled) 24 | color = ColorStateList(states, intArrayOf(enable,normal)) 25 | 26 | return true 27 | } 28 | 29 | override fun decorate(view: View) { 30 | if(view is TextView){ 31 | view.setTextColor(color) 32 | } 33 | } 34 | 35 | } -------------------------------------------------------------------------------- /library/src/main/java/com/zhangzheng/superxml/library/decorate/TextColorPresenterDecorate.kt: -------------------------------------------------------------------------------- 1 | package com.zhangzheng.superxml.library.decorate 2 | 3 | import android.content.res.ColorStateList 4 | import android.content.res.TypedArray 5 | import android.view.View 6 | import android.widget.TextView 7 | import com.zhangzheng.superxml.library.R 8 | 9 | 10 | internal class TextColorPresenterDecorate(var color: ColorStateList? = null) : IDecorateView() { 11 | 12 | override fun initExtraInfo(typedArray: TypedArray): Boolean { 13 | val pressed = typedArray.getColor( 14 | R.styleable.decorate_view_layout_textColor_pressedTrue,0) 15 | val normal = typedArray.getColor( 16 | R.styleable.decorate_view_layout_textColor_pressedFalse,0) 17 | if (pressed == 0 || normal == 0) { 18 | return false 19 | } 20 | 21 | val states = arrayOfNulls(2) 22 | states[0] = intArrayOf(android.R.attr.state_pressed) 23 | states[1] = intArrayOf(-android.R.attr.state_pressed) 24 | color = ColorStateList(states, intArrayOf(pressed,normal)) 25 | 26 | 27 | return true 28 | } 29 | 30 | override fun decorate(view: View) { 31 | if(view is TextView){ 32 | view.setTextColor(color) 33 | } 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /library/src/main/java/com/zhangzheng/superxml/library/decorate/TextColorSelectedDecorate.kt: -------------------------------------------------------------------------------- 1 | package com.zhangzheng.superxml.library.decorate 2 | 3 | import android.content.res.ColorStateList 4 | import android.content.res.TypedArray 5 | import android.view.View 6 | import android.widget.TextView 7 | import com.zhangzheng.superxml.library.R 8 | 9 | 10 | internal class TextColorSelectedDecorate(var color: ColorStateList? = null) : IDecorateView() { 11 | 12 | override fun initExtraInfo(typedArray: TypedArray): Boolean { 13 | val selected = typedArray.getColor( 14 | R.styleable.decorate_view_layout_textColor_selectedTrue,0) 15 | val normal = typedArray.getColor( 16 | R.styleable.decorate_view_layout_textColor_selectedFalse,0) 17 | if (selected == 0 || normal == 0) { 18 | return false 19 | } 20 | 21 | val states = arrayOfNulls(2) 22 | states[0] = intArrayOf(android.R.attr.state_selected) 23 | states[1] = intArrayOf(-android.R.attr.state_selected) 24 | color = ColorStateList(states, intArrayOf(selected,normal)) 25 | 26 | return true 27 | } 28 | 29 | override fun decorate(view: View) { 30 | if(view is TextView){ 31 | view.setTextColor(color) 32 | } 33 | } 34 | 35 | } -------------------------------------------------------------------------------- /library/src/main/java/com/zhangzheng/superxml/library/decorate/BackgroundEnableDecorate.kt: -------------------------------------------------------------------------------- 1 | package com.zhangzheng.superxml.library.decorate 2 | 3 | import android.content.res.TypedArray 4 | import android.graphics.drawable.StateListDrawable 5 | import android.view.View 6 | import com.zhangzheng.superxml.library.R 7 | import com.zhangzheng.superxml.library.ext.* 8 | 9 | 10 | internal class BackgroundEnableDecorate(var drawable: StateListDrawable? = null) : IDecorateView() { 11 | 12 | override fun initExtraInfo(typedArray: TypedArray): Boolean { 13 | val radius = typedArray.getDimension(R.styleable.decorate_view_layout_radius,0f) 14 | 15 | val enable = createRadiusDrawable(radius,typedArray.getDrawable( 16 | R.styleable.decorate_view_layout_background_enableTrue 17 | )) 18 | val normal = createRadiusDrawable(radius,typedArray.getDrawable( 19 | R.styleable.decorate_view_layout_background_enableFalse 20 | )) 21 | if (enable == null || normal == null) { 22 | return false 23 | } 24 | 25 | drawable = StateListDrawable() 26 | drawable?.addState(intArrayOf(android.R.attr.state_enabled), enable) 27 | drawable?.addState(intArrayOf(-android.R.attr.state_enabled), normal) 28 | return true 29 | } 30 | 31 | 32 | override fun decorate(view: View) { 33 | view.background = drawable 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | apply plugin: 'kotlin-android' 4 | 5 | apply plugin: 'kotlin-android-extensions' 6 | 7 | android { 8 | compileSdkVersion 28 9 | buildToolsVersion "30.0.2" 10 | defaultConfig { 11 | applicationId "com.zhangzheng.superxml.demo" 12 | minSdkVersion 21 13 | targetSdkVersion 28 14 | versionCode 1 15 | versionName "1.0" 16 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 17 | } 18 | buildTypes { 19 | release { 20 | minifyEnabled false 21 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 22 | } 23 | } 24 | 25 | compileOptions { 26 | kotlinOptions.freeCompilerArgs += ['-module-name', "com.zhangzheng.superxml"] 27 | } 28 | } 29 | 30 | dependencies { 31 | implementation fileTree(dir: 'libs', include: ['*.jar']) 32 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 33 | implementation 'androidx.appcompat:appcompat:1.2.0' 34 | implementation 'androidx.core:core-ktx:1.3.1' 35 | implementation 'androidx.constraintlayout:constraintlayout:2.0.1' 36 | testImplementation 'junit:junit:4.12' 37 | androidTestImplementation 'androidx.test.ext:junit:1.1.2' 38 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' 39 | 40 | implementation project(":library") 41 | } 42 | 43 | 44 | -------------------------------------------------------------------------------- /library/src/main/java/com/zhangzheng/superxml/library/decorate/wrap/coverchildren/TextViewCoverParse.kt: -------------------------------------------------------------------------------- 1 | package com.zhangzheng.superxml.library.decorate.wrap.coverchildren 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import android.widget.TextView 6 | 7 | class TextViewCoverParse : AbsChildViewParse() { 8 | 9 | override fun createInfoView(context: Context, attributeSet: AttributeSet?): TextView = 10 | TextView(context, attributeSet) 11 | 12 | override fun coverAttribute(): MutableList<*> = mutableListOf( 13 | AttributeInfo("textSize",{ textSize }) { value -> textSize = value }, 14 | AttributeInfo("textColor",{ textColors }) { value -> setTextColor(value) }, 15 | AttributeInfo("text",{ text }) { text -> setText(text) }, 16 | AttributeInfo("maxLines",{ maxLines }) { maxLines -> setMaxLines(maxLines) }, 17 | AttributeInfo("maxEms",{ maxEms }) { maxEms -> setMaxEms(maxEms) }, 18 | AttributeInfo("textColorHint",{ hintTextColors }) { hintTextColors -> setHintTextColor(hintTextColors) }, 19 | AttributeInfo("hint",{ hint }) { hint -> setHint(hint) }, 20 | AttributeInfo("textDirection",{ textDirection }) { textDirection -> setTextDirection(textDirection) }, 21 | AttributeInfo("textStyle",{ typeface }) { typeface -> setTypeface(typeface) }, 22 | AttributeInfo("capitalize",{ inputType }) { inputType -> setInputType(inputType) } 23 | ) 24 | 25 | 26 | 27 | } -------------------------------------------------------------------------------- /library/src/main/java/com/zhangzheng/superxml/library/decorate/BackgroundPressedDecorate.kt: -------------------------------------------------------------------------------- 1 | package com.zhangzheng.superxml.library.decorate 2 | 3 | import android.content.res.TypedArray 4 | import android.graphics.drawable.StateListDrawable 5 | import android.view.View 6 | import com.zhangzheng.superxml.library.R 7 | import com.zhangzheng.superxml.library.ext.createRadiusDrawable 8 | 9 | 10 | internal class BackgroundPressedDecorate(var drawable: StateListDrawable? = null) : 11 | IDecorateView() { 12 | 13 | 14 | override fun initExtraInfo(typedArray: TypedArray): Boolean { 15 | val radius = typedArray.getDimension(R.styleable.decorate_view_layout_radius, 0f) 16 | 17 | val press = createRadiusDrawable( 18 | radius, typedArray.getDrawable( 19 | R.styleable.decorate_view_layout_background_pressedTrue 20 | ) 21 | ) 22 | val normal = createRadiusDrawable( 23 | radius, typedArray.getDrawable( 24 | R.styleable.decorate_view_layout_background_pressedFalse 25 | ) 26 | ) 27 | if (press == null || normal == null) { 28 | return false 29 | } 30 | 31 | drawable = StateListDrawable() 32 | drawable?.addState(intArrayOf(android.R.attr.state_pressed), press) 33 | drawable?.addState(intArrayOf(-android.R.attr.state_pressed), normal) 34 | return true 35 | } 36 | 37 | override fun decorate(view: View) { 38 | view.background = drawable 39 | } 40 | 41 | } -------------------------------------------------------------------------------- /library/src/main/java/com/zhangzheng/superxml/library/decorate/BackgroundSelectedDecorate.kt: -------------------------------------------------------------------------------- 1 | package com.zhangzheng.superxml.library.decorate 2 | 3 | import android.content.res.TypedArray 4 | import android.graphics.drawable.StateListDrawable 5 | import android.view.View 6 | import com.zhangzheng.superxml.library.R 7 | import com.zhangzheng.superxml.library.ext.createRadiusDrawable 8 | 9 | 10 | internal class BackgroundSelectedDecorate(var drawable: StateListDrawable? = null) : 11 | IDecorateView() { 12 | 13 | override fun initExtraInfo(typedArray: TypedArray): Boolean { 14 | 15 | val radius = typedArray.getDimension(R.styleable.decorate_view_layout_radius, 0f) 16 | 17 | val selected = createRadiusDrawable( 18 | radius, typedArray.getDrawable( 19 | R.styleable.decorate_view_layout_background_selectedTrue 20 | ) 21 | ) 22 | 23 | val normal = createRadiusDrawable( 24 | radius, typedArray.getDrawable( 25 | R.styleable.decorate_view_layout_background_selectedFalse 26 | ) 27 | ) 28 | 29 | if (selected == null || normal == null) { 30 | return false 31 | } 32 | 33 | drawable = StateListDrawable() 34 | drawable?.addState(intArrayOf(android.R.attr.state_selected), selected) 35 | drawable?.addState(intArrayOf(-android.R.attr.state_selected), normal) 36 | return true 37 | } 38 | 39 | override fun decorate(view: View) { 40 | view.background = drawable 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /library/src/main/java/com/zhangzheng/superxml/library/decorate/wrap/ScrollWrapDecorate.kt: -------------------------------------------------------------------------------- 1 | package com.zhangzheng.superxml.library.decorate.wrap 2 | 3 | import android.content.res.TypedArray 4 | import android.graphics.Color 5 | import android.util.AttributeSet 6 | import android.view.View 7 | import android.view.ViewGroup 8 | import android.widget.ScrollView 9 | import com.zhangzheng.superxml.library.R 10 | 11 | private class ScrollViewProxy(val view: View,attributeSet: AttributeSet?) : ScrollView(view.context,attributeSet) { 12 | 13 | init { 14 | setBackgroundColor(Color.TRANSPARENT) 15 | } 16 | 17 | override fun addView(child: View?, index: Int, params: ViewGroup.LayoutParams?) { 18 | if (child?.parent != null) { 19 | return 20 | } 21 | if (child == view) { 22 | super.addView(child, index, params) 23 | } else if (view is ViewGroup) { 24 | view.addView(child, index, params) 25 | } 26 | } 27 | 28 | override fun onFinishInflate() { 29 | super.onFinishInflate() 30 | addView(view) 31 | id = R.id.decorateScrollView 32 | } 33 | } 34 | 35 | 36 | internal class ScrollWrapDecorate(var canScroll: Boolean = false) : IWrapDecorateView() { 37 | 38 | override fun initExtraInfo(typedArray: TypedArray): Boolean { 39 | canScroll = typedArray.getBoolean(R.styleable.decorate_view_layout_canScroll, false) 40 | return canScroll 41 | } 42 | 43 | override fun decorateView(view: View): View { 44 | return ScrollViewProxy( 45 | view, 46 | attributeSet 47 | ) 48 | } 49 | 50 | 51 | } -------------------------------------------------------------------------------- /library/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /library/src/main/java/com/zhangzheng/superxml/library/view/DottedLineView.kt: -------------------------------------------------------------------------------- 1 | package com.zhangzheng.superxml.library.view 2 | 3 | import android.content.Context 4 | import android.content.res.TypedArray 5 | import android.graphics.Canvas 6 | import android.util.AttributeSet 7 | import android.view.View 8 | import com.zhangzheng.superxml.library.R 9 | 10 | internal class DottedLineView : View { 11 | 12 | private var dashWidth = 0 13 | private var dashHeight = 0 14 | private var dashGap = 0 15 | 16 | constructor(context: Context?) : super(context) 17 | constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) { 18 | val typedArray: TypedArray = 19 | context!!.obtainStyledAttributes(attrs, R.styleable.decorate_view) 20 | dashWidth = typedArray.getDimension( 21 | R.styleable.decorate_view_layout_dash_width, 0f 22 | ).toInt() 23 | 24 | dashHeight = typedArray.getDimension( 25 | R.styleable.decorate_view_layout_dash_height, 0f 26 | ).toInt() 27 | 28 | dashGap = typedArray.getDimension( 29 | R.styleable.decorate_view_layout_dash_gap, 0f 30 | ).toInt() 31 | 32 | typedArray.recycle() 33 | } 34 | 35 | constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super( 36 | context, 37 | attrs, 38 | defStyleAttr 39 | ) 40 | 41 | 42 | override fun onDraw(canvas: Canvas) { 43 | 44 | background.setBounds(0, 0, dashWidth, dashHeight) 45 | background.draw(canvas) 46 | 47 | if (width > height) { 48 | var translateX = 0 49 | while (translateX <= width) { 50 | canvas.translate((dashWidth + dashGap).toFloat(), 0f) 51 | background.draw(canvas) 52 | translateX += dashWidth + dashGap 53 | } 54 | }else{ 55 | var translateY = 0 56 | while (translateY <= height) { 57 | canvas.translate(0f, (dashHeight + dashGap).toFloat()) 58 | background.draw(canvas) 59 | translateY += dashHeight + dashGap 60 | } 61 | } 62 | 63 | 64 | } 65 | } -------------------------------------------------------------------------------- /library/src/main/java/com/zhangzheng/superxml/library/decorate/wrap/coverchildren/CoverChildrenLayout.kt: -------------------------------------------------------------------------------- 1 | package com.zhangzheng.superxml.library.decorate.wrap.coverchildren 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import android.view.View 6 | import android.view.ViewGroup 7 | import android.widget.FrameLayout 8 | 9 | interface IChildViewParse { 10 | 11 | fun init(context: Context) 12 | 13 | fun parentAttribute(attributeSet: AttributeSet?) 14 | 15 | fun childAttribute(childViewAttr: AttributeSet?) 16 | 17 | fun updateChildView(view: View) 18 | } 19 | 20 | private val childViewParseList = mutableListOf( 21 | TextViewCoverParse(), 22 | ImageViewCoverParse() 23 | ) 24 | 25 | fun addCoverChildViewParse(parse:IChildViewParse){ 26 | childViewParseList.add(parse) 27 | } 28 | 29 | class CoverChildrenLayout(var baseView: ViewGroup, attributeSet: AttributeSet?) : FrameLayout(baseView.context) { 30 | 31 | init { 32 | childViewParseList.forEach { it.init(context) } 33 | childViewParseList.forEach { it.parentAttribute(attributeSet) } 34 | } 35 | 36 | override fun addView(child: View?, index: Int, params: ViewGroup.LayoutParams?) { 37 | baseView.addView(child, index, params) 38 | childViewParseList.forEach { 39 | if (child != null) { 40 | it.updateChildView(child) 41 | } 42 | } 43 | } 44 | 45 | override fun onAttachedToWindow() { 46 | super.onAttachedToWindow() 47 | (parent as ViewGroup).addView(baseView, removeSelf()) 48 | } 49 | 50 | override fun generateLayoutParams(attrs: AttributeSet?): LayoutParams { 51 | childViewParseList.forEach { it.childAttribute(attrs) } 52 | return super.generateLayoutParams(attrs) 53 | } 54 | 55 | private fun removeSelf(): Int { 56 | val parent = parent as ViewGroup 57 | var index = 0 58 | for (i in 0 until parent.childCount) { 59 | if (parent.getChildAt(i) == this) { 60 | parent.removeView(this) 61 | break 62 | } 63 | index++ 64 | } 65 | return index 66 | } 67 | } -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /library/src/main/java/com/zhangzheng/superxml/library/SuperXml.kt: -------------------------------------------------------------------------------- 1 | package com.zhangzheng.superxml.library 2 | 3 | import android.app.Activity 4 | import android.app.Application 5 | import android.os.Bundle 6 | import android.util.AttributeSet 7 | import android.view.LayoutInflater 8 | import android.view.View 9 | import com.zhangzheng.superxml.library.decorate.IDecorateView 10 | import com.zhangzheng.superxml.library.decorate.wrap.IWrapDecorateView 11 | import com.zhangzheng.superxml.library.decorate.wrap.coverchildren.IChildViewParse 12 | import com.zhangzheng.superxml.library.decorate.wrap.coverchildren.addCoverChildViewParse 13 | 14 | object SuperXml { 15 | 16 | fun addDecorate(decorate: IWrapDecorateView) = ViewDecorateManager.addDecorate(decorate) 17 | 18 | fun addDecorate(decorate: IDecorateView) = ViewDecorateManager.addDecorate(decorate) 19 | 20 | fun addCoverAttributeParse(parse: IChildViewParse){ 21 | addCoverChildViewParse(parse) 22 | } 23 | 24 | fun init(app: Application) { 25 | app.registerActivityLifecycleCallbacks(object : Application.ActivityLifecycleCallbacks { 26 | override fun onActivityCreated(p0: Activity, p1: Bundle?) = hookActivityLayout(p0) 27 | override fun onActivityPaused(p0: Activity) = Unit 28 | override fun onActivityStarted(p0: Activity) = Unit 29 | override fun onActivityDestroyed(p0: Activity) = Unit 30 | override fun onActivitySaveInstanceState(p0: Activity, p1: Bundle) = Unit 31 | override fun onActivityStopped(p0: Activity) = Unit 32 | override fun onActivityResumed(p0: Activity) = Unit 33 | }) 34 | } 35 | 36 | private fun hookActivityLayout(activity: Activity) { 37 | val layoutInflater = LayoutInflater.from(activity) 38 | setLayoutInflateAllowState(layoutInflater, true) 39 | layoutInflater.factory2 = 40 | LayoutInflateFactoryProxy(layoutInflater, object : LayoutInflateFactoryProxy.IService { 41 | override fun hasDecorate(attrs: AttributeSet) = 42 | ViewDecorateManager.hasDecorate(activity, attrs) 43 | 44 | override fun decorate(view: View) = ViewDecorateManager.decorate(view) 45 | }) 46 | setLayoutInflateAllowState(layoutInflater, false) 47 | } 48 | 49 | private fun setLayoutInflateAllowState(layoutInflater: LayoutInflater, isAllow: Boolean) { 50 | val mFactorySet = LayoutInflater::class.java.getDeclaredField("mFactorySet") 51 | mFactorySet.isAccessible = true 52 | mFactorySet.set(layoutInflater, !isAllow) 53 | } 54 | } -------------------------------------------------------------------------------- /library/src/main/java/com/zhangzheng/superxml/library/decorate/wrap/coverchildren/AbsChildViewParse.kt: -------------------------------------------------------------------------------- 1 | package com.zhangzheng.superxml.library.decorate.wrap.coverchildren 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import android.view.View 6 | 7 | abstract class AbsChildViewParse : IChildViewParse { 8 | 9 | inner class AttributeInfo( 10 | var name: String, 11 | var getAttr: T.() -> M, 12 | var setAttr: T.(value: M) -> Unit 13 | ) 14 | 15 | private lateinit var infoView: T 16 | private lateinit var coverAttribute: MutableList<*> 17 | private lateinit var updateAttribute: MutableList<*> 18 | protected lateinit var context:Context 19 | 20 | override fun init(context: Context) { 21 | this.context = context 22 | } 23 | 24 | override fun parentAttribute(attributeSet: AttributeSet?) { 25 | infoView = createInfoView(context, attributeSet) 26 | coverAttribute = coverAttribute() 27 | filterAttribute(coverAttribute,attributeSet, false) 28 | } 29 | 30 | private fun filterAttribute(attributeList: MutableList<*>, attributeSet: AttributeSet?, hasAttrFilter: Boolean) { 31 | val iterator = attributeList.iterator() 32 | while (iterator.hasNext()) { 33 | val item = iterator.next() as AttributeInfo 34 | val name = item.name 35 | if ((hasAttrFilter && hasAttribute(attributeSet, name)) 36 | || (!hasAttrFilter && !hasAttribute(attributeSet, name)) 37 | ) { 38 | iterator.remove() 39 | } 40 | } 41 | } 42 | 43 | private fun hasAttribute(attributeSet: AttributeSet?, name: String): Boolean { 44 | val nameSpace = "http://schemas.android.com/apk/res/android" 45 | return attributeSet?.getAttributeValue(nameSpace, name)?.isNotEmpty() == true 46 | } 47 | 48 | override fun childAttribute(childViewAttr: AttributeSet?) { 49 | updateAttribute = ArrayList(coverAttribute) 50 | filterAttribute(updateAttribute,childViewAttr, true) 51 | } 52 | 53 | abstract fun createInfoView(context: Context, attributeSet: AttributeSet?): T 54 | 55 | abstract fun coverAttribute(): MutableList<*> 56 | 57 | override fun updateChildView(childView: View) { 58 | updateAttribute.forEach { 59 | try { 60 | it as AttributeInfo 61 | val value = it.getAttr(infoView) 62 | it.setAttr(childView as T, value) 63 | }catch (e:ClassCastException){ 64 | 65 | } 66 | } 67 | } 68 | 69 | 70 | } -------------------------------------------------------------------------------- /library/src/main/java/com/zhangzheng/superxml/library/ViewDecorateManager.kt: -------------------------------------------------------------------------------- 1 | package com.zhangzheng.superxml.library 2 | 3 | import android.content.Context 4 | import android.content.res.TypedArray 5 | import android.util.AttributeSet 6 | import android.view.View 7 | import com.zhangzheng.superxml.library.decorate.* 8 | import com.zhangzheng.superxml.library.decorate.RadiusDecorate 9 | import com.zhangzheng.superxml.library.decorate.SrcRadiusDecorate 10 | import com.zhangzheng.superxml.library.decorate.wrap.CoverChildrenWrapDecorate 11 | import com.zhangzheng.superxml.library.decorate.wrap.DottedLineWrapDecorate 12 | import com.zhangzheng.superxml.library.decorate.wrap.IWrapDecorateView 13 | import com.zhangzheng.superxml.library.decorate.wrap.ScrollWrapDecorate 14 | 15 | internal object ViewDecorateManager { 16 | 17 | private val decorateList = arrayListOf( 18 | RadiusDecorate(), 19 | SrcRadiusDecorate(), 20 | BackgroundPressedDecorate(), 21 | BackgroundSelectedDecorate(), 22 | BackgroundEnableDecorate(), 23 | TextColorEnableDecorate(), 24 | TextColorPresenterDecorate(), 25 | TextColorSelectedDecorate(), 26 | BorderDecorate() 27 | ) 28 | 29 | private val wrapDecorateList = arrayListOf( 30 | ScrollWrapDecorate(), 31 | DottedLineWrapDecorate(), 32 | CoverChildrenWrapDecorate() 33 | ) 34 | 35 | fun addDecorate(decorate: IWrapDecorateView){ 36 | wrapDecorateList.add(decorate) 37 | } 38 | 39 | fun addDecorate(decorate:IDecorateView){ 40 | decorateList.add(decorate) 41 | } 42 | 43 | 44 | fun hasDecorate(context: Context, attributeSet: AttributeSet): Boolean { 45 | val typedArray: TypedArray = context.obtainStyledAttributes( 46 | attributeSet, R.styleable.decorate_view 47 | ) 48 | 49 | var hasDecorateInfo = false 50 | (decorateList + wrapDecorateList).forEach { 51 | it.attributeSet = attributeSet 52 | if (it.initExtraInfo(typedArray)) { 53 | hasDecorateInfo = true 54 | it.hasExtraInfo = true 55 | } else { 56 | it.hasExtraInfo = false 57 | } 58 | } 59 | 60 | typedArray.recycle() 61 | 62 | return hasDecorateInfo 63 | } 64 | 65 | fun decorate(view: View): View { 66 | 67 | decorateList.forEach { 68 | if (it.hasExtraInfo) { 69 | it.decorate(view) 70 | } 71 | } 72 | 73 | var wrapView = view 74 | wrapDecorateList.forEach { 75 | if (it.hasExtraInfo) { 76 | wrapView = it.decorateView(wrapView) 77 | } 78 | } 79 | return wrapView 80 | } 81 | } -------------------------------------------------------------------------------- /library/src/main/java/com/zhangzheng/superxml/library/ext/ViewRadiusExt.kt: -------------------------------------------------------------------------------- 1 | package com.zhangzheng.superxml.library.ext 2 | 3 | import android.graphics.* 4 | import android.graphics.drawable.BitmapDrawable 5 | import android.graphics.drawable.ColorDrawable 6 | import android.graphics.drawable.Drawable 7 | import android.graphics.drawable.GradientDrawable 8 | import android.view.View 9 | import android.widget.ImageView 10 | 11 | 12 | fun View.setRadius(radius: Float) { 13 | val backgroundColor = getBackgroundColor(this) 14 | val background = getBackground(this) 15 | if (backgroundColor != null) { 16 | this.background = getRoundRectBgByColorValue( backgroundColor, radius) 17 | }else if(background!=null){ 18 | this.background = BitmapDrawable(toRoundCorner(background,radius)) 19 | } 20 | } 21 | 22 | fun View.setSrcRadius(radius: Float){ 23 | 24 | if(this is ImageView){ 25 | val src = drawable 26 | if(src is BitmapDrawable){ 27 | setImageBitmap(toRoundCorner(src.bitmap,radius)) 28 | } 29 | } 30 | } 31 | 32 | internal fun createRadiusDrawable(radius: Float,drawable: Drawable?):Drawable?{ 33 | if(drawable is ColorDrawable){ 34 | return getRoundRectBgByColorValue( drawable.color, radius) 35 | } 36 | 37 | if(drawable is BitmapDrawable){ 38 | return BitmapDrawable(toRoundCorner(drawable.bitmap,radius)) 39 | } 40 | 41 | return drawable 42 | } 43 | 44 | 45 | private fun getRoundRectBgByColorValue( color: Int, radius: Float) :Drawable{ 46 | return GradientDrawable().also { 47 | it.shape = GradientDrawable.RECTANGLE 48 | it.cornerRadius = radius 49 | it.setColor(color) 50 | } 51 | } 52 | 53 | 54 | private fun getBackgroundColor(view: View): Int? { 55 | var bgColor: Int? = null 56 | if (view.background is ColorDrawable) { 57 | val colorDrawable = view.background as ColorDrawable 58 | bgColor = colorDrawable.color 59 | } 60 | return bgColor 61 | } 62 | 63 | private fun getBackground(view: View): Bitmap? { 64 | val background = view.background 65 | return if (background is BitmapDrawable) { 66 | background.bitmap 67 | } else { 68 | null 69 | } 70 | } 71 | 72 | private fun toRoundCorner(bitmap: Bitmap, pixels: Float): Bitmap? { 73 | val output = 74 | Bitmap.createBitmap(bitmap.width, bitmap.height, Bitmap.Config.ARGB_8888) 75 | val canvas = Canvas(output) 76 | val paint = Paint() 77 | val rect = Rect(0, 0, bitmap.width, bitmap.height) 78 | val rectF = RectF(rect) 79 | paint.isAntiAlias = true 80 | canvas.drawARGB(0, 0, 0, 0) 81 | canvas.drawRoundRect(rectF, pixels/2, pixels/2, paint) 82 | paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN) 83 | canvas.drawBitmap(bitmap, rect, rect, paint) 84 | return output 85 | } 86 | -------------------------------------------------------------------------------- /library/src/main/java/com/zhangzheng/superxml/library/LayoutInflateFactoryProxy.kt: -------------------------------------------------------------------------------- 1 | package com.zhangzheng.superxml.library 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import android.view.LayoutInflater 6 | import android.view.View 7 | import java.lang.Exception 8 | 9 | 10 | 11 | internal class LayoutInflateFactoryProxy(layoutInflater: LayoutInflater, private var service:IService ): LayoutInflater.Factory2 { 12 | 13 | interface IService { 14 | fun hasDecorate(attrs: AttributeSet): Boolean 15 | 16 | fun decorate(view: View):View 17 | } 18 | 19 | private var factory = layoutInflater.factory 20 | private var factory2 = layoutInflater.factory2 21 | private var cloneLayoutInflate = layoutInflater.cloneInContext(layoutInflater.context) 22 | 23 | override fun onCreateView(parent: View?, name: String?, context: Context?, 24 | attrs: AttributeSet?): View? { 25 | 26 | if(attrs==null||!service.hasDecorate(attrs)){ 27 | return null 28 | } 29 | 30 | var view = factory2?.onCreateView(parent, name, context, attrs) 31 | if (view == null) { 32 | view = factory?.onCreateView(name, context, attrs) 33 | } 34 | if (view == null) { 35 | view = createView(name, null, attrs) 36 | } 37 | if (view == null) { 38 | view = createView(name, "android.widget.", attrs) 39 | } 40 | if (view == null) { 41 | view = createView(name, "android.view.", attrs) 42 | } 43 | 44 | if (view == null) { 45 | view = compensateCreateView(name,context,attrs) 46 | } 47 | 48 | 49 | 50 | if (view != null) { 51 | view = service.decorate(view) 52 | } 53 | 54 | return view 55 | } 56 | 57 | private fun compensateCreateView(name: String?, context: Context?, attrs: AttributeSet?): View? { 58 | if (name == null || context == null || attrs == null) { 59 | return null 60 | } 61 | var view = reflexCreateView(name, context, attrs) 62 | if (view == null) { 63 | view = reflexCreateView("android.widget.$name", context, attrs) 64 | } 65 | if (view == null) { 66 | view = reflexCreateView("android.view.$name", context, attrs) 67 | } 68 | return view 69 | } 70 | 71 | private fun reflexCreateView(name: String, context: Context, attrs: AttributeSet): View? { 72 | try { 73 | val clazz = Class.forName(name) 74 | val constructor = clazz.getConstructor(Context::class.java, AttributeSet::class.java) 75 | return constructor.newInstance(context, attrs) as View 76 | } catch (e: Exception) { 77 | 78 | } 79 | return null 80 | } 81 | 82 | private fun createView(name: String?, prefix: String?, attrs: AttributeSet?): View? { 83 | return try { 84 | cloneLayoutInflate.createView(name, prefix, attrs) 85 | } catch (e: Exception) { 86 | null 87 | } 88 | } 89 | 90 | override fun onCreateView(name: String?, context: Context?, attrs: AttributeSet?) = 91 | onCreateView(null, name, context, attrs) 92 | 93 | 94 | } -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | xmlns:android 17 | 18 | ^$ 19 | 20 | 21 | 22 |
23 |
24 | 25 | 26 | 27 | xmlns:.* 28 | 29 | ^$ 30 | 31 | 32 | BY_NAME 33 | 34 |
35 |
36 | 37 | 38 | 39 | .*:id 40 | 41 | http://schemas.android.com/apk/res/android 42 | 43 | 44 | 45 |
46 |
47 | 48 | 49 | 50 | .*:name 51 | 52 | http://schemas.android.com/apk/res/android 53 | 54 | 55 | 56 |
57 |
58 | 59 | 60 | 61 | name 62 | 63 | ^$ 64 | 65 | 66 | 67 |
68 |
69 | 70 | 71 | 72 | style 73 | 74 | ^$ 75 | 76 | 77 | 78 |
79 |
80 | 81 | 82 | 83 | .* 84 | 85 | ^$ 86 | 87 | 88 | BY_NAME 89 | 90 |
91 |
92 | 93 | 94 | 95 | .* 96 | 97 | http://schemas.android.com/apk/res/android 98 | 99 | 100 | ANDROID_ATTRIBUTE_ORDER 101 | 102 |
103 |
104 | 105 | 106 | 107 | .* 108 | 109 | .* 110 | 111 | 112 | BY_NAME 113 | 114 |
115 |
116 |
117 |
118 | 119 | 121 |
122 |
-------------------------------------------------------------------------------- /library/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'kotlin-android-extensions' 4 | android { 5 | compileSdkVersion 28 6 | buildToolsVersion "30.0.2" 7 | 8 | 9 | defaultConfig { 10 | minSdkVersion 21 11 | targetSdkVersion 28 12 | versionCode 1 13 | versionName "1.0" 14 | 15 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 16 | consumerProguardFiles 'consumer-rules.pro' 17 | } 18 | 19 | buildTypes { 20 | release { 21 | minifyEnabled false 22 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 23 | } 24 | } 25 | 26 | compileOptions { 27 | kotlinOptions.freeCompilerArgs += ['-module-name', "com.zhangzheng.superxml"] 28 | } 29 | 30 | } 31 | 32 | dependencies { 33 | compileOnly "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 34 | } 35 | 36 | 37 | 38 | /** 以下开始是将Android Library上传到JCenter的相关配置**/ 39 | 40 | apply plugin: 'com.github.dcendents.android-maven' 41 | apply plugin: 'com.jfrog.bintray' 42 | 43 | //项目主页 44 | def siteUrl = 'https://github.com/long8313002/SuperXml' 45 | //项目的版本控制地址 46 | def gitUrl = 'https://github.com/long8313002/SuperXml' 47 | 48 | //发布到组织名称名字,必须填写 49 | group = "com.zhangzheng.superxml" 50 | //发布到JCenter上的项目名字,必须填写 51 | def libName = "SuperXml" 52 | // 版本号,下次更新是只需要更改版本号即可 53 | version = "1.1.4" 54 | /** 上面配置后上传至JCenter后的编译路径是这样的: compile 'group:libName:version' **/ 55 | 56 | //生成源文件 57 | task sourcesJar(type: Jar) { 58 | from android.sourceSets.main.java.srcDirs 59 | classifier = 'sources' 60 | } 61 | //生成文档 62 | task javadoc(type: Javadoc) { 63 | source = android.sourceSets.main.java.srcDirs 64 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) 65 | options.encoding "UTF-8" 66 | options.charSet 'UTF-8' 67 | options.author true 68 | options.version true 69 | options.links "https://github.com/long8313002/CrashProtect" 70 | failOnError false 71 | } 72 | 73 | //文档打包成jar 74 | task javadocJar(type: Jar, dependsOn: javadoc) { 75 | classifier = 'javadoc' 76 | from javadoc.destinationDir 77 | } 78 | //拷贝javadoc文件 79 | task copyDoc(type: Copy) { 80 | from "${buildDir}/docs/" 81 | into "docs" 82 | } 83 | 84 | //上传到jCenter所需要的源码文件 85 | artifacts { 86 | archives javadocJar 87 | archives sourcesJar 88 | } 89 | 90 | // 配置maven库,生成POM.xml文件 91 | install { 92 | repositories.mavenInstaller { 93 | // This generates POM.xml with proper parameters 94 | pom { 95 | project { 96 | packaging 'aar' 97 | name 'SuperXml' 98 | url siteUrl 99 | licenses { 100 | license { 101 | name 'The Apache Software License, Version 2.0' 102 | url 'http://www.apache.org/licenses/LICENSE-2.0.txt' 103 | } 104 | } 105 | developers { 106 | developer { 107 | id 'zhangzheng' 108 | name 'zhangzheng' 109 | email 'zhangzheng@xyz.cn' 110 | } 111 | } 112 | scm { 113 | connection gitUrl 114 | developerConnection gitUrl 115 | url siteUrl 116 | } 117 | } 118 | } 119 | } 120 | } 121 | 122 | //上传到JCenter 123 | Properties properties = new Properties() 124 | properties.load(project.rootProject.file('local.properties').newDataInputStream()) 125 | bintray { 126 | user = properties.getProperty("bintray.user") //读取 local.properties 文件里面的 bintray.user 127 | key = properties.getProperty("bintray.apikey") //读取 local.properties 文件里面的 bintray.apikey 128 | println("-----"+user+"-----"+key) 129 | configurations = ['archives'] 130 | pkg { 131 | repo = "maven" 132 | name = libName //发布到JCenter上的项目名字,必须填写 133 | desc = 'SuperXml' //项目描述 134 | websiteUrl = siteUrl 135 | vcsUrl = gitUrl 136 | licenses = ["Apache-2.0"] 137 | publish = true 138 | } 139 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 |