├── 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 |
4 |
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 |
8 |
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 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
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 |
5 |
6 |
7 |
8 |
9 |
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 |
120 |
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 |
22 |
23 |
32 |
33 |
38 |
39 |
46 |
47 |
53 |
54 |
60 |
61 |
67 |
68 |
69 |
70 |
79 |
80 |
81 |
87 |
88 |
97 |
98 |
104 |
105 |
111 |
112 |
113 |
121 |
122 |
123 |
133 |
134 |
139 |
140 |
144 |
145 |
149 |
150 |
151 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/app/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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # android布局能力增加,轻松实现圆角、边框、虚线、属性覆盖等功能。完全无侵入
3 |
4 | 有排版: https://blog.csdn.net/long8313002/article/details/108703057
5 |
6 |
7 | 概述
8 |
9 | android开发中,我们常常使用xml来写布局文件,这种实现方式不仅简单,而且表达能力更强。但是google提供的布局属性有限,有些功能的实现我们不得不使用代码,或者自定义控件的方式来实现。那有没有一种方法,可以将属性增强来实现额外的功能呢?例如我们常常使用background 来表示和设置背景,那是不是可以使用layout_radius来表示和设置圆角呢?
10 |
11 |
12 |
13 | 使用示例
14 | 需要在项目build.gradle中引用依赖
15 |
16 | implementation 'com.zhangzheng.superxml:library:1.1.0'
17 | 另外在Application注册一行代码
18 |
19 | SuperXml.init(this)
20 | OVER
21 |
22 |
23 |
24 | 能力说明
25 |
26 | 属性增强
27 | 圆角:
28 |
34 | 说明
35 |
36 | app:layout_radius 支持将控件背景设置为圆角,背景支持纯色背景或者图片,另外对于ImageView 的src如果想设置成圆角需要使用app:layout_src_radius,例如
37 |
38 |
44 |
45 |
46 | 复合属性
47 |
48 |
49 |
56 | 说明
57 |
58 | 一般情况下,我们要表示点击和普通状态下不同的字体颜色,或者背景会使用selector来定义一个文件,然后在布局文件中引用,一方面这样的使用很麻烦,另外一方面可读性也会降低(用户需要进入selector文件进行分析,才知道代码表达意图)。这边封装了常用的复用属性,如下:
59 |
60 | 属性 属性类型 说明
61 | layout_background_enableTrue
62 | layout_background_enableFalse
63 | reference|color(资源或者颜色)
64 | 背景(是否可用)
65 | layout_background_pressedTrue
66 | layout_background_pressedFalse
67 | reference|color(资源或者颜色) 背景(是否按压)
68 | layout_background_selectedTrue
69 | layout_background_selectedTrue
70 | reference|color(资源或者颜色) 背景(是否选择)
71 | layout_textColor_enableTrue
72 | layout_textColor_enableFalse
73 | reference|color(资源或者颜色) 字体颜色(是否可用)
74 | layout_textColor_pressedTrue
75 | layout_textColor_pressedFalse
76 |
77 |
78 | reference|color(资源或者颜色) 字体颜色(是否按压)
79 | layout_textColor_selectedTrue
80 | layout_textColor_selectedFalse
81 | reference|color(资源或者颜色) 字体颜色(是否选择)
82 |
83 |
84 | 边框
85 |
94 |
95 |
96 | 说明
97 |
98 | 比较简单,layout_border_color表示边框颜色,layout_border_width表示边框粗细,和radius一起使用表示边框圆角。
99 |
100 |
101 |
102 |
103 |
104 | 虚线
105 |
113 |
114 |
115 | 说明
116 |
117 | 可以在任何视图上使用(建议在View中定义),必须同时定义grap、dash_height、dash_width。支持横虚线,和竖虚线,这里会检测视图宽高来确定。属性说明:dash_grap(虚线间距)、dash_width(单个小线的宽)、dash_height(单个小线的高)
118 |
119 |
120 |
121 |
122 |
123 | 视图替换或增强
124 | 这个能力可能会将布局文件中的视图替换成其他控件、或者对其进行增强。
125 |
126 |
127 |
128 | 滚动视图
129 | 为了适配小屏手机,我们可能会在每一个布局文件中加上一层ScrollView,现在对容器控件进行能力增强。
130 |
131 |
138 | 说明
139 |
140 | 在需要滚动的视图上添加属性app:layout_canScroll="true",来使其获得滚动的能力。另外所有scrollView的属性,可以配置在该容器控件中。
141 |
142 |
143 |
144 |
145 |
146 | 属性覆盖
147 | 有一种很常见的业务场景,在一个条目中有多个控件,控件大多数属性是相同的(例如TextView的字体颜色、大小等),一般我们会给每一个控件加上相同的属性(冗余)、或者定义公共样式(太麻烦)。现在参考html的布局方式,在父控件中设置公共样式,给子控件当默认值。
148 |
149 |
158 |
159 |
164 |
165 |
172 |
173 |
179 |
180 |
186 |
187 |
193 |
194 |
195 |
196 |
197 | 支持的属性
198 |
199 |
200 |
201 | 控件类型 属性
202 | TextView
203 | textColor
204 |
205 | textSize
206 |
207 | text
208 |
209 | maxLines
210 |
211 | maxEms
212 |
213 | textColorHint
214 |
215 | hint
216 |
217 | textDirection
218 |
219 | textStyle
220 |
221 | capitalize
222 |
223 | ImageView
224 | src
225 |
226 | scaleType
227 |
228 |
229 |
230 | 扩展
231 |
232 |
233 | 属性扩展
234 | SuperXml.addDecorate(object : IDecorateView() {
235 | override fun initExtraInfo(typedArray: TypedArray): Boolean {
236 | }
237 |
238 | override fun decorate(view: View) {
239 | }
240 | })
241 | 实现参考
242 |
243 | internal class RadiusDecorate(var radius: Float = 0f) : IDecorateView() {
244 |
245 | override fun initExtraInfo(typedArray: TypedArray): Boolean {
246 | radius = typedArray.getDimension(R.styleable.decorate_view_layout_radius,0f)
247 | return radius > 0
248 | }
249 |
250 | override fun decorate(view: View)= view.setRadius(radius)
251 |
252 | }
253 |
254 |
255 | 控件替换 OR 增强
256 | SuperXml.addDecorate(object :IWrapDecorateView(){
257 | override fun decorateView(view: View): View {
258 | }
259 |
260 | override fun initExtraInfo(typedArray: TypedArray): Boolean {
261 | }
262 | })
263 | 实现参考
264 |
265 | internal class ScrollWrapDecorate(var canScroll: Boolean = false) : IWrapDecorateView() {
266 |
267 | override fun initExtraInfo(typedArray: TypedArray): Boolean {
268 | canScroll = typedArray.getBoolean(R.styleable.decorate_view_layout_canScroll, false)
269 | return canScroll
270 | }
271 |
272 | override fun decorateView(view: View): View {
273 | return ScrollViewProxy(
274 | view,
275 | attributeSet
276 | )
277 | }
278 |
279 |
280 | }
281 |
282 | 属性覆盖
283 | SuperXml.addCoverAttributeParse(object : AbsChildViewParse(){
284 | override fun createInfoView(context: Context, attributeSet: AttributeSet?): TextView {
285 | }
286 |
287 | override fun coverAttribute(): MutableList<*> {
288 | }
289 | })
290 | 实现参考
291 |
292 | class TextViewCoverParse : AbsChildViewParse() {
293 |
294 | override fun createInfoView(context: Context, attributeSet: AttributeSet?): TextView =
295 | TextView(context, attributeSet)
296 |
297 | override fun coverAttribute(): MutableList<*> = mutableListOf(
298 | AttributeInfo("textSize",{ textSize }) { value -> textSize = value },
299 | AttributeInfo("textColor",{ textColors }) { value -> setTextColor(value) },
300 | AttributeInfo("text",{ text }) { text -> setText(text) },
301 | AttributeInfo("maxLines",{ maxLines }) { maxLines -> setMaxLines(maxLines) },
302 | AttributeInfo("maxEms",{ maxEms }) { maxEms -> setMaxEms(maxEms) },
303 | AttributeInfo("textColorHint",{ hintTextColors }) { hintTextColors -> setHintTextColor(hintTextColors) },
304 | AttributeInfo("hint",{ hint }) { hint -> setHint(hint) },
305 | AttributeInfo("textDirection",{ textDirection }) { textDirection -> setTextDirection(textDirection) },
306 | AttributeInfo("textStyle",{ typeface }) { typeface -> setTypeface(typeface) },
307 | AttributeInfo("capitalize",{ inputType }) { inputType -> setInputType(inputType) }
308 | )
309 |
310 |
311 |
312 | }
313 |
314 |
315 | 代码:github
316 | https://github.com/long8313002/SuperXml
317 |
--------------------------------------------------------------------------------