├── app ├── .gitignore ├── src │ ├── main │ │ ├── res │ │ │ ├── mipmap-hdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── values │ │ │ │ ├── colors.xml │ │ │ │ ├── styles.xml │ │ │ │ └── strings.xml │ │ │ ├── mipmap-anydpi-v26 │ │ │ │ ├── ic_launcher.xml │ │ │ │ └── ic_launcher_round.xml │ │ │ ├── drawable-v24 │ │ │ │ └── ic_launcher_foreground.xml │ │ │ ├── drawable │ │ │ │ └── ic_launcher_background.xml │ │ │ └── layout │ │ │ │ └── activity_main.xml │ │ ├── AndroidManifest.xml │ │ └── java │ │ │ └── cn │ │ │ └── mtjsoft │ │ │ └── www │ │ │ └── shapeviewdemo │ │ │ └── MainActivity.java │ ├── test │ │ └── java │ │ │ └── cn │ │ │ └── mtjsoft │ │ │ └── www │ │ │ └── shapeviewdemo │ │ │ └── ExampleUnitTest.java │ └── androidTest │ │ └── java │ │ └── cn │ │ └── mtjsoft │ │ └── www │ │ └── shapeviewdemo │ │ └── ExampleInstrumentedTest.java ├── proguard-rules.pro └── build.gradle ├── shapeview ├── .gitignore ├── src │ └── main │ │ ├── res │ │ └── values │ │ │ ├── strings.xml │ │ │ └── attrs.xml │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── cn │ │ └── mtjsoft │ │ └── www │ │ └── shapeview │ │ ├── imp │ │ ├── IStyleable.kt │ │ └── BuilderImp.kt │ │ ├── ShapeRadioGroup.kt │ │ ├── ShapeFrameLayout.kt │ │ ├── ShapeTextView.kt │ │ ├── ShapeRelativeLayout.kt │ │ ├── ShapeRecyclerView.kt │ │ ├── ShapeConstraintLayout.kt │ │ ├── ShapeEditText.kt │ │ ├── ShapeLinearLayout.kt │ │ ├── ShapeImageView.kt │ │ ├── styleable │ │ ├── ShapeEditTextStyleable.kt │ │ ├── ShapeTextViewStyleable.kt │ │ ├── ShapeImageViewStyleable.kt │ │ ├── ShapeRadioGroupStyleable.kt │ │ ├── ShapeFrameLayoutStyleable.kt │ │ ├── ShapeLinearLayoutStyleable.kt │ │ ├── ShapeRecyclerViewStyleable.kt │ │ ├── ShapeRelativeLayoutStyleable.kt │ │ ├── ShapeConstraintLayoutStyleable.kt │ │ ├── ShapeCheckBoxStyleable.kt │ │ └── ShapeRadioButtonStyleable.kt │ │ ├── ShapeCheckBox.kt │ │ ├── ShapeRadioButton.kt │ │ ├── util │ │ └── GradientDrawableUtil.kt │ │ └── builder │ │ └── CustomBuilder.kt ├── proguard-rules.pro └── build.gradle ├── settings.gradle ├── wxqrcode.jpg ├── shapeview.gif ├── shapeview.jpg ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .gitignore ├── gradle.properties ├── .idea ├── gradle.xml ├── codeStyles │ └── Project.xml └── misc.xml ├── gradlew.bat ├── gradlew ├── LICENSE └── README.md /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /shapeview/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':shapeview' 2 | -------------------------------------------------------------------------------- /wxqrcode.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mtjsoft/ShapeView/HEAD/wxqrcode.jpg -------------------------------------------------------------------------------- /shapeview.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mtjsoft/ShapeView/HEAD/shapeview.gif -------------------------------------------------------------------------------- /shapeview.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mtjsoft/ShapeView/HEAD/shapeview.jpg -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mtjsoft/ShapeView/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /shapeview/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | ShapeView 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mtjsoft/ShapeView/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mtjsoft/ShapeView/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mtjsoft/ShapeView/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mtjsoft/ShapeView/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mtjsoft/ShapeView/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mtjsoft/ShapeView/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/mtjsoft/ShapeView/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/mtjsoft/ShapeView/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mtjsoft/ShapeView/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /shapeview/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mtjsoft/ShapeView/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches/build_file_checksums.ser 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | .DS_Store 9 | /build 10 | /captures 11 | .externalNativeBuild 12 | /.idea/ 13 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #008577 4 | #00574B 5 | #D81B60 6 | 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/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/test/java/cn/mtjsoft/www/shapeviewdemo/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package cn.mtjsoft.www.shapeviewdemo; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /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 | android.useAndroidX=true 15 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | ShapeViewDemo 3 | 我是%s,性别%s 4 | 5 | 1. 服务开通\n 6 | \t①开通此服务将同意接收老板换装邀请,具体流程为:接收老板赠送时装并完成换装并上传照片及视频。\n 7 | \t②可自定义选择服务中时装品类的接受,全部开启表示同意全部接收。\n 8 | 9 | 2.换装流程\n 10 | \t①老板赠送的时装,均由平台进行发货。接收时装后,须尽快完成换装上传照片及视频,若在接收到时装48小时内未完成换装,则平台将会做相应的处罚;\n 11 | \t②换装后的照片和视频可在订单中进行上传,一个订单系统默认生成一个相册,相册不可自由创建,相册的照片平台审核发布后,不可删除。\n 12 | 13 | 3.回购服务\n 14 | \t①陪玩可在自己的相册中设置回购,回购的时装为该相册订单中的时装,件数为1,不可任意添加时装;\n 15 | \t②老板在拍下回购的时装后,须在48小时内尽快完成发货,逾期平台将会给予一定的处罚;\n 16 | \t③回购的时装为保障双方隐私及安全,将由平台转寄,请知悉。\n 17 | 18 | 2.订单说明\n 19 | \t①换装订单:完成该订单,则获得订单金额的20%作为奖励金自动发放到余额,同时获得该订单中时装对应的“虚拟卡通形象装扮”;\n 20 | \t②回购订单:时装发布回购的价格,可自定义设置,平台将抽取30%作为平台运营费用,请知悉。 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 | -------------------------------------------------------------------------------- /shapeview/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 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/androidTest/java/cn/mtjsoft/www/shapeviewdemo/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package cn.mtjsoft.www.shapeviewdemo; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("cn.mtjsoft.www.shapeviewdemo", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /shapeview/src/main/java/cn/mtjsoft/www/shapeview/imp/IStyleable.kt: -------------------------------------------------------------------------------- 1 | package cn.mtjsoft.www.shapeview.imp 2 | 3 | /** 4 | * @author mtj 5 | * @date 2022/2/7 6 | * @desc 7 | * @email mtjsoft3@gmail.com 8 | */ 9 | interface IStyleable { 10 | val shape: Int 11 | val solidColor: Int 12 | val strokeColor: Int 13 | val startColor: Int 14 | val centerColor: Int 15 | val endColor: Int 16 | val startSelectColor: Int 17 | val centerSelectColor: Int 18 | val endSelectColor: Int 19 | val orientation: Int 20 | val gradientType: Int 21 | val gradientRadius: Int 22 | val strokeWidth: Int 23 | val dashWidth: Int 24 | val dashGap: Int 25 | val radius: Int 26 | val topLeftRadius: Int 27 | val topRightRadius: Int 28 | val bottomLeftRadius: Int 29 | val bottomRightRadius: Int 30 | val isOpenSelector: Int 31 | val textNormalColor: Int 32 | val textSelectColor: Int 33 | val solidSelectColor: Int 34 | val strokeSelectColor: Int 35 | } -------------------------------------------------------------------------------- /shapeview/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'com.github.dcendents.android-maven' 4 | group='com.github.mtjsoft' 5 | android { 6 | compileSdkVersion 29 7 | defaultConfig { 8 | minSdkVersion 19 9 | targetSdkVersion 29 10 | versionCode 301 11 | versionName "3.0.1" 12 | } 13 | 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | compileOptions { 21 | sourceCompatibility JavaVersion.VERSION_1_8 22 | targetCompatibility JavaVersion.VERSION_1_8 23 | } 24 | kotlinOptions { 25 | jvmTarget = '1.8' 26 | } 27 | } 28 | 29 | dependencies { 30 | implementation fileTree(dir: 'libs', include: ['*.jar']) 31 | implementation "androidx.appcompat:appcompat:1.1.0" 32 | implementation 'androidx.recyclerview:recyclerview:1.0.0' 33 | implementation "androidx.constraintlayout:constraintlayout:1.1.3" 34 | } 35 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 29 5 | defaultConfig { 6 | applicationId "cn.mtjsoft.www.shapeviewdemo" 7 | minSdkVersion 21 8 | targetSdkVersion 29 9 | versionCode 1 10 | versionName "1.0" 11 | 12 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | implementation fileTree(include: ['*.jar'], dir: 'libs') 24 | implementation "androidx.appcompat:appcompat:1.1.0" 25 | implementation "androidx.constraintlayout:constraintlayout:1.1.3" 26 | 27 | testImplementation 'junit:junit:4.12' 28 | androidTestImplementation 'androidx.test.ext:junit:1.1.1' 29 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' 30 | 31 | implementation project(':shapeview') 32 | // implementation 'com.github.mtjsoft:ShapeView:v3.0.0' 33 | } 34 | -------------------------------------------------------------------------------- /shapeview/src/main/java/cn/mtjsoft/www/shapeview/ShapeRadioGroup.kt: -------------------------------------------------------------------------------- 1 | package cn.mtjsoft.www.shapeview 2 | 3 | import android.content.Context 4 | import android.graphics.drawable.GradientDrawable 5 | import android.util.AttributeSet 6 | import android.widget.RadioGroup 7 | import cn.mtjsoft.www.shapeview.builder.CustomBuilder 8 | import cn.mtjsoft.www.shapeview.styleable.ShapeRadioGroupStyleable 9 | import cn.mtjsoft.www.shapeview.util.GradientDrawableUtil.Companion.init 10 | 11 | /** 12 | * 实现自定义圆角背景 13 | */ 14 | class ShapeRadioGroup constructor(context: Context, attrs: AttributeSet) : 15 | RadioGroup(context, attrs) { 16 | //自定背景边框Drawable 17 | var gradientDrawable: GradientDrawable? = null 18 | private set 19 | private lateinit var builder: CustomBuilder 20 | 21 | /** 22 | * 初始化参数 23 | */ 24 | private fun init(context: Context, attrs: AttributeSet) { 25 | val ta = context.obtainStyledAttributes(attrs, R.styleable.ShapeRadioGroup) 26 | builder = CustomBuilder(this, ta, STYLEABLE) 27 | setCustomBackground() 28 | } 29 | 30 | fun setBuilder(builder: CustomBuilder) { 31 | this.builder = builder 32 | setCustomBackground() 33 | } 34 | 35 | fun getBuilder(): CustomBuilder { 36 | return builder 37 | } 38 | 39 | private fun setCustomBackground() { 40 | builder.setLayerType(this) 41 | gradientDrawable = init().getNormalDrawable(builder) 42 | this.background = gradientDrawable 43 | this.isFocusable = false 44 | this.isFocusableInTouchMode = false 45 | } 46 | 47 | companion object { 48 | private val STYLEABLE = ShapeRadioGroupStyleable() 49 | } 50 | 51 | init { 52 | init(context, attrs) 53 | } 54 | } -------------------------------------------------------------------------------- /shapeview/src/main/java/cn/mtjsoft/www/shapeview/imp/BuilderImp.kt: -------------------------------------------------------------------------------- 1 | package cn.mtjsoft.www.shapeview.imp 2 | 3 | import android.graphics.drawable.GradientDrawable 4 | import cn.mtjsoft.www.shapeview.builder.CustomBuilder 5 | import cn.mtjsoft.www.shapeview.builder.CustomBuilder.GradientType 6 | 7 | /** 8 | * @author mtj 9 | * @date 2022/1/13 10 | * @desc 11 | * @email mtjsoft3@gmail.com 12 | */ 13 | interface BuilderImp { 14 | fun setShape(@CustomBuilder.Shape shape: Int): BuilderImp 15 | fun setSolidColor(solidColor: Int): BuilderImp 16 | fun setStrokeColor(strokeColor: Int): BuilderImp 17 | fun setColors(startColor: Int, centerColor: Int, endColor: Int): BuilderImp 18 | fun setSelectColors(startColor: Int, centerColor: Int, endColor: Int): BuilderImp 19 | fun setOrientation(orientation: GradientDrawable.Orientation): BuilderImp 20 | fun setGradientType(@GradientType gradientType: Int): BuilderImp 21 | fun setGradientRadius(gradientRadius: Float): BuilderImp 22 | fun setStrokeWidth(strokeWidth: Int): BuilderImp 23 | fun setDashWidth(dashWidth: Float): BuilderImp 24 | fun setDashGap(dashGap: Float): BuilderImp 25 | fun setRadius(radius: Int): BuilderImp 26 | fun setTopLeftRadius(topLeftRadius: Int): BuilderImp 27 | fun setTopRightRadius(topRightRadius: Int): BuilderImp 28 | fun setBottomLeftRadius(bottomLeftRadius: Int): BuilderImp 29 | fun setBottomRightRadius(bottomRightRadius: Int): BuilderImp 30 | fun setOpenSelector(openSelector: Boolean): BuilderImp 31 | fun setTextNormalColor(textNormalColor: Int): BuilderImp 32 | fun setTextSelectColor(textSelectColor: Int): BuilderImp 33 | fun setSolidSelectColor(solidSelectColor: Int): BuilderImp 34 | fun setStrokeSelectColor(strokeSelectColor: Int): BuilderImp 35 | } -------------------------------------------------------------------------------- /shapeview/src/main/java/cn/mtjsoft/www/shapeview/ShapeFrameLayout.kt: -------------------------------------------------------------------------------- 1 | package cn.mtjsoft.www.shapeview 2 | 3 | import android.content.Context 4 | import android.graphics.drawable.GradientDrawable 5 | import android.util.AttributeSet 6 | import android.widget.FrameLayout 7 | import cn.mtjsoft.www.shapeview.builder.CustomBuilder 8 | import cn.mtjsoft.www.shapeview.styleable.ShapeFrameLayoutStyleable 9 | import cn.mtjsoft.www.shapeview.util.GradientDrawableUtil.Companion.init 10 | 11 | /** 12 | * 实现自定义圆角背景 13 | */ 14 | class ShapeFrameLayout @JvmOverloads constructor( 15 | context: Context, 16 | attrs: AttributeSet, 17 | defStyleAttr: Int = 0 18 | ) : FrameLayout(context, attrs, defStyleAttr) { 19 | //自定背景边框Drawable 20 | var gradientDrawable: GradientDrawable? = null 21 | private set 22 | private lateinit var builder: CustomBuilder 23 | 24 | /** 25 | * 初始化参数 26 | */ 27 | private fun init(context: Context, attrs: AttributeSet) { 28 | val ta = context.obtainStyledAttributes(attrs, R.styleable.ShapeFrameLayout) 29 | builder = CustomBuilder(this, ta, STYLEABLE) 30 | setCustomBackground() 31 | } 32 | 33 | fun setBuilder(builder: CustomBuilder) { 34 | this.builder = builder 35 | setCustomBackground() 36 | } 37 | 38 | fun getBuilder(): CustomBuilder { 39 | return builder 40 | } 41 | 42 | private fun setCustomBackground() { 43 | builder.setLayerType(this) 44 | gradientDrawable = init().getNormalDrawable(builder) 45 | this.background = gradientDrawable 46 | this.isFocusable = false 47 | this.isFocusableInTouchMode = false 48 | } 49 | 50 | companion object { 51 | private val STYLEABLE = ShapeFrameLayoutStyleable() 52 | } 53 | 54 | init { 55 | init(context, attrs) 56 | } 57 | } -------------------------------------------------------------------------------- /shapeview/src/main/java/cn/mtjsoft/www/shapeview/ShapeTextView.kt: -------------------------------------------------------------------------------- 1 | package cn.mtjsoft.www.shapeview 2 | 3 | import android.content.Context 4 | import android.graphics.drawable.GradientDrawable 5 | import android.util.AttributeSet 6 | import androidx.appcompat.widget.AppCompatTextView 7 | import cn.mtjsoft.www.shapeview.builder.CustomBuilder 8 | import cn.mtjsoft.www.shapeview.styleable.ShapeTextViewStyleable 9 | import cn.mtjsoft.www.shapeview.util.GradientDrawableUtil.Companion.init 10 | 11 | /** 12 | * 实现自定义圆角背景 13 | */ 14 | class ShapeTextView @JvmOverloads constructor( 15 | context: Context, 16 | attrs: AttributeSet, 17 | defStyleAttr: Int = 0 18 | ) : AppCompatTextView(context, attrs, defStyleAttr) { 19 | //自定背景边框Drawable 20 | var gradientDrawable: GradientDrawable? = null 21 | private set 22 | private lateinit var builder: CustomBuilder 23 | 24 | /** 25 | * 初始化参数 26 | */ 27 | private fun init(context: Context, attrs: AttributeSet) { 28 | val ta = context.obtainStyledAttributes(attrs, R.styleable.ShapeTextView) 29 | builder = CustomBuilder(this, ta, STYLEABLE) 30 | setCustomBackground() 31 | } 32 | 33 | fun setBuilder(builder: CustomBuilder) { 34 | this.builder = builder 35 | setCustomBackground() 36 | } 37 | 38 | fun getBuilder(): CustomBuilder { 39 | return builder 40 | } 41 | 42 | private fun setCustomBackground() { 43 | builder.setLayerType(this) 44 | gradientDrawable = init().getNormalDrawable(builder) 45 | this.background = gradientDrawable 46 | this.isFocusable = false 47 | this.isFocusableInTouchMode = false 48 | } 49 | 50 | companion object { 51 | private val STYLEABLE = ShapeTextViewStyleable() 52 | } 53 | 54 | init { 55 | init(context, attrs) 56 | } 57 | } -------------------------------------------------------------------------------- /shapeview/src/main/java/cn/mtjsoft/www/shapeview/ShapeRelativeLayout.kt: -------------------------------------------------------------------------------- 1 | package cn.mtjsoft.www.shapeview 2 | 3 | import android.content.Context 4 | import android.graphics.drawable.GradientDrawable 5 | import android.util.AttributeSet 6 | import android.widget.RelativeLayout 7 | import cn.mtjsoft.www.shapeview.builder.CustomBuilder 8 | import cn.mtjsoft.www.shapeview.styleable.ShapeRelativeLayoutStyleable 9 | import cn.mtjsoft.www.shapeview.util.GradientDrawableUtil.Companion.init 10 | 11 | /** 12 | * 实现自定义圆角背景 13 | */ 14 | class ShapeRelativeLayout @JvmOverloads constructor( 15 | context: Context, 16 | attrs: AttributeSet, 17 | defStyleAttr: Int = 0 18 | ) : RelativeLayout(context, attrs, defStyleAttr) { 19 | //自定背景边框Drawable 20 | var gradientDrawable: GradientDrawable? = null 21 | private set 22 | private lateinit var builder: CustomBuilder 23 | 24 | /** 25 | * 初始化参数 26 | */ 27 | private fun init(context: Context, attrs: AttributeSet) { 28 | val ta = context.obtainStyledAttributes(attrs, R.styleable.ShapeRelativeLayout) 29 | builder = CustomBuilder(this, ta, STYLEABLE) 30 | setCustomBackground() 31 | } 32 | 33 | fun setBuilder(builder: CustomBuilder) { 34 | this.builder = builder 35 | setCustomBackground() 36 | } 37 | 38 | fun getBuilder(): CustomBuilder { 39 | return builder 40 | } 41 | 42 | private fun setCustomBackground() { 43 | builder.setLayerType(this) 44 | gradientDrawable = init().getNormalDrawable(builder) 45 | this.background = gradientDrawable 46 | this.isFocusable = false 47 | this.isFocusableInTouchMode = false 48 | } 49 | 50 | companion object { 51 | private val STYLEABLE = ShapeRelativeLayoutStyleable() 52 | } 53 | 54 | init { 55 | init(context, attrs) 56 | } 57 | } -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 15 | 16 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /shapeview/src/main/java/cn/mtjsoft/www/shapeview/ShapeRecyclerView.kt: -------------------------------------------------------------------------------- 1 | package cn.mtjsoft.www.shapeview 2 | 3 | import android.content.Context 4 | import android.graphics.drawable.GradientDrawable 5 | import android.util.AttributeSet 6 | import androidx.recyclerview.widget.RecyclerView 7 | import cn.mtjsoft.www.shapeview.builder.CustomBuilder 8 | import cn.mtjsoft.www.shapeview.styleable.ShapeRecyclerViewStyleable 9 | import cn.mtjsoft.www.shapeview.util.GradientDrawableUtil.Companion.init 10 | 11 | /** 12 | * 实现自定义圆角背景 13 | * 14 | * @author mtj 15 | */ 16 | class ShapeRecyclerView @JvmOverloads constructor( 17 | context: Context, 18 | attrs: AttributeSet, 19 | defStyleAttr: Int = 0 20 | ) : RecyclerView(context, attrs, defStyleAttr) { 21 | //自定背景边框Drawable 22 | var gradientDrawable: GradientDrawable? = null 23 | private set 24 | private lateinit var builder: CustomBuilder 25 | 26 | /** 27 | * 初始化参数 28 | */ 29 | private fun init(context: Context, attrs: AttributeSet) { 30 | val ta = context.obtainStyledAttributes(attrs, R.styleable.ShapeRecyclerView) 31 | builder = CustomBuilder(this, ta, STYLEABLE) 32 | setCustomBackground() 33 | } 34 | 35 | fun setBuilder(builder: CustomBuilder) { 36 | this.builder = builder 37 | setCustomBackground() 38 | } 39 | 40 | fun getBuilder(): CustomBuilder { 41 | return builder 42 | } 43 | 44 | private fun setCustomBackground() { 45 | builder.setLayerType(this) 46 | gradientDrawable = init().getNormalDrawable(builder) 47 | this.background = gradientDrawable 48 | this.isFocusable = false 49 | this.isFocusableInTouchMode = false 50 | } 51 | 52 | companion object { 53 | private val STYLEABLE = ShapeRecyclerViewStyleable() 54 | } 55 | 56 | init { 57 | init(context, attrs) 58 | } 59 | } -------------------------------------------------------------------------------- /shapeview/src/main/java/cn/mtjsoft/www/shapeview/ShapeConstraintLayout.kt: -------------------------------------------------------------------------------- 1 | package cn.mtjsoft.www.shapeview 2 | 3 | import android.content.Context 4 | import android.graphics.drawable.GradientDrawable 5 | import android.util.AttributeSet 6 | import androidx.constraintlayout.widget.ConstraintLayout 7 | import cn.mtjsoft.www.shapeview.builder.CustomBuilder 8 | import cn.mtjsoft.www.shapeview.styleable.ShapeConstraintLayoutStyleable 9 | import cn.mtjsoft.www.shapeview.util.GradientDrawableUtil.Companion.init 10 | 11 | /** 12 | * 实现自定义圆角背景 13 | */ 14 | class ShapeConstraintLayout @JvmOverloads constructor( 15 | context: Context, 16 | attrs: AttributeSet, 17 | defStyleAttr: Int = 0 18 | ) : ConstraintLayout(context, attrs, defStyleAttr) { 19 | //自定背景边框Drawable 20 | var gradientDrawable: GradientDrawable? = null 21 | private set 22 | private lateinit var builder: CustomBuilder 23 | 24 | /** 25 | * 初始化参数 26 | */ 27 | private fun init(context: Context, attrs: AttributeSet) { 28 | val ta = context.obtainStyledAttributes(attrs, R.styleable.ShapeConstraintLayout) 29 | builder = CustomBuilder(this, ta, STYLEABLE) 30 | setCustomBackground() 31 | } 32 | 33 | fun setBuilder(builder: CustomBuilder) { 34 | this.builder = builder 35 | setCustomBackground() 36 | } 37 | 38 | fun getBuilder(): CustomBuilder { 39 | return builder 40 | } 41 | 42 | private fun setCustomBackground() { 43 | builder.setLayerType(this) 44 | gradientDrawable = init().getNormalDrawable(builder) 45 | this.background = gradientDrawable 46 | this.isFocusable = false 47 | this.isFocusableInTouchMode = false 48 | } 49 | 50 | companion object { 51 | private val STYLEABLE = ShapeConstraintLayoutStyleable() 52 | } 53 | 54 | init { 55 | init(context, attrs) 56 | } 57 | } -------------------------------------------------------------------------------- /shapeview/src/main/java/cn/mtjsoft/www/shapeview/ShapeEditText.kt: -------------------------------------------------------------------------------- 1 | package cn.mtjsoft.www.shapeview 2 | 3 | import android.content.Context 4 | import android.graphics.drawable.GradientDrawable 5 | import android.util.AttributeSet 6 | import androidx.appcompat.widget.AppCompatEditText 7 | import cn.mtjsoft.www.shapeview.builder.CustomBuilder 8 | import cn.mtjsoft.www.shapeview.styleable.ShapeEditTextStyleable 9 | import cn.mtjsoft.www.shapeview.util.GradientDrawableUtil.Companion.init 10 | 11 | /** 12 | * 实现自定义圆角背景 13 | * 14 | * @author mtj 15 | */ 16 | class ShapeEditText @JvmOverloads constructor( 17 | context: Context, 18 | attrs: AttributeSet, 19 | defStyleAttr: Int = 0 20 | ) : AppCompatEditText(context, attrs, defStyleAttr) { 21 | /** 22 | * 自定背景Drawable 23 | */ 24 | var gradientDrawable: GradientDrawable? = null 25 | private set 26 | 27 | private lateinit var builder: CustomBuilder 28 | 29 | /** 30 | * 初始化参数 31 | */ 32 | private fun init(context: Context, attrs: AttributeSet) { 33 | val ta = context.obtainStyledAttributes(attrs, R.styleable.ShapeEditText) 34 | builder = CustomBuilder(this, ta, STYLEABLE) 35 | setCustomBackground() 36 | } 37 | 38 | fun setBuilder(builder: CustomBuilder) { 39 | this.builder = builder 40 | setCustomBackground() 41 | } 42 | 43 | fun getBuilder(): CustomBuilder { 44 | return builder 45 | } 46 | 47 | private fun setCustomBackground() { 48 | builder.setLayerType(this) 49 | gradientDrawable = init().getNormalDrawable(builder) 50 | this.background = gradientDrawable 51 | this.isFocusable = true 52 | this.isFocusableInTouchMode = true 53 | } 54 | 55 | companion object { 56 | private val STYLEABLE = ShapeEditTextStyleable() 57 | } 58 | 59 | init { 60 | init(context, attrs) 61 | } 62 | } -------------------------------------------------------------------------------- /shapeview/src/main/java/cn/mtjsoft/www/shapeview/ShapeLinearLayout.kt: -------------------------------------------------------------------------------- 1 | package cn.mtjsoft.www.shapeview 2 | 3 | import android.content.Context 4 | import android.graphics.drawable.GradientDrawable 5 | import android.util.AttributeSet 6 | import android.widget.LinearLayout 7 | import cn.mtjsoft.www.shapeview.builder.CustomBuilder 8 | import cn.mtjsoft.www.shapeview.styleable.ShapeLinearLayoutStyleable 9 | import cn.mtjsoft.www.shapeview.util.GradientDrawableUtil.Companion.init 10 | 11 | /** 12 | * 实现自定义圆角背景 13 | */ 14 | class ShapeLinearLayout @JvmOverloads constructor( 15 | context: Context, 16 | attrs: AttributeSet, 17 | defStyleAttr: Int = 0 18 | ) : LinearLayout(context, attrs, defStyleAttr) { 19 | //自定背景边框Drawable 20 | var gradientDrawable: GradientDrawable? = null 21 | private set 22 | private lateinit var builder: CustomBuilder 23 | 24 | /** 25 | * 初始化参数 26 | * 27 | * @param context 28 | * @param attrs 29 | */ 30 | private fun init(context: Context, attrs: AttributeSet) { 31 | val ta = context.obtainStyledAttributes(attrs, R.styleable.ShapeLinearLayout) 32 | builder = CustomBuilder(this, ta, STYLEABLE) 33 | setCustomBackground() 34 | } 35 | 36 | fun setBuilder(builder: CustomBuilder) { 37 | this.builder = builder 38 | setCustomBackground() 39 | } 40 | 41 | fun getBuilder(): CustomBuilder { 42 | return builder 43 | } 44 | 45 | private fun setCustomBackground() { 46 | builder.setLayerType(this) 47 | gradientDrawable = init().getNormalDrawable(builder) 48 | this.background = gradientDrawable 49 | this.isFocusable = false 50 | this.isFocusableInTouchMode = false 51 | } 52 | 53 | companion object { 54 | private val STYLEABLE = ShapeLinearLayoutStyleable() 55 | } 56 | 57 | init { 58 | init(context, attrs) 59 | } 60 | } -------------------------------------------------------------------------------- /shapeview/src/main/java/cn/mtjsoft/www/shapeview/ShapeImageView.kt: -------------------------------------------------------------------------------- 1 | package cn.mtjsoft.www.shapeview 2 | 3 | import android.content.Context 4 | import android.graphics.drawable.GradientDrawable 5 | import android.util.AttributeSet 6 | import androidx.appcompat.widget.AppCompatImageView 7 | import cn.mtjsoft.www.shapeview.builder.CustomBuilder 8 | import cn.mtjsoft.www.shapeview.styleable.ShapeImageViewStyleable 9 | import cn.mtjsoft.www.shapeview.util.GradientDrawableUtil.Companion.init 10 | 11 | /** 12 | * 实现自定义圆角背景 13 | */ 14 | class ShapeImageView @JvmOverloads constructor( 15 | context: Context, 16 | attrs: AttributeSet, 17 | defStyleAttr: Int = 0 18 | ) : AppCompatImageView(context, attrs, defStyleAttr) { 19 | //自定背景边框Drawable 20 | var gradientDrawable: GradientDrawable? = null 21 | private set 22 | private lateinit var builder: CustomBuilder 23 | 24 | /** 25 | * 初始化参数 26 | * 27 | * @param context 28 | * @param attrs 29 | */ 30 | private fun init(context: Context, attrs: AttributeSet) { 31 | val ta = context.obtainStyledAttributes(attrs, R.styleable.ShapeImageView) 32 | builder = CustomBuilder(this, ta, STYLEABLE) 33 | setCustomBackground() 34 | } 35 | 36 | fun setBuilder(builder: CustomBuilder) { 37 | this.builder = builder 38 | setCustomBackground() 39 | } 40 | 41 | fun getBuilder(): CustomBuilder { 42 | return builder 43 | } 44 | 45 | private fun setCustomBackground() { 46 | builder.setLayerType(this) 47 | gradientDrawable = init().getNormalDrawable(builder) 48 | this.background = gradientDrawable 49 | this.isFocusable = false 50 | this.isFocusableInTouchMode = false 51 | } 52 | 53 | companion object { 54 | private val STYLEABLE = ShapeImageViewStyleable() 55 | } 56 | 57 | init { 58 | init(context, attrs) 59 | } 60 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/java/cn/mtjsoft/www/shapeviewdemo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package cn.mtjsoft.www.shapeviewdemo; 2 | 3 | import android.os.Build; 4 | import android.os.Bundle; 5 | import android.util.Log; 6 | import android.view.View; 7 | import android.view.Window; 8 | import android.view.WindowManager; 9 | 10 | import androidx.appcompat.app.AppCompatActivity; 11 | import androidx.core.content.ContextCompat; 12 | import cn.mtjsoft.www.shapeview.ShapeTextView; 13 | 14 | public class MainActivity extends AppCompatActivity { 15 | 16 | private ShapeTextView shapeTextView; 17 | 18 | @Override 19 | protected void onCreate(Bundle savedInstanceState) { 20 | super.onCreate(savedInstanceState); 21 | try { 22 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 23 | Window window = getWindow(); 24 | window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); 25 | window.setStatusBarColor(ContextCompat.getColor(this, R.color.colorPrimary)); 26 | window.getDecorView() 27 | .setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); 28 | } 29 | } catch (Exception e) { 30 | e.printStackTrace(); 31 | } 32 | setContentView(R.layout.activity_main); 33 | if (getSupportActionBar() != null) { 34 | getSupportActionBar().setTitle(R.string.app_name); 35 | } 36 | shapeTextView = findViewById(R.id.stv); 37 | // 代码动态设置 38 | shapeTextView.setBuilder( 39 | shapeTextView 40 | .getBuilder() 41 | .setStrokeWidth(3) 42 | .setStrokeColor(ContextCompat.getColor(getBaseContext(), R.color.colorAccent)) 43 | .setColors(ContextCompat.getColor(getBaseContext(), R.color.colorAccent), 44 | ContextCompat.getColor(getBaseContext(), R.color.colorPrimaryDark), 45 | ContextCompat.getColor(getBaseContext(), R.color.colorPrimary)) 46 | .setRadius(10) 47 | ); 48 | String str = String.format(getString(R.string.test_str),"小明", "男"); 49 | Log.i("mtj", str); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /shapeview/src/main/java/cn/mtjsoft/www/shapeview/styleable/ShapeEditTextStyleable.kt: -------------------------------------------------------------------------------- 1 | package cn.mtjsoft.www.shapeview.styleable 2 | 3 | import cn.mtjsoft.www.shapeview.imp.IStyleable 4 | import cn.mtjsoft.www.shapeview.R 5 | 6 | /** 7 | * @author mtj 8 | * @date 2022/2/7 9 | * @desc 10 | * @email mtjsoft3@gmail.com 11 | */ 12 | class ShapeEditTextStyleable : IStyleable { 13 | override val shape: Int 14 | get() = R.styleable.ShapeEditText_sv_shape 15 | override val solidColor: Int 16 | get() = R.styleable.ShapeEditText_sv_solidColor 17 | override val strokeColor: Int 18 | get() = R.styleable.ShapeEditText_sv_strokeColor 19 | override val startColor: Int 20 | get() = R.styleable.ShapeEditText_sv_startColor 21 | override val centerColor: Int 22 | get() = R.styleable.ShapeEditText_sv_centerColor 23 | override val endColor: Int 24 | get() = R.styleable.ShapeEditText_sv_endColor 25 | override val startSelectColor: Int 26 | get() = R.styleable.ShapeEditText_sv_startSelectColor 27 | override val centerSelectColor: Int 28 | get() = R.styleable.ShapeEditText_sv_centerSelectColor 29 | override val endSelectColor: Int 30 | get() = R.styleable.ShapeEditText_sv_endSelectColor 31 | override val orientation: Int 32 | get() = R.styleable.ShapeEditText_sv_orientation 33 | override val gradientType: Int 34 | get() = R.styleable.ShapeEditText_sv_gradientType 35 | override val gradientRadius: Int 36 | get() = R.styleable.ShapeEditText_sv_gradientRadius 37 | override val strokeWidth: Int 38 | get() = R.styleable.ShapeEditText_sv_strokeWidth 39 | override val dashWidth: Int 40 | get() = R.styleable.ShapeEditText_sv_dashWidth 41 | override val dashGap: Int 42 | get() = R.styleable.ShapeEditText_sv_dashGap 43 | override val radius: Int 44 | get() = R.styleable.ShapeEditText_sv_radius 45 | override val topLeftRadius: Int 46 | get() = R.styleable.ShapeEditText_sv_topLeftRadius 47 | override val topRightRadius: Int 48 | get() = R.styleable.ShapeEditText_sv_topRightRadius 49 | override val bottomLeftRadius: Int 50 | get() = R.styleable.ShapeEditText_sv_bottomLeftRadius 51 | override val bottomRightRadius: Int 52 | get() = R.styleable.ShapeEditText_sv_bottomRightRadius 53 | override val isOpenSelector: Int 54 | get() = 0 55 | override val textNormalColor: Int 56 | get() = 0 57 | override val textSelectColor: Int 58 | get() = 0 59 | override val solidSelectColor: Int 60 | get() = 0 61 | override val strokeSelectColor: Int 62 | get() = 0 63 | } -------------------------------------------------------------------------------- /shapeview/src/main/java/cn/mtjsoft/www/shapeview/styleable/ShapeTextViewStyleable.kt: -------------------------------------------------------------------------------- 1 | package cn.mtjsoft.www.shapeview.styleable 2 | 3 | import cn.mtjsoft.www.shapeview.imp.IStyleable 4 | import cn.mtjsoft.www.shapeview.R 5 | 6 | /** 7 | * @author mtj 8 | * @date 2022/2/7 9 | * @desc 10 | * @email mtjsoft3@gmail.com 11 | */ 12 | class ShapeTextViewStyleable : IStyleable { 13 | override val shape: Int 14 | get() = R.styleable.ShapeTextView_sv_shape 15 | override val solidColor: Int 16 | get() = R.styleable.ShapeTextView_sv_solidColor 17 | override val strokeColor: Int 18 | get() = R.styleable.ShapeTextView_sv_strokeColor 19 | override val startColor: Int 20 | get() = R.styleable.ShapeTextView_sv_startColor 21 | override val centerColor: Int 22 | get() = R.styleable.ShapeTextView_sv_centerColor 23 | override val endColor: Int 24 | get() = R.styleable.ShapeTextView_sv_endColor 25 | override val startSelectColor: Int 26 | get() = R.styleable.ShapeTextView_sv_startSelectColor 27 | override val centerSelectColor: Int 28 | get() = R.styleable.ShapeTextView_sv_centerSelectColor 29 | override val endSelectColor: Int 30 | get() = R.styleable.ShapeTextView_sv_endSelectColor 31 | override val orientation: Int 32 | get() = R.styleable.ShapeTextView_sv_orientation 33 | override val gradientType: Int 34 | get() = R.styleable.ShapeTextView_sv_gradientType 35 | override val gradientRadius: Int 36 | get() = R.styleable.ShapeTextView_sv_gradientRadius 37 | override val strokeWidth: Int 38 | get() = R.styleable.ShapeTextView_sv_strokeWidth 39 | override val dashWidth: Int 40 | get() = R.styleable.ShapeTextView_sv_dashWidth 41 | override val dashGap: Int 42 | get() = R.styleable.ShapeTextView_sv_dashGap 43 | override val radius: Int 44 | get() = R.styleable.ShapeTextView_sv_radius 45 | override val topLeftRadius: Int 46 | get() = R.styleable.ShapeTextView_sv_topLeftRadius 47 | override val topRightRadius: Int 48 | get() = R.styleable.ShapeTextView_sv_topRightRadius 49 | override val bottomLeftRadius: Int 50 | get() = R.styleable.ShapeTextView_sv_bottomLeftRadius 51 | override val bottomRightRadius: Int 52 | get() = R.styleable.ShapeTextView_sv_bottomRightRadius 53 | override val isOpenSelector: Int 54 | get() = 0 55 | override val textNormalColor: Int 56 | get() = 0 57 | override val textSelectColor: Int 58 | get() = 0 59 | override val solidSelectColor: Int 60 | get() = 0 61 | override val strokeSelectColor: Int 62 | get() = 0 63 | } -------------------------------------------------------------------------------- /shapeview/src/main/java/cn/mtjsoft/www/shapeview/styleable/ShapeImageViewStyleable.kt: -------------------------------------------------------------------------------- 1 | package cn.mtjsoft.www.shapeview.styleable 2 | 3 | import cn.mtjsoft.www.shapeview.imp.IStyleable 4 | import cn.mtjsoft.www.shapeview.R 5 | 6 | /** 7 | * @author mtj 8 | * @date 2022/2/7 9 | * @desc 10 | * @email mtjsoft3@gmail.com 11 | */ 12 | class ShapeImageViewStyleable : IStyleable { 13 | override val shape: Int 14 | get() = R.styleable.ShapeImageView_sv_shape 15 | override val solidColor: Int 16 | get() = R.styleable.ShapeImageView_sv_solidColor 17 | override val strokeColor: Int 18 | get() = R.styleable.ShapeImageView_sv_strokeColor 19 | override val startColor: Int 20 | get() = R.styleable.ShapeImageView_sv_startColor 21 | override val centerColor: Int 22 | get() = R.styleable.ShapeImageView_sv_centerColor 23 | override val endColor: Int 24 | get() = R.styleable.ShapeImageView_sv_endColor 25 | override val startSelectColor: Int 26 | get() = R.styleable.ShapeImageView_sv_startSelectColor 27 | override val centerSelectColor: Int 28 | get() = R.styleable.ShapeImageView_sv_centerSelectColor 29 | override val endSelectColor: Int 30 | get() = R.styleable.ShapeImageView_sv_endSelectColor 31 | override val orientation: Int 32 | get() = R.styleable.ShapeImageView_sv_orientation 33 | override val gradientType: Int 34 | get() = R.styleable.ShapeImageView_sv_gradientType 35 | override val gradientRadius: Int 36 | get() = R.styleable.ShapeImageView_sv_gradientRadius 37 | override val strokeWidth: Int 38 | get() = R.styleable.ShapeImageView_sv_strokeWidth 39 | override val dashWidth: Int 40 | get() = R.styleable.ShapeImageView_sv_dashWidth 41 | override val dashGap: Int 42 | get() = R.styleable.ShapeImageView_sv_dashGap 43 | override val radius: Int 44 | get() = R.styleable.ShapeImageView_sv_radius 45 | override val topLeftRadius: Int 46 | get() = R.styleable.ShapeImageView_sv_topLeftRadius 47 | override val topRightRadius: Int 48 | get() = R.styleable.ShapeImageView_sv_topRightRadius 49 | override val bottomLeftRadius: Int 50 | get() = R.styleable.ShapeImageView_sv_bottomLeftRadius 51 | override val bottomRightRadius: Int 52 | get() = R.styleable.ShapeImageView_sv_bottomRightRadius 53 | override val isOpenSelector: Int 54 | get() = 0 55 | override val textNormalColor: Int 56 | get() = 0 57 | override val textSelectColor: Int 58 | get() = 0 59 | override val solidSelectColor: Int 60 | get() = 0 61 | override val strokeSelectColor: Int 62 | get() = 0 63 | } -------------------------------------------------------------------------------- /shapeview/src/main/java/cn/mtjsoft/www/shapeview/styleable/ShapeRadioGroupStyleable.kt: -------------------------------------------------------------------------------- 1 | package cn.mtjsoft.www.shapeview.styleable 2 | 3 | import cn.mtjsoft.www.shapeview.imp.IStyleable 4 | import cn.mtjsoft.www.shapeview.R 5 | 6 | /** 7 | * @author mtj 8 | * @date 2022/2/7 9 | * @desc 10 | * @email mtjsoft3@gmail.com 11 | */ 12 | class ShapeRadioGroupStyleable : IStyleable { 13 | override val shape: Int 14 | get() = R.styleable.ShapeRadioGroup_sv_shape 15 | override val solidColor: Int 16 | get() = R.styleable.ShapeRadioGroup_sv_solidColor 17 | override val strokeColor: Int 18 | get() = R.styleable.ShapeRadioGroup_sv_strokeColor 19 | override val startColor: Int 20 | get() = R.styleable.ShapeRadioGroup_sv_startColor 21 | override val centerColor: Int 22 | get() = R.styleable.ShapeRadioGroup_sv_centerColor 23 | override val endColor: Int 24 | get() = R.styleable.ShapeRadioGroup_sv_endColor 25 | override val startSelectColor: Int 26 | get() = R.styleable.ShapeRadioGroup_sv_startSelectColor 27 | override val centerSelectColor: Int 28 | get() = R.styleable.ShapeRadioGroup_sv_centerSelectColor 29 | override val endSelectColor: Int 30 | get() = R.styleable.ShapeRadioGroup_sv_endSelectColor 31 | override val orientation: Int 32 | get() = R.styleable.ShapeRadioGroup_sv_orientation 33 | override val gradientType: Int 34 | get() = R.styleable.ShapeRadioGroup_sv_gradientType 35 | override val gradientRadius: Int 36 | get() = R.styleable.ShapeRadioGroup_sv_gradientRadius 37 | override val strokeWidth: Int 38 | get() = R.styleable.ShapeRadioGroup_sv_strokeWidth 39 | override val dashWidth: Int 40 | get() = R.styleable.ShapeRadioGroup_sv_dashWidth 41 | override val dashGap: Int 42 | get() = R.styleable.ShapeRadioGroup_sv_dashGap 43 | override val radius: Int 44 | get() = R.styleable.ShapeRadioGroup_sv_radius 45 | override val topLeftRadius: Int 46 | get() = R.styleable.ShapeRadioGroup_sv_topLeftRadius 47 | override val topRightRadius: Int 48 | get() = R.styleable.ShapeRadioGroup_sv_topRightRadius 49 | override val bottomLeftRadius: Int 50 | get() = R.styleable.ShapeRadioGroup_sv_bottomLeftRadius 51 | override val bottomRightRadius: Int 52 | get() = R.styleable.ShapeRadioGroup_sv_bottomRightRadius 53 | override val isOpenSelector: Int 54 | get() = 0 55 | override val textNormalColor: Int 56 | get() = 0 57 | override val textSelectColor: Int 58 | get() = 0 59 | override val solidSelectColor: Int 60 | get() = 0 61 | override val strokeSelectColor: Int 62 | get() = 0 63 | } -------------------------------------------------------------------------------- /shapeview/src/main/java/cn/mtjsoft/www/shapeview/styleable/ShapeFrameLayoutStyleable.kt: -------------------------------------------------------------------------------- 1 | package cn.mtjsoft.www.shapeview.styleable 2 | 3 | import cn.mtjsoft.www.shapeview.imp.IStyleable 4 | import cn.mtjsoft.www.shapeview.R 5 | 6 | /** 7 | * @author mtj 8 | * @date 2022/2/7 9 | * @desc 10 | * @email mtjsoft3@gmail.com 11 | */ 12 | class ShapeFrameLayoutStyleable : IStyleable { 13 | override val shape: Int 14 | get() = R.styleable.ShapeFrameLayout_sv_shape 15 | override val solidColor: Int 16 | get() = R.styleable.ShapeFrameLayout_sv_solidColor 17 | override val strokeColor: Int 18 | get() = R.styleable.ShapeFrameLayout_sv_strokeColor 19 | override val startColor: Int 20 | get() = R.styleable.ShapeFrameLayout_sv_startColor 21 | override val centerColor: Int 22 | get() = R.styleable.ShapeFrameLayout_sv_centerColor 23 | override val endColor: Int 24 | get() = R.styleable.ShapeFrameLayout_sv_endColor 25 | override val startSelectColor: Int 26 | get() = R.styleable.ShapeFrameLayout_sv_startSelectColor 27 | override val centerSelectColor: Int 28 | get() = R.styleable.ShapeFrameLayout_sv_centerSelectColor 29 | override val endSelectColor: Int 30 | get() = R.styleable.ShapeFrameLayout_sv_endSelectColor 31 | override val orientation: Int 32 | get() = R.styleable.ShapeFrameLayout_sv_orientation 33 | override val gradientType: Int 34 | get() = R.styleable.ShapeFrameLayout_sv_gradientType 35 | override val gradientRadius: Int 36 | get() = R.styleable.ShapeFrameLayout_sv_gradientRadius 37 | override val strokeWidth: Int 38 | get() = R.styleable.ShapeFrameLayout_sv_strokeWidth 39 | override val dashWidth: Int 40 | get() = R.styleable.ShapeFrameLayout_sv_dashWidth 41 | override val dashGap: Int 42 | get() = R.styleable.ShapeFrameLayout_sv_dashGap 43 | override val radius: Int 44 | get() = R.styleable.ShapeFrameLayout_sv_radius 45 | override val topLeftRadius: Int 46 | get() = R.styleable.ShapeFrameLayout_sv_topLeftRadius 47 | override val topRightRadius: Int 48 | get() = R.styleable.ShapeFrameLayout_sv_topRightRadius 49 | override val bottomLeftRadius: Int 50 | get() = R.styleable.ShapeFrameLayout_sv_bottomLeftRadius 51 | override val bottomRightRadius: Int 52 | get() = R.styleable.ShapeFrameLayout_sv_bottomRightRadius 53 | override val isOpenSelector: Int 54 | get() = 0 55 | override val textNormalColor: Int 56 | get() = 0 57 | override val textSelectColor: Int 58 | get() = 0 59 | override val solidSelectColor: Int 60 | get() = 0 61 | override val strokeSelectColor: Int 62 | get() = 0 63 | } -------------------------------------------------------------------------------- /shapeview/src/main/java/cn/mtjsoft/www/shapeview/styleable/ShapeLinearLayoutStyleable.kt: -------------------------------------------------------------------------------- 1 | package cn.mtjsoft.www.shapeview.styleable 2 | 3 | import cn.mtjsoft.www.shapeview.imp.IStyleable 4 | import cn.mtjsoft.www.shapeview.R 5 | 6 | /** 7 | * @author mtj 8 | * @date 2022/2/7 9 | * @desc 10 | * @email mtjsoft3@gmail.com 11 | */ 12 | class ShapeLinearLayoutStyleable : IStyleable { 13 | override val shape: Int 14 | get() = R.styleable.ShapeLinearLayout_sv_shape 15 | override val solidColor: Int 16 | get() = R.styleable.ShapeLinearLayout_sv_solidColor 17 | override val strokeColor: Int 18 | get() = R.styleable.ShapeLinearLayout_sv_strokeColor 19 | override val startColor: Int 20 | get() = R.styleable.ShapeLinearLayout_sv_startColor 21 | override val centerColor: Int 22 | get() = R.styleable.ShapeLinearLayout_sv_centerColor 23 | override val endColor: Int 24 | get() = R.styleable.ShapeLinearLayout_sv_endColor 25 | override val startSelectColor: Int 26 | get() = R.styleable.ShapeLinearLayout_sv_startSelectColor 27 | override val centerSelectColor: Int 28 | get() = R.styleable.ShapeLinearLayout_sv_centerSelectColor 29 | override val endSelectColor: Int 30 | get() = R.styleable.ShapeLinearLayout_sv_endSelectColor 31 | override val orientation: Int 32 | get() = R.styleable.ShapeLinearLayout_sv_orientation 33 | override val gradientType: Int 34 | get() = R.styleable.ShapeLinearLayout_sv_gradientType 35 | override val gradientRadius: Int 36 | get() = R.styleable.ShapeLinearLayout_sv_gradientRadius 37 | override val strokeWidth: Int 38 | get() = R.styleable.ShapeLinearLayout_sv_strokeWidth 39 | override val dashWidth: Int 40 | get() = R.styleable.ShapeLinearLayout_sv_dashWidth 41 | override val dashGap: Int 42 | get() = R.styleable.ShapeLinearLayout_sv_dashGap 43 | override val radius: Int 44 | get() = R.styleable.ShapeLinearLayout_sv_radius 45 | override val topLeftRadius: Int 46 | get() = R.styleable.ShapeLinearLayout_sv_topLeftRadius 47 | override val topRightRadius: Int 48 | get() = R.styleable.ShapeLinearLayout_sv_topRightRadius 49 | override val bottomLeftRadius: Int 50 | get() = R.styleable.ShapeLinearLayout_sv_bottomLeftRadius 51 | override val bottomRightRadius: Int 52 | get() = R.styleable.ShapeLinearLayout_sv_bottomRightRadius 53 | override val isOpenSelector: Int 54 | get() = 0 55 | override val textNormalColor: Int 56 | get() = 0 57 | override val textSelectColor: Int 58 | get() = 0 59 | override val solidSelectColor: Int 60 | get() = 0 61 | override val strokeSelectColor: Int 62 | get() = 0 63 | } -------------------------------------------------------------------------------- /shapeview/src/main/java/cn/mtjsoft/www/shapeview/styleable/ShapeRecyclerViewStyleable.kt: -------------------------------------------------------------------------------- 1 | package cn.mtjsoft.www.shapeview.styleable 2 | 3 | import cn.mtjsoft.www.shapeview.imp.IStyleable 4 | import cn.mtjsoft.www.shapeview.R 5 | 6 | /** 7 | * @author mtj 8 | * @date 2022/2/7 9 | * @desc 10 | * @email mtjsoft3@gmail.com 11 | */ 12 | class ShapeRecyclerViewStyleable : IStyleable { 13 | override val shape: Int 14 | get() = R.styleable.ShapeRecyclerView_sv_shape 15 | override val solidColor: Int 16 | get() = R.styleable.ShapeRecyclerView_sv_solidColor 17 | override val strokeColor: Int 18 | get() = R.styleable.ShapeRecyclerView_sv_strokeColor 19 | override val startColor: Int 20 | get() = R.styleable.ShapeRecyclerView_sv_startColor 21 | override val centerColor: Int 22 | get() = R.styleable.ShapeRecyclerView_sv_centerColor 23 | override val endColor: Int 24 | get() = R.styleable.ShapeRecyclerView_sv_endColor 25 | override val startSelectColor: Int 26 | get() = R.styleable.ShapeRecyclerView_sv_startSelectColor 27 | override val centerSelectColor: Int 28 | get() = R.styleable.ShapeRecyclerView_sv_centerSelectColor 29 | override val endSelectColor: Int 30 | get() = R.styleable.ShapeRecyclerView_sv_endSelectColor 31 | override val orientation: Int 32 | get() = R.styleable.ShapeRecyclerView_sv_orientation 33 | override val gradientType: Int 34 | get() = R.styleable.ShapeRecyclerView_sv_gradientType 35 | override val gradientRadius: Int 36 | get() = R.styleable.ShapeRecyclerView_sv_gradientRadius 37 | override val strokeWidth: Int 38 | get() = R.styleable.ShapeRecyclerView_sv_strokeWidth 39 | override val dashWidth: Int 40 | get() = R.styleable.ShapeRecyclerView_sv_dashWidth 41 | override val dashGap: Int 42 | get() = R.styleable.ShapeRecyclerView_sv_dashGap 43 | override val radius: Int 44 | get() = R.styleable.ShapeRecyclerView_sv_radius 45 | override val topLeftRadius: Int 46 | get() = R.styleable.ShapeRecyclerView_sv_topLeftRadius 47 | override val topRightRadius: Int 48 | get() = R.styleable.ShapeRecyclerView_sv_topRightRadius 49 | override val bottomLeftRadius: Int 50 | get() = R.styleable.ShapeRecyclerView_sv_bottomLeftRadius 51 | override val bottomRightRadius: Int 52 | get() = R.styleable.ShapeRecyclerView_sv_bottomRightRadius 53 | override val isOpenSelector: Int 54 | get() = 0 55 | override val textNormalColor: Int 56 | get() = 0 57 | override val textSelectColor: Int 58 | get() = 0 59 | override val solidSelectColor: Int 60 | get() = 0 61 | override val strokeSelectColor: Int 62 | get() = 0 63 | } -------------------------------------------------------------------------------- /shapeview/src/main/java/cn/mtjsoft/www/shapeview/styleable/ShapeRelativeLayoutStyleable.kt: -------------------------------------------------------------------------------- 1 | package cn.mtjsoft.www.shapeview.styleable 2 | 3 | import cn.mtjsoft.www.shapeview.imp.IStyleable 4 | import cn.mtjsoft.www.shapeview.R 5 | 6 | /** 7 | * @author mtj 8 | * @date 2022/2/7 9 | * @desc 10 | * @email mtjsoft3@gmail.com 11 | */ 12 | class ShapeRelativeLayoutStyleable : IStyleable { 13 | override val shape: Int 14 | get() = R.styleable.ShapeRelativeLayout_sv_shape 15 | override val solidColor: Int 16 | get() = R.styleable.ShapeRelativeLayout_sv_solidColor 17 | override val strokeColor: Int 18 | get() = R.styleable.ShapeRelativeLayout_sv_strokeColor 19 | override val startColor: Int 20 | get() = R.styleable.ShapeRelativeLayout_sv_startColor 21 | override val centerColor: Int 22 | get() = R.styleable.ShapeRelativeLayout_sv_centerColor 23 | override val endColor: Int 24 | get() = R.styleable.ShapeRelativeLayout_sv_endColor 25 | override val startSelectColor: Int 26 | get() = R.styleable.ShapeRelativeLayout_sv_startSelectColor 27 | override val centerSelectColor: Int 28 | get() = R.styleable.ShapeRelativeLayout_sv_centerSelectColor 29 | override val endSelectColor: Int 30 | get() = R.styleable.ShapeRelativeLayout_sv_endSelectColor 31 | override val orientation: Int 32 | get() = R.styleable.ShapeRelativeLayout_sv_orientation 33 | override val gradientType: Int 34 | get() = R.styleable.ShapeRelativeLayout_sv_gradientType 35 | override val gradientRadius: Int 36 | get() = R.styleable.ShapeRelativeLayout_sv_gradientRadius 37 | override val strokeWidth: Int 38 | get() = R.styleable.ShapeRelativeLayout_sv_strokeWidth 39 | override val dashWidth: Int 40 | get() = R.styleable.ShapeRelativeLayout_sv_dashWidth 41 | override val dashGap: Int 42 | get() = R.styleable.ShapeRelativeLayout_sv_dashGap 43 | override val radius: Int 44 | get() = R.styleable.ShapeRelativeLayout_sv_radius 45 | override val topLeftRadius: Int 46 | get() = R.styleable.ShapeRelativeLayout_sv_topLeftRadius 47 | override val topRightRadius: Int 48 | get() = R.styleable.ShapeRelativeLayout_sv_topRightRadius 49 | override val bottomLeftRadius: Int 50 | get() = R.styleable.ShapeRelativeLayout_sv_bottomLeftRadius 51 | override val bottomRightRadius: Int 52 | get() = R.styleable.ShapeRelativeLayout_sv_bottomRightRadius 53 | override val isOpenSelector: Int 54 | get() = 0 55 | override val textNormalColor: Int 56 | get() = 0 57 | override val textSelectColor: Int 58 | get() = 0 59 | override val solidSelectColor: Int 60 | get() = 0 61 | override val strokeSelectColor: Int 62 | get() = 0 63 | } -------------------------------------------------------------------------------- /shapeview/src/main/java/cn/mtjsoft/www/shapeview/styleable/ShapeConstraintLayoutStyleable.kt: -------------------------------------------------------------------------------- 1 | package cn.mtjsoft.www.shapeview.styleable 2 | 3 | import cn.mtjsoft.www.shapeview.imp.IStyleable 4 | import cn.mtjsoft.www.shapeview.R 5 | 6 | /** 7 | * @author mtj 8 | * @date 2022/2/7 9 | * @desc 10 | * @email mtjsoft3@gmail.com 11 | */ 12 | class ShapeConstraintLayoutStyleable : IStyleable { 13 | override val shape: Int 14 | get() = R.styleable.ShapeConstraintLayout_sv_shape 15 | override val solidColor: Int 16 | get() = R.styleable.ShapeConstraintLayout_sv_solidColor 17 | override val strokeColor: Int 18 | get() = R.styleable.ShapeConstraintLayout_sv_strokeColor 19 | override val startColor: Int 20 | get() = R.styleable.ShapeConstraintLayout_sv_startColor 21 | override val centerColor: Int 22 | get() = R.styleable.ShapeConstraintLayout_sv_centerColor 23 | override val endColor: Int 24 | get() = R.styleable.ShapeConstraintLayout_sv_endColor 25 | override val startSelectColor: Int 26 | get() = R.styleable.ShapeConstraintLayout_sv_startSelectColor 27 | override val centerSelectColor: Int 28 | get() = R.styleable.ShapeConstraintLayout_sv_centerSelectColor 29 | override val endSelectColor: Int 30 | get() = R.styleable.ShapeConstraintLayout_sv_endSelectColor 31 | override val orientation: Int 32 | get() = R.styleable.ShapeConstraintLayout_sv_orientation 33 | override val gradientType: Int 34 | get() = R.styleable.ShapeConstraintLayout_sv_gradientType 35 | override val gradientRadius: Int 36 | get() = R.styleable.ShapeConstraintLayout_sv_gradientRadius 37 | override val strokeWidth: Int 38 | get() = R.styleable.ShapeConstraintLayout_sv_strokeWidth 39 | override val dashWidth: Int 40 | get() = R.styleable.ShapeConstraintLayout_sv_dashWidth 41 | override val dashGap: Int 42 | get() = R.styleable.ShapeConstraintLayout_sv_dashGap 43 | override val radius: Int 44 | get() = R.styleable.ShapeConstraintLayout_sv_radius 45 | override val topLeftRadius: Int 46 | get() = R.styleable.ShapeConstraintLayout_sv_topLeftRadius 47 | override val topRightRadius: Int 48 | get() = R.styleable.ShapeConstraintLayout_sv_topRightRadius 49 | override val bottomLeftRadius: Int 50 | get() = R.styleable.ShapeConstraintLayout_sv_bottomLeftRadius 51 | override val bottomRightRadius: Int 52 | get() = R.styleable.ShapeConstraintLayout_sv_bottomRightRadius 53 | override val isOpenSelector: Int 54 | get() = 0 55 | override val textNormalColor: Int 56 | get() = 0 57 | override val textSelectColor: Int 58 | get() = 0 59 | override val solidSelectColor: Int 60 | get() = 0 61 | override val strokeSelectColor: Int 62 | get() = 0 63 | } -------------------------------------------------------------------------------- /shapeview/src/main/java/cn/mtjsoft/www/shapeview/styleable/ShapeCheckBoxStyleable.kt: -------------------------------------------------------------------------------- 1 | package cn.mtjsoft.www.shapeview.styleable 2 | 3 | import cn.mtjsoft.www.shapeview.imp.IStyleable 4 | import cn.mtjsoft.www.shapeview.R 5 | 6 | /** 7 | * @author mtj 8 | * @date 2022/2/7 9 | * @desc 10 | * @email mtjsoft3@gmail.com 11 | */ 12 | class ShapeCheckBoxStyleable : IStyleable { 13 | override val shape: Int 14 | get() = R.styleable.ShapeCheckBox_sv_shape 15 | override val solidColor: Int 16 | get() = R.styleable.ShapeCheckBox_sv_solidColor 17 | override val strokeColor: Int 18 | get() = R.styleable.ShapeCheckBox_sv_strokeColor 19 | override val startColor: Int 20 | get() = R.styleable.ShapeCheckBox_sv_startColor 21 | override val centerColor: Int 22 | get() = R.styleable.ShapeCheckBox_sv_centerColor 23 | override val endColor: Int 24 | get() = R.styleable.ShapeCheckBox_sv_endColor 25 | override val startSelectColor: Int 26 | get() = R.styleable.ShapeCheckBox_sv_startSelectColor 27 | override val centerSelectColor: Int 28 | get() = R.styleable.ShapeCheckBox_sv_centerSelectColor 29 | override val endSelectColor: Int 30 | get() = R.styleable.ShapeCheckBox_sv_endSelectColor 31 | override val orientation: Int 32 | get() = R.styleable.ShapeCheckBox_sv_orientation 33 | override val gradientType: Int 34 | get() = R.styleable.ShapeCheckBox_sv_gradientType 35 | override val gradientRadius: Int 36 | get() = R.styleable.ShapeCheckBox_sv_gradientRadius 37 | override val strokeWidth: Int 38 | get() = R.styleable.ShapeCheckBox_sv_strokeWidth 39 | override val dashWidth: Int 40 | get() = R.styleable.ShapeCheckBox_sv_dashWidth 41 | override val dashGap: Int 42 | get() = R.styleable.ShapeCheckBox_sv_dashGap 43 | override val radius: Int 44 | get() = R.styleable.ShapeCheckBox_sv_radius 45 | override val topLeftRadius: Int 46 | get() = R.styleable.ShapeCheckBox_sv_topLeftRadius 47 | override val topRightRadius: Int 48 | get() = R.styleable.ShapeCheckBox_sv_topRightRadius 49 | override val bottomLeftRadius: Int 50 | get() = R.styleable.ShapeCheckBox_sv_bottomLeftRadius 51 | override val bottomRightRadius: Int 52 | get() = R.styleable.ShapeCheckBox_sv_bottomRightRadius 53 | override val isOpenSelector: Int 54 | get() = R.styleable.ShapeCheckBox_sv_openSelector 55 | override val textNormalColor: Int 56 | get() = R.styleable.ShapeCheckBox_sv_textNormalColor 57 | override val textSelectColor: Int 58 | get() = R.styleable.ShapeCheckBox_sv_textSelectColor 59 | override val solidSelectColor: Int 60 | get() = R.styleable.ShapeCheckBox_sv_solidSelectColor 61 | override val strokeSelectColor: Int 62 | get() = R.styleable.ShapeCheckBox_sv_strokeSelectColor 63 | } -------------------------------------------------------------------------------- /shapeview/src/main/java/cn/mtjsoft/www/shapeview/styleable/ShapeRadioButtonStyleable.kt: -------------------------------------------------------------------------------- 1 | package cn.mtjsoft.www.shapeview.styleable 2 | 3 | import cn.mtjsoft.www.shapeview.imp.IStyleable 4 | import cn.mtjsoft.www.shapeview.R 5 | 6 | /** 7 | * @author mtj 8 | * @date 2022/2/7 9 | * @desc 10 | * @email mtjsoft3@gmail.com 11 | */ 12 | class ShapeRadioButtonStyleable : IStyleable { 13 | override val shape: Int 14 | get() = R.styleable.ShapeRadioButton_sv_shape 15 | override val solidColor: Int 16 | get() = R.styleable.ShapeRadioButton_sv_solidColor 17 | override val strokeColor: Int 18 | get() = R.styleable.ShapeRadioButton_sv_strokeColor 19 | override val startColor: Int 20 | get() = R.styleable.ShapeRadioButton_sv_startColor 21 | override val centerColor: Int 22 | get() = R.styleable.ShapeRadioButton_sv_centerColor 23 | override val endColor: Int 24 | get() = R.styleable.ShapeRadioButton_sv_endColor 25 | override val startSelectColor: Int 26 | get() = R.styleable.ShapeRadioButton_sv_startSelectColor 27 | override val centerSelectColor: Int 28 | get() = R.styleable.ShapeRadioButton_sv_centerSelectColor 29 | override val endSelectColor: Int 30 | get() = R.styleable.ShapeRadioButton_sv_endSelectColor 31 | override val orientation: Int 32 | get() = R.styleable.ShapeRadioButton_sv_orientation 33 | override val gradientType: Int 34 | get() = R.styleable.ShapeRadioButton_sv_gradientType 35 | override val gradientRadius: Int 36 | get() = R.styleable.ShapeRadioButton_sv_gradientRadius 37 | override val strokeWidth: Int 38 | get() = R.styleable.ShapeRadioButton_sv_strokeWidth 39 | override val dashWidth: Int 40 | get() = R.styleable.ShapeRadioButton_sv_dashWidth 41 | override val dashGap: Int 42 | get() = R.styleable.ShapeRadioButton_sv_dashGap 43 | override val radius: Int 44 | get() = R.styleable.ShapeRadioButton_sv_radius 45 | override val topLeftRadius: Int 46 | get() = R.styleable.ShapeRadioButton_sv_topLeftRadius 47 | override val topRightRadius: Int 48 | get() = R.styleable.ShapeRadioButton_sv_topRightRadius 49 | override val bottomLeftRadius: Int 50 | get() = R.styleable.ShapeRadioButton_sv_bottomLeftRadius 51 | override val bottomRightRadius: Int 52 | get() = R.styleable.ShapeRadioButton_sv_bottomRightRadius 53 | override val isOpenSelector: Int 54 | get() = R.styleable.ShapeRadioButton_sv_openSelector 55 | override val textNormalColor: Int 56 | get() = R.styleable.ShapeRadioButton_sv_textNormalColor 57 | override val textSelectColor: Int 58 | get() = R.styleable.ShapeRadioButton_sv_textSelectColor 59 | override val solidSelectColor: Int 60 | get() = R.styleable.ShapeRadioButton_sv_solidSelectColor 61 | override val strokeSelectColor: Int 62 | get() = R.styleable.ShapeRadioButton_sv_strokeSelectColor 63 | } -------------------------------------------------------------------------------- /shapeview/src/main/java/cn/mtjsoft/www/shapeview/ShapeCheckBox.kt: -------------------------------------------------------------------------------- 1 | package cn.mtjsoft.www.shapeview 2 | 3 | import android.content.Context 4 | import android.content.res.ColorStateList 5 | import android.graphics.drawable.GradientDrawable 6 | import android.graphics.drawable.StateListDrawable 7 | import android.util.AttributeSet 8 | import androidx.appcompat.widget.AppCompatCheckBox 9 | import cn.mtjsoft.www.shapeview.builder.CustomBuilder 10 | import cn.mtjsoft.www.shapeview.styleable.ShapeCheckBoxStyleable 11 | import cn.mtjsoft.www.shapeview.util.GradientDrawableUtil.Companion.init 12 | 13 | /** 14 | * 实现自定义圆角背景 15 | */ 16 | class ShapeCheckBox @JvmOverloads constructor( 17 | context: Context, 18 | attrs: AttributeSet, 19 | defStyleAttr: Int = 0 20 | ) : AppCompatCheckBox(context, attrs, defStyleAttr) { 21 | //自定背景边框Drawable 22 | var gradientDrawable: GradientDrawable? = null 23 | private set 24 | 25 | //选中时的Drawable 26 | var selectorDrawable: GradientDrawable? = null 27 | private set 28 | private lateinit var builder: CustomBuilder 29 | 30 | /** 31 | * 初始化参数 32 | */ 33 | private fun init(context: Context, attrs: AttributeSet) { 34 | val ta = context.obtainStyledAttributes(attrs, R.styleable.ShapeCheckBox) 35 | builder = CustomBuilder(this, ta, STYLEABLE) 36 | setCustomBackground() 37 | } 38 | 39 | fun setBuilder(builder: CustomBuilder) { 40 | this.builder = builder 41 | setCustomBackground() 42 | } 43 | 44 | fun getBuilder(): CustomBuilder { 45 | return builder 46 | } 47 | 48 | private fun setCustomBackground() { 49 | builder.setLayerType(this) 50 | gradientDrawable = init().getNormalDrawable(builder) 51 | //如果设置了选中时的背景 52 | if (builder.isOpenSelector) { 53 | selectorDrawable = init().getSelectorDrawable(builder) 54 | //动态生成Selector 55 | val stateListDrawable = StateListDrawable() 56 | //是否选中 57 | val checked = android.R.attr.state_checked 58 | stateListDrawable.addState(intArrayOf(checked), selectorDrawable) 59 | stateListDrawable.addState(intArrayOf(), gradientDrawable) 60 | // 设置背景色 61 | this.background = stateListDrawable 62 | val states = arrayOfNulls(2) 63 | states[0] = intArrayOf(android.R.attr.state_checked) 64 | states[1] = intArrayOf() 65 | val textColorStateList = ColorStateList( 66 | states, 67 | intArrayOf(builder.textSelectColor, builder.textNormalColor) 68 | ) 69 | this.setTextColor(textColorStateList) 70 | } else { 71 | this.background = gradientDrawable 72 | } 73 | this.isFocusable = false 74 | this.isClickable = true 75 | } 76 | 77 | companion object { 78 | private val STYLEABLE = ShapeCheckBoxStyleable() 79 | } 80 | 81 | init { 82 | init(context, attrs) 83 | } 84 | } -------------------------------------------------------------------------------- /shapeview/src/main/java/cn/mtjsoft/www/shapeview/ShapeRadioButton.kt: -------------------------------------------------------------------------------- 1 | package cn.mtjsoft.www.shapeview 2 | 3 | import android.content.Context 4 | import android.content.res.ColorStateList 5 | import android.graphics.drawable.GradientDrawable 6 | import android.graphics.drawable.StateListDrawable 7 | import android.util.AttributeSet 8 | import androidx.appcompat.widget.AppCompatRadioButton 9 | import cn.mtjsoft.www.shapeview.builder.CustomBuilder 10 | import cn.mtjsoft.www.shapeview.styleable.ShapeRadioButtonStyleable 11 | import cn.mtjsoft.www.shapeview.util.GradientDrawableUtil.Companion.init 12 | 13 | /** 14 | * 实现自定义圆角背景 15 | */ 16 | class ShapeRadioButton @JvmOverloads constructor( 17 | context: Context, 18 | attrs: AttributeSet, 19 | defStyleAttr: Int = 0 20 | ) : AppCompatRadioButton(context, attrs, defStyleAttr) { 21 | //自定背景边框Drawable 22 | var gradientDrawable: GradientDrawable? = null 23 | private set 24 | 25 | //选中时的Drawable 26 | var selectorDrawable: GradientDrawable? = null 27 | private set 28 | private lateinit var builder: CustomBuilder 29 | 30 | /** 31 | * 初始化参数 32 | * 33 | * @param context 34 | * @param attrs 35 | */ 36 | private fun init(context: Context, attrs: AttributeSet) { 37 | val ta = context.obtainStyledAttributes(attrs, R.styleable.ShapeRadioButton) 38 | builder = CustomBuilder(this, ta, STYLEABLE) 39 | setCustomBackground() 40 | } 41 | 42 | fun setBuilder(builder: CustomBuilder) { 43 | this.builder = builder 44 | setCustomBackground() 45 | } 46 | 47 | fun getBuilder(): CustomBuilder { 48 | return builder 49 | } 50 | 51 | private fun setCustomBackground() { 52 | builder.setLayerType(this) 53 | gradientDrawable = init().getNormalDrawable(builder) 54 | //如果设置了选中时的背景 55 | if (builder.isOpenSelector) { 56 | selectorDrawable = init().getSelectorDrawable(builder) 57 | //动态生成Selector 58 | val stateListDrawable = StateListDrawable() 59 | //是否选中 60 | val checked = android.R.attr.state_checked 61 | stateListDrawable.addState(intArrayOf(checked), selectorDrawable) 62 | stateListDrawable.addState(intArrayOf(), gradientDrawable) 63 | // 设置背景色 64 | this.background = stateListDrawable 65 | val states = arrayOfNulls(2) 66 | states[0] = intArrayOf(android.R.attr.state_checked) 67 | states[1] = intArrayOf() 68 | val textColorStateList = ColorStateList( 69 | states, 70 | intArrayOf(builder.textSelectColor, builder.textNormalColor) 71 | ) 72 | this.setTextColor(textColorStateList) 73 | } else { 74 | this.background = gradientDrawable 75 | } 76 | this.isFocusable = false 77 | this.isClickable = true 78 | } 79 | 80 | companion object { 81 | private val STYLEABLE = ShapeRadioButtonStyleable() 82 | } 83 | 84 | init { 85 | init(context, attrs) 86 | } 87 | } -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 15 | 16 | 17 | 39 | 59 | 60 | 61 | 62 | 63 | 64 | 66 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /shapeview/src/main/java/cn/mtjsoft/www/shapeview/util/GradientDrawableUtil.kt: -------------------------------------------------------------------------------- 1 | package cn.mtjsoft.www.shapeview.util 2 | 3 | import android.graphics.drawable.GradientDrawable 4 | import cn.mtjsoft.www.shapeview.builder.CustomBuilder 5 | import cn.mtjsoft.www.shapeview.builder.CustomBuilder.GradientType 6 | 7 | class GradientDrawableUtil { 8 | /** 9 | * @param radius 四个角的半径 10 | * @param colors 渐变的颜色 11 | * @param strokeWidth 边框宽度 12 | * @param strokeColor 边框颜色 13 | * @return 14 | */ 15 | private fun getNeedDrawable( 16 | @CustomBuilder.Shape shape: Int, 17 | radius: FloatArray, 18 | colors: IntArray, 19 | strokeWidth: Int, 20 | strokeColor: Int, 21 | dashWidth: Float, 22 | dashGap: Float, 23 | orientation: GradientDrawable.Orientation, 24 | @GradientType gradient: Int, 25 | gradientRadius: Float 26 | ): GradientDrawable { 27 | val drawable = GradientDrawable() 28 | drawable.setDither(true) 29 | drawable.shape = shape 30 | drawable.cornerRadii = radius 31 | if (strokeWidth > 0) { 32 | if (dashWidth <= 0 || dashGap <= 0) { 33 | drawable.setStroke(strokeWidth, strokeColor) 34 | } else { 35 | drawable.setStroke(strokeWidth, strokeColor, dashWidth, dashGap) 36 | } 37 | } 38 | drawable.orientation = orientation 39 | drawable.colors = colors 40 | drawable.gradientType = gradient 41 | if (gradient == GradientDrawable.RADIAL_GRADIENT) { 42 | drawable.gradientRadius = gradientRadius 43 | } 44 | return drawable 45 | } 46 | 47 | /** 48 | * @param radius 四个角的半径 49 | * @param bgColor 背景颜色 50 | * @param strokeWidth 边框宽度 51 | * @param strokeColor 边框颜色 52 | * @return 53 | */ 54 | private fun getNeedDrawable( 55 | @CustomBuilder.Shape shape: Int, 56 | radius: FloatArray, 57 | bgColor: Int, 58 | strokeWidth: Int, 59 | strokeColor: Int 60 | ): GradientDrawable { 61 | val drawable = GradientDrawable() 62 | drawable.shape = shape 63 | drawable.cornerRadii = radius 64 | drawable.setStroke(strokeWidth, strokeColor) 65 | drawable.setColor(bgColor) 66 | return drawable 67 | } 68 | 69 | /** 70 | * @param radius 四个角的半径 71 | * @param bgColor 背景颜色 72 | * @param strokeWidth 边框宽度 73 | * @param strokeColor 边框颜色 74 | * @param dashWidth 虚线边框宽度 75 | * @param dashGap 虚线边框间隙 76 | * @return 77 | */ 78 | private fun getNeedDrawable( 79 | @CustomBuilder.Shape shape: Int, 80 | radius: FloatArray, 81 | bgColor: Int, 82 | strokeWidth: Int, 83 | strokeColor: Int, 84 | dashWidth: Float, 85 | dashGap: Float 86 | ): GradientDrawable { 87 | if (dashWidth <= 0 || dashGap <= 0) { 88 | return getNeedDrawable(shape, radius, bgColor, strokeWidth, strokeColor) 89 | } 90 | val drawable = GradientDrawable() 91 | drawable.shape = shape 92 | drawable.cornerRadii = radius 93 | drawable.setStroke(strokeWidth, strokeColor, dashWidth, dashGap) 94 | drawable.setColor(bgColor) 95 | return drawable 96 | } 97 | 98 | /** 99 | * 获取常规 圆角 背景 100 | * 101 | * @param builder 102 | * @return 103 | */ 104 | fun getNormalDrawable(builder: CustomBuilder): GradientDrawable { 105 | // 渐变色 106 | if (builder.startColor != 0 && builder.endColor != 0) { 107 | var size = 2 108 | if (builder.centerColor != 0) { 109 | size = 3 110 | } 111 | val colors = IntArray(size) 112 | colors[0] = builder.startColor 113 | if (size == 3) { 114 | colors[1] = builder.centerColor 115 | colors[2] = builder.endColor 116 | } else { 117 | colors[1] = builder.endColor 118 | } 119 | return getNeedDrawable( 120 | builder.shape, 121 | floatArrayOf( 122 | builder.topLeftRadius.toFloat(), 123 | builder.topLeftRadius.toFloat(), 124 | builder.topRightRadius.toFloat(), 125 | builder.topRightRadius.toFloat(), 126 | builder.bottomRightRadius.toFloat(), 127 | builder.bottomRightRadius.toFloat(), 128 | builder.bottomLeftRadius.toFloat(), 129 | builder.bottomLeftRadius.toFloat() 130 | ), 131 | colors, 132 | builder.strokeWidth, 133 | builder.strokeColor, 134 | builder.dashWidth, 135 | builder.dashGap, 136 | builder.orientation, 137 | builder.gradientType, 138 | builder.gradientRadius 139 | ) 140 | } 141 | // 常规 142 | return getNeedDrawable( 143 | builder.shape, 144 | floatArrayOf( 145 | builder.topLeftRadius.toFloat(), 146 | builder.topLeftRadius.toFloat(), 147 | builder.topRightRadius.toFloat(), 148 | builder.topRightRadius.toFloat(), 149 | builder.bottomRightRadius.toFloat(), 150 | builder.bottomRightRadius.toFloat(), 151 | builder.bottomLeftRadius.toFloat(), 152 | builder.bottomLeftRadius.toFloat() 153 | ), 154 | builder.solidColor, 155 | builder.strokeWidth, 156 | builder.strokeColor, 157 | builder.dashWidth, 158 | builder.dashGap 159 | ) 160 | } 161 | 162 | /** 163 | * 获取选中状态 圆角 背景 164 | * 165 | * @param builder 166 | * @return 167 | */ 168 | fun getSelectorDrawable(builder: CustomBuilder): GradientDrawable { 169 | // 渐变色 170 | if (builder.startSelectColor != 0 && builder.endSelectColor != 0) { 171 | var size = 2 172 | if (builder.centerSelectColor != 0) { 173 | size = 3 174 | } 175 | val colors = IntArray(size) 176 | colors[0] = builder.startSelectColor 177 | if (size == 3) { 178 | colors[1] = builder.centerSelectColor 179 | colors[2] = builder.endSelectColor 180 | } else { 181 | colors[1] = builder.endSelectColor 182 | } 183 | return getNeedDrawable( 184 | builder.shape, 185 | floatArrayOf( 186 | builder.topLeftRadius.toFloat(), 187 | builder.topLeftRadius.toFloat(), 188 | builder.topRightRadius.toFloat(), 189 | builder.topRightRadius.toFloat(), 190 | builder.bottomRightRadius.toFloat(), 191 | builder.bottomRightRadius.toFloat(), 192 | builder.bottomLeftRadius.toFloat(), 193 | builder.bottomLeftRadius.toFloat() 194 | ), 195 | colors, 196 | builder.strokeWidth, 197 | builder.strokeColor, 198 | builder.dashWidth, 199 | builder.dashGap, 200 | builder.orientation, 201 | builder.gradientType, 202 | builder.gradientRadius 203 | ) 204 | } 205 | return getNeedDrawable( 206 | builder.shape, 207 | floatArrayOf( 208 | builder.topLeftRadius.toFloat(), 209 | builder.topLeftRadius.toFloat(), 210 | builder.topRightRadius.toFloat(), 211 | builder.topRightRadius.toFloat(), 212 | builder.bottomRightRadius.toFloat(), 213 | builder.bottomRightRadius.toFloat(), 214 | builder.bottomLeftRadius.toFloat(), 215 | builder.bottomLeftRadius.toFloat() 216 | ), 217 | builder.solidSelectColor, 218 | builder.strokeWidth, 219 | builder.strokeSelectColor, 220 | builder.dashWidth, 221 | builder.dashGap 222 | ) 223 | } 224 | 225 | companion object { 226 | private val gradientDrawableUtil: GradientDrawableUtil by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) { 227 | GradientDrawableUtil() 228 | } 229 | 230 | @JvmStatic 231 | fun init(): GradientDrawableUtil { 232 | return gradientDrawableUtil 233 | } 234 | } 235 | } -------------------------------------------------------------------------------- /shapeview/src/main/java/cn/mtjsoft/www/shapeview/builder/CustomBuilder.kt: -------------------------------------------------------------------------------- 1 | package cn.mtjsoft.www.shapeview.builder 2 | 3 | import android.content.res.TypedArray 4 | import android.graphics.Color 5 | import android.graphics.drawable.GradientDrawable 6 | import android.view.View 7 | import androidx.annotation.IntDef 8 | import cn.mtjsoft.www.shapeview.imp.BuilderImp 9 | import cn.mtjsoft.www.shapeview.imp.IStyleable 10 | 11 | class CustomBuilder : BuilderImp { 12 | private lateinit var mView: View 13 | 14 | /** 15 | * GET 16 | */ 17 | @Shape 18 | var shape = GradientDrawable.RECTANGLE 19 | private set 20 | 21 | //填充色 22 | var solidColor = 0 23 | private set 24 | 25 | //边框色 26 | var strokeColor = 0 27 | private set 28 | 29 | //渐变开始颜色 30 | var startColor = 0 31 | private set 32 | 33 | //渐变中间色 34 | var centerColor = 0 35 | private set 36 | 37 | //渐变结束色 38 | var endColor = 0 39 | private set 40 | 41 | //openSelector开启时,选中时的渐变颜色 42 | var startSelectColor = 0 43 | private set 44 | var centerSelectColor = 0 45 | private set 46 | var endSelectColor = 0 47 | private set 48 | 49 | //渐变方向 50 | var orientation: GradientDrawable.Orientation = GradientDrawable.Orientation.LEFT_RIGHT 51 | private set 52 | 53 | //渐变类型 支持 线性渐变,放射性渐变,扫描式渐变 54 | @GradientType 55 | var gradientType = GradientDrawable.LINEAR_GRADIENT 56 | private set 57 | 58 | //渐变半径. 只有当渐变类型设置为 RADIAL_GRADIENT 时,半径才有效。 59 | var gradientRadius = 0f 60 | private set 61 | 62 | //边框宽度 63 | var strokeWidth = 0 64 | private set 65 | 66 | //虚线边框宽度 67 | var dashWidth = 0f 68 | private set 69 | 70 | //虚线边框间隙 71 | var dashGap = 0f 72 | private set 73 | 74 | //四个角的弧度 75 | var radius = 0 76 | private set 77 | var topLeftRadius = radius 78 | private set 79 | var topRightRadius = radius 80 | private set 81 | var bottomLeftRadius = radius 82 | private set 83 | var bottomRightRadius = radius 84 | private set 85 | 86 | // 是否使用选择器 87 | var isOpenSelector = false 88 | private set 89 | 90 | // 未选中的字体颜色 91 | var textNormalColor = Color.BLACK 92 | private set 93 | 94 | // 选中的字体颜色 95 | var textSelectColor = Color.RED 96 | private set 97 | 98 | // 选中填充色 99 | var solidSelectColor = 0 100 | private set 101 | 102 | // 选中边框色 103 | var strokeSelectColor = 0 104 | private set 105 | 106 | @IntDef( 107 | GradientDrawable.LINEAR_GRADIENT, 108 | GradientDrawable.RADIAL_GRADIENT, 109 | GradientDrawable.SWEEP_GRADIENT 110 | ) 111 | @kotlin.annotation.Retention(AnnotationRetention.SOURCE) 112 | annotation class GradientType 113 | 114 | @IntDef( 115 | GradientDrawable.RECTANGLE, 116 | GradientDrawable.OVAL, 117 | GradientDrawable.LINE, 118 | GradientDrawable.RING 119 | ) 120 | @kotlin.annotation.Retention(AnnotationRetention.SOURCE) 121 | annotation class Shape {} 122 | 123 | constructor() 124 | constructor(view: View, ta: TypedArray, styleable: IStyleable) { 125 | mView = view 126 | shape = ta.getInt(styleable.shape, GradientDrawable.RECTANGLE) 127 | if (shape > GradientDrawable.RING) { 128 | shape = GradientDrawable.RECTANGLE 129 | } 130 | // 渐变 131 | startColor = ta.getColor(styleable.startColor, 0) 132 | centerColor = ta.getColor(styleable.centerColor, 0) 133 | endColor = ta.getColor(styleable.endColor, 0) 134 | startSelectColor = ta.getColor(styleable.startSelectColor, 0) 135 | centerSelectColor = ta.getColor(styleable.centerSelectColor, 0) 136 | endSelectColor = ta.getColor(styleable.endSelectColor, 0) 137 | var orientation = ta.getInt(styleable.orientation, 6) 138 | if (orientation > 7) { 139 | orientation = 6 140 | } 141 | setOrientationById(orientation) 142 | gradientType = ta.getInt(styleable.gradientType, GradientDrawable.LINEAR_GRADIENT) 143 | if (gradientType > GradientDrawable.SWEEP_GRADIENT) { 144 | gradientType = GradientDrawable.LINEAR_GRADIENT 145 | } 146 | gradientRadius = ta.getFloat(styleable.gradientRadius, 0f) 147 | // 填充以及边框 148 | solidColor = ta.getColor(styleable.solidColor, Color.TRANSPARENT) 149 | strokeColor = ta.getColor(styleable.strokeColor, Color.TRANSPARENT) 150 | strokeWidth = ta.getDimensionPixelSize(styleable.strokeWidth, 0) 151 | dashWidth = ta.getDimensionPixelSize(styleable.dashWidth, 0).toFloat() 152 | dashGap = ta.getDimensionPixelSize(styleable.dashGap, 0).toFloat() 153 | // 四个角单独设置会覆盖radius设置 154 | radius = ta.getDimensionPixelSize(styleable.radius, 0) 155 | topLeftRadius = ta.getDimensionPixelSize(styleable.topLeftRadius, radius) 156 | topRightRadius = ta.getDimensionPixelSize(styleable.topRightRadius, radius) 157 | bottomLeftRadius = ta.getDimensionPixelSize(styleable.bottomLeftRadius, radius) 158 | bottomRightRadius = ta.getDimensionPixelSize(styleable.bottomRightRadius, radius) 159 | // 选择器 160 | isOpenSelector = ta.getBoolean(styleable.isOpenSelector, false) 161 | if (isOpenSelector) { 162 | textNormalColor = ta.getColor(styleable.textNormalColor, Color.BLACK) 163 | textSelectColor = ta.getColor(styleable.textSelectColor, Color.RED) 164 | solidSelectColor = ta.getColor(styleable.solidSelectColor, Color.TRANSPARENT) 165 | strokeSelectColor = ta.getColor(styleable.strokeSelectColor, Color.TRANSPARENT) 166 | } 167 | ta.recycle() 168 | } 169 | 170 | fun setLayerType(view: View) { 171 | mView = view 172 | // 有虚线,需要关闭硬件加速 173 | if (dashWidth > 0 && dashGap > 0) { 174 | // 需要关闭硬件加速,否则虚线或者阴影在某些手机上面无法生效 175 | mView.setLayerType(View.LAYER_TYPE_SOFTWARE, null) 176 | } 177 | } 178 | 179 | override fun setShape(@Shape shape: Int): CustomBuilder { 180 | this.shape = shape 181 | return this 182 | } 183 | 184 | override fun setSolidColor(solidColor: Int): CustomBuilder { 185 | this.solidColor = solidColor 186 | return this 187 | } 188 | 189 | override fun setStrokeColor(strokeColor: Int): CustomBuilder { 190 | this.strokeColor = strokeColor 191 | return this 192 | } 193 | 194 | override fun setColors(startColor: Int, centerColor: Int, endColor: Int): CustomBuilder { 195 | this.startColor = startColor 196 | this.centerColor = centerColor 197 | this.endColor = endColor 198 | return this 199 | } 200 | 201 | override fun setSelectColors(startColor: Int, centerColor: Int, endColor: Int): CustomBuilder { 202 | startSelectColor = startColor 203 | centerSelectColor = centerColor 204 | endSelectColor = endColor 205 | return this 206 | } 207 | 208 | override fun setOrientation(orientation: GradientDrawable.Orientation): CustomBuilder { 209 | this.orientation = orientation 210 | return this 211 | } 212 | 213 | private fun setOrientationById(orientation: Int): CustomBuilder { 214 | when (orientation) { 215 | 0 -> this.orientation = GradientDrawable.Orientation.TOP_BOTTOM 216 | 1 -> this.orientation = GradientDrawable.Orientation.TR_BL 217 | 2 -> this.orientation = GradientDrawable.Orientation.RIGHT_LEFT 218 | 3 -> this.orientation = GradientDrawable.Orientation.BR_TL 219 | 4 -> this.orientation = GradientDrawable.Orientation.BOTTOM_TOP 220 | 5 -> this.orientation = GradientDrawable.Orientation.BL_TR 221 | 7 -> this.orientation = GradientDrawable.Orientation.TL_BR 222 | else -> this.orientation = GradientDrawable.Orientation.LEFT_RIGHT 223 | } 224 | return this 225 | } 226 | 227 | override fun setGradientType(@GradientType gradientType: Int): CustomBuilder { 228 | this.gradientType = gradientType 229 | return this 230 | } 231 | 232 | override fun setGradientRadius(gradientRadius: Float): CustomBuilder { 233 | this.gradientRadius = gradientRadius 234 | return this 235 | } 236 | 237 | override fun setStrokeWidth(strokeWidth: Int): CustomBuilder { 238 | this.strokeWidth = strokeWidth 239 | return this 240 | } 241 | 242 | override fun setDashWidth(dashWidth: Float): CustomBuilder { 243 | this.dashWidth = dashWidth 244 | return this 245 | } 246 | 247 | override fun setDashGap(dashGap: Float): CustomBuilder { 248 | this.dashGap = dashGap 249 | return this 250 | } 251 | 252 | override fun setRadius(radius: Int): CustomBuilder { 253 | this.radius = radius 254 | return this 255 | } 256 | 257 | override fun setTopLeftRadius(topLeftRadius: Int): CustomBuilder { 258 | this.topLeftRadius = topLeftRadius 259 | return this 260 | } 261 | 262 | override fun setTopRightRadius(topRightRadius: Int): CustomBuilder { 263 | this.topRightRadius = topRightRadius 264 | return this 265 | } 266 | 267 | override fun setBottomLeftRadius(bottomLeftRadius: Int): CustomBuilder { 268 | this.bottomLeftRadius = bottomLeftRadius 269 | return this 270 | } 271 | 272 | override fun setBottomRightRadius(bottomRightRadius: Int): CustomBuilder { 273 | this.bottomRightRadius = bottomRightRadius 274 | return this 275 | } 276 | 277 | override fun setOpenSelector(openSelector: Boolean): CustomBuilder { 278 | isOpenSelector = openSelector 279 | return this 280 | } 281 | 282 | override fun setTextNormalColor(textNormalColor: Int): CustomBuilder { 283 | this.textNormalColor = textNormalColor 284 | return this 285 | } 286 | 287 | override fun setTextSelectColor(textSelectColor: Int): CustomBuilder { 288 | this.textSelectColor = textSelectColor 289 | return this 290 | } 291 | 292 | override fun setSolidSelectColor(solidSelectColor: Int): CustomBuilder { 293 | this.solidSelectColor = solidSelectColor 294 | return this 295 | } 296 | 297 | override fun setStrokeSelectColor(strokeSelectColor: Int): CustomBuilder { 298 | this.strokeSelectColor = strokeSelectColor 299 | return this 300 | } 301 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 21 | 22 | 34 | 35 | 49 | 50 | 63 | 64 | 71 | 72 | 77 | 78 | 88 | 89 | 104 | 105 | 122 | 123 | 140 | 141 | 142 | 149 | 150 | 161 | 162 | 169 | 170 | 185 | 186 | 193 | 194 | 199 | 200 | 215 | 216 | 231 | 232 | 233 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2020 mtjsoft 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # ShapeView组件: 3 | 4 | 自定义带圆角背景的ShapeTextView、ShapeEditText、ShapeImageView、ShapeLinearLayout、ShapeRelativeLayout; 5 | 6 | 自定义根据状态切换背景色、字体色的ShapeCheckBox、ShapeRadioButton; 7 | 8 | UI设计图会经常出现不同圆角、不同背景色的按钮和输入框。 9 | 甚至还有很多会根据状态来切换字体颜色和背景颜色的按钮。 10 | 11 | 最常见的做法就是定义好需要的Shape后,在XML中设置属性使用,但是如果有很多个不同样式的时候,我们就需要定义很多个Shape,写起来很是麻烦的。 12 | 13 | 14 | # ShapeView组件效果 15 | 16 | ![效果](./shapeview.gif)![效果2](./shapeview.jpg) 17 | 18 | # 如何使用ShapeView组件 19 | 20 | # 1、在根目录 build.gradle 添加: 21 | 22 | ``` 23 | allprojects { 24 | repositories { 25 | ... 26 | maven { url 'https://jitpack.io' } 27 | } 28 | } 29 | ``` 30 | 31 | # 2、在app项目下的build.gradle中添加: 32 | 33 | ``` 34 | dependencies { 35 | implementation 'com.github.mtjsoft:ShapeView:v3.0.1' 36 | } 37 | ``` 38 | 39 | [![](https://jitpack.io/v/mtjsoft/ShapeView.svg)](https://jitpack.io/#mtjsoft/ShapeView) 40 | 41 | 42 | # 3、GridPager组件的版本及属性说明 43 | 44 | V3.0.1 45 | -------------------------- 46 | - 原有的全部属性名称添加前缀 sv_ 如: shape 改成 sv_shape 47 | - 防止自定义的属性和工程中的重复,升级此版本需谨慎 48 | 49 | V3.0.0 50 | -------------------------- 51 | - 修改成kotlin 52 | 53 | V2.1.0 54 | -------------------------- 55 | - 优化属性设置 56 | - 修复已知问题 57 | 58 | V2.0.2 59 | -------------------------- 60 | - 修改属性配置 61 | 62 | V2.0.1 63 | -------------------------- 64 | - 重构设置属性代码。统一由 setBuilder(CustomBuilder builder)方法设置,详见demo 65 | - 新增渐变色相关属性 66 | - 新增虚线属性 67 | 68 | 2.0.0 新增属性 | 属性说明 | 备注 69 | ------------- | ------------- | ------------- 70 | shape | shape类型。integer 0~3 分别对应 GradientDrawable.RECTANGLE, GradientDrawable.OVAL, GradientDrawable.LINE, GradientDrawable.RING | 2022-1-14 71 | startColor | 渐变开始颜色 72 | centerColor | 渐变中间颜色 73 | endColor | 渐变结束颜色 74 | startSelectColor | openSelector属性为true 时的选中渐变开始颜色 75 | centerSelectColor | openSelector属性为true 时的选中渐变中间颜色 76 | endSelectColor | openSelector属性为true 时的选中渐变结束颜色 77 | orientation | 渐变方向。integer 0~7 分别对应 GradientDrawable.Orientation枚举类中的值 78 | gradientType | 渐变类型。支持线性渐变、放射性渐变、扫描式渐变 integer 0~2 分别对应 GradientDrawable.LINEAR_GRADIENT, GradientDrawable.RADIAL_GRADIENT, GradientDrawable.SWEEP_GRADIENT 79 | gradientRadius | 渐变半径. 只有当渐变类型设置为 RADIAL_GRADIENT 时,半径才有效。format="float" 80 | dashWidth | 虚线边框宽度 81 | dashGap | 虚线边框间隙 82 | 83 | V1.2.0 84 | -------------------------- 85 | - 升AndroidX 86 | 87 | V1.1.0 88 | -------------------------- 89 | 90 | 1.1.0说明 | 备注 91 | ------------- | ------------- 92 | 新增了代码中动态设置的set方法 | 动态设置完属性后,setCustomBackground()展示 93 | 94 | V1.0.0 95 | -------------------------- 96 | 97 | 1.0.0 属性 | 属性说明 | 备注 98 | ------------- | ------------- | ------------- 99 | solidColor | 填充色 | 2019-10-10 12:22:12 100 | strokeColor | 边框色 101 | strokeWidth | 边框宽度 102 | radius | 圆角弧度(4个角的弧度) 103 | topLeftRadius | 单独设置左上角弧度 104 | topRightRadius | 单独设置右上角弧度 105 | bottomLeftRadius | 单独设置左下角弧度 106 | bottomRightRadius | 单独设置右下角弧度 107 | openSelector | 是否使用Selector选择器 | ShapeCheckBox、ShapeRadioButton有以下属性 108 | textNormalColor | 使用选择器时的默认字体色 109 | textSelectColor | 使用选择器时的选中字体色 110 | solidSelectColor | 使用选择器时的选中填充色 111 | strokeSelectColor | 使用选择器时的选中边框色 112 | 113 | 全部属性: 114 | -------------------------- 115 | ``` 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | ``` 188 | 189 | 190 | # 4、在需要使用的布局xml中添加ShapeView组件,根据需要设置相关属性 191 | 192 | ### ShapeTextView4个圆角、填充色 193 | ``` 194 | 205 | ``` 206 | ### ShapeTextView2个圆角、边框 207 | ``` 208 | 221 | ``` 222 | ### ShapeEditText输入框,圆角、边框 223 | ``` 224 | 235 | ``` 236 | ### ShapeCheckBox,根据选中状态切换背景色、字体色 237 | ``` 238 | 253 | ``` 254 | ### ShapeRadioButton示例 255 | ``` 256 | 261 | 262 | 277 | 278 | 293 | 294 | ``` 295 | ### 渐变颜色示例 296 | 297 | ``` 298 | 303 | 304 | 319 | 320 | 337 | 338 | 355 | 356 | ``` 357 | 358 | **添加我个人微信号交流,记得添加时备注一下哦** 359 | 360 | ![个人微信号](https://img-blog.csdnimg.cn/20190925134415595.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzI4Nzc5MDgz,size_16,color_FFFFFF,t_70) 361 | -------------------------------------------------------------------------------- /shapeview/src/main/res/values/attrs.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 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | --------------------------------------------------------------------------------