├── .gitignore ├── LICENSE ├── README.md ├── build.gradle ├── demo ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── angcyo │ │ └── dslitem │ │ └── demo │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── angcyo │ │ │ └── dslitem │ │ │ └── demo │ │ │ ├── MainActivity.kt │ │ │ └── dslitem │ │ │ └── SingleImageItem.kt │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable-xhdpi │ │ └── png.png │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ └── item_single_image.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── angcyo │ └── dslitem │ └── demo │ └── ExampleUnitTest.kt ├── dslitem ├── .gitignore ├── README.md ├── build.gradle ├── consumer-rules.pro ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── angcyo │ │ ├── drawable │ │ ├── DslAttrBadgeDrawable.kt │ │ └── DslBadgeDrawable.kt │ │ ├── extend │ │ ├── IToText.kt │ │ └── IToValue.kt │ │ ├── item │ │ ├── AnimEx.kt │ │ ├── DslBaseEditItem.kt │ │ ├── DslBaseInfoItem.kt │ │ ├── DslBaseLabelItem.kt │ │ ├── DslBottomButtonItem.kt │ │ ├── DslBottomItem.kt │ │ ├── DslButtonItem.kt │ │ ├── DslGridItem.kt │ │ ├── DslLabelEditItem.kt │ │ ├── DslLabelTextItem.kt │ │ ├── DslNestedRecyclerItem.kt │ │ ├── DslSwitchInfoItem.kt │ │ ├── DslTextInfoItem.kt │ │ ├── DslTextItem.kt │ │ ├── LibEx.kt │ │ ├── RAnimatorListener.kt │ │ ├── base │ │ │ ├── LibInitProvider.kt │ │ │ ├── RAnimationListener.kt │ │ │ └── SingleTextWatcher.kt │ │ └── style │ │ │ ├── ButtonStyleConfig.kt │ │ │ ├── EditStyleConfig.kt │ │ │ ├── IAutoInitItem.kt │ │ │ ├── IBadgeItem.kt │ │ │ ├── IBodyItem.kt │ │ │ ├── IButtonItem.kt │ │ │ ├── ICheckGroupItem.kt │ │ │ ├── ICheckItem.kt │ │ │ ├── IDesItem.kt │ │ │ ├── IEditItem.kt │ │ │ ├── ILabelItem.kt │ │ │ ├── INestedRecyclerItem.kt │ │ │ ├── ISwitchItem.kt │ │ │ ├── ITextInfoItem.kt │ │ │ ├── ITextItem.kt │ │ │ ├── ImageStyleConfig.kt │ │ │ ├── TextStyleConfig.kt │ │ │ └── ViewStyleConfig.kt │ │ └── widget │ │ ├── BadgeTextView.kt │ │ ├── CharLengthFilter.kt │ │ ├── DslGravity.kt │ │ ├── DslSelector.kt │ │ ├── IBadgeView.kt │ │ ├── ITouchDelegate.kt │ │ ├── ITouchHold.kt │ │ ├── SwitchButton.kt │ │ ├── TouchActionDelegate.kt │ │ ├── TouchListener.kt │ │ ├── ViewGroupEx.kt │ │ └── recycler │ │ ├── DslRecyclerView.kt │ │ ├── GridLayoutManagerWrap.kt │ │ ├── LinearLayoutManagerWrap.kt │ │ ├── RecyclerEx.kt │ │ ├── ScrollHelper.kt │ │ ├── ScrollPositionConfig.kt │ │ └── StaggeredGridLayoutManagerWrap.kt │ └── res │ ├── drawable-anydpi │ ├── lib_audio_cover_tip.xml │ ├── lib_audio_tip.xml │ ├── lib_check_checked.xml │ ├── lib_check_normal.xml │ ├── lib_icon_edit_tip.xml │ ├── lib_image_remove.xml │ ├── lib_image_tip.xml │ ├── lib_video_cover_tip.xml │ └── lib_video_tip.xml │ ├── drawable-v21 │ ├── lib_bg2_selector.xml │ ├── lib_bg_selector.xml │ └── lib_ripple_shape.xml │ ├── drawable │ ├── lib_bottom_line_selector.xml │ ├── lib_check_selector.xml │ ├── lib_dark_bottom_line_shape.xml │ ├── lib_duration_bg_shape.xml │ ├── lib_image_remove_circle_selector.xml │ ├── lib_remove_circle_shape.xml │ ├── lib_theme_bottom_line_shape.xml │ ├── lib_theme_circle_shape.xml │ └── lib_theme_press_circle_shape.xml │ ├── layout │ ├── dsl_bottom_button_item.xml │ ├── dsl_bottom_item.xml │ ├── dsl_button_item.xml │ ├── dsl_edit_item.xml │ ├── dsl_extent_switch_item.xml │ ├── dsl_extent_text_item.xml │ ├── dsl_grid_item.xml │ ├── dsl_info_item.xml │ ├── dsl_label_edit_item.xml │ ├── dsl_label_item.xml │ ├── dsl_label_text_item.xml │ ├── dsl_nested_recycler_item.xml │ ├── dsl_text_item.xml │ ├── layout_check.xml │ └── lib_tab_item_layout.xml │ └── values │ ├── attr_badge_view.xml │ ├── attr_dsl_recycler_view.xml │ ├── item_ids.xml │ ├── item_styles.xml │ └── switch_button_attrs.xml ├── dslitem2 ├── .gitignore ├── README.md ├── build.gradle ├── consumer-rules.pro ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── angcyo │ │ └── item2 │ │ ├── DslBannerItem.kt │ │ ├── ILoopAdapterItem.kt │ │ └── widget │ │ └── recycler │ │ ├── DrawableIndicator.kt │ │ ├── InvalidateProperty.kt │ │ ├── LoopRecyclerView.kt │ │ ├── LoopSnapHelper.kt │ │ └── RequestLayoutProperty.kt │ └── res │ ├── drawable │ ├── lib_indicator_focus.xml │ └── lib_indicator_normal.xml │ ├── layout │ └── dsl_banner_item.xml │ └── values │ ├── attr_border_view.xml │ ├── attr_drawable_indicator.xml │ ├── attr_loop_recycler_view.xml │ └── item2_values.xml ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── png └── item.png └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | .idea 16 | /UICore 17 | /UICoreEx 18 | /apk -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 angcyo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DslItem 2 | 基于`DslAdapter`的`DslAdapterItem`库, 挑选能用的, 把界面拼起来. 3 | 4 | 请先了解[DslAdapter](https://github.com/angcyo/DslAdapter). 5 | 6 | 针对[DslAdapter](https://github.com/angcyo/DslAdapter)库, 编写的一些常用的`DslAdapterItem`, 欢迎PR, 欢迎提出想要的`Item`建议. 7 | 8 | ![](https://img.shields.io/badge/License-MIT-EA660C) ![](https://img.shields.io/badge/Api-16+-FA0730) ![](https://img.shields.io/badge/AndroidX-yes-0A803C) 9 | ![](https://img.shields.io/badge/Kotlin-yes-B0F9F9) 10 | 11 | # 愿望 12 | 13 | 安卓界面的编写形式应该是`Item+Item+Item`,轻松+高度可复用: 14 | 15 | 如下形式: 16 | 17 | ```kotlin 18 | renderAdapter{ 19 | 头部Item() 20 | 轮播图Item() 21 | 列表Item() 22 | 列表Item() 23 | 列表Item() 24 | ... 25 | 尾部Item() 26 | 加载更多Item() 27 | } 28 | ``` 29 | 30 | 借助[DslAdapter](https://github.com/angcyo/DslAdapter)库,再结合本库,把界面`+`起来. 31 | 32 | 希望广大同仁 能与我共同维护此库 欢迎PR. 33 | 34 | 35 | ![](https://raw.githubusercontent.com/angcyo/DslItem/master/png/item.png) 36 | 37 | > 对应`Item`的属性和说明, 请依赖之后在源码内查看. 因为太丰富了, 源码看了就能懂. 38 | 39 | # 使用`JitPack`的方式, 引入库. 40 | 41 | ## 根目录中的 `build.gradle` 42 | 43 | ```kotlin 44 | allprojects { 45 | repositories { 46 | ... 47 | maven { url 'https://jitpack.io' } 48 | } 49 | } 50 | ``` 51 | 52 | ## APP目录中的 `build.gradle` 53 | 54 | ```kotlin 55 | dependencies { 56 | implementation 'com.github.angcyo:DslItem:1.0.9' 57 | } 58 | ``` 59 | 60 | --- 61 | **群内有`各(pian)种(ni)各(jin)样(qun)`的大佬,等你来撩.** 62 | 63 | # 联系作者 64 | 65 | [点此QQ对话](http://wpa.qq.com/msgrd?v=3&uin=664738095&site=qq&menu=yes) `该死的空格` [点此快速加群](https://shang.qq.com/wpa/qunwpa?idkey=cbcf9a42faf2fe730b51004d33ac70863617e6999fce7daf43231f3cf2997460) 66 | 67 | [开源地址](https://github.com/angcyo/DslAdapter) 68 | 69 | ![](https://gitee.com/angcyo/res/raw/master/code/all_in1.jpg) 70 | 71 | ![](https://gitee.com/angcyo/res/raw/master/code/all_in2.jpg) 72 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | ext.kotlin_version = '1.8.21' 5 | repositories { 6 | google() 7 | mavenCentral() 8 | } 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:7.4.2' 11 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 12 | 13 | // NOTE: Do not place your application dependencies here; they belong 14 | // in the individual module build.gradle files 15 | } 16 | } 17 | 18 | allprojects { 19 | repositories { 20 | google() 21 | mavenCentral() 22 | maven { url 'https://jitpack.io' } 23 | } 24 | } 25 | 26 | task clean(type: Delete) { 27 | delete rootProject.buildDir 28 | } 29 | -------------------------------------------------------------------------------- /demo/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /demo/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'kotlin-parcelize' 4 | apply plugin: 'kotlin-kapt' 5 | 6 | android { 7 | compileSdk Integer.parseInt(C_SDK) 8 | 9 | defaultConfig { 10 | applicationId "com.angcyo.dslitem.demo" 11 | minSdk Integer.parseInt(M_SDK) 12 | targetSdk Integer.parseInt(T_SDK) 13 | versionCode 1 14 | versionName "1.0" 15 | 16 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 17 | } 18 | 19 | buildTypes { 20 | release { 21 | minifyEnabled false 22 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 23 | } 24 | } 25 | namespace 'com.angcyo.dslitem.demo' 26 | 27 | } 28 | 29 | dependencies { 30 | implementation fileTree(dir: 'libs', include: ['*.jar']) 31 | implementation 'androidx.appcompat:appcompat:1.6.1' 32 | implementation 'androidx.core:core-ktx:1.10.0' 33 | implementation 'androidx.constraintlayout:constraintlayout:2.1.4' 34 | testImplementation 'junit:junit:4.13.2' 35 | androidTestImplementation 'androidx.test.ext:junit:1.1.5' 36 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' 37 | 38 | implementation project(":dslitem") 39 | implementation project(":dslitem2") 40 | 41 | def glide_version = "4.15.1" 42 | //https://muyangmin.github.io/glide-docs-cn/ 43 | //https://github.com/bumptech/glide 44 | implementation "com.github.bumptech.glide:glide:$glide_version" 45 | kapt "com.github.bumptech.glide:compiler:$glide_version" 46 | } 47 | -------------------------------------------------------------------------------- /demo/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 | -------------------------------------------------------------------------------- /demo/src/androidTest/java/com/angcyo/dslitem/demo/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.dslitem.demo 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("com.angcyo.dslitem.demo", appContext.packageName) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /demo/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 14 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /demo/src/main/java/com/angcyo/dslitem/demo/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.dslitem.demo 2 | 3 | import android.os.Bundle 4 | import androidx.appcompat.app.AppCompatActivity 5 | import androidx.recyclerview.widget.RecyclerView 6 | import com.angcyo.dsladapter.dpi 7 | import com.angcyo.dsladapter.initDslAdapter 8 | import com.angcyo.dslitem.demo.dslitem.SingleImageItem 9 | import com.angcyo.item.DslBaseEditItem 10 | import com.angcyo.item.DslBaseInfoItem 11 | import com.angcyo.item.DslBaseLabelItem 12 | import com.angcyo.item.DslButtonItem 13 | import com.angcyo.item.DslGridItem 14 | import com.angcyo.item.DslLabelEditItem 15 | import com.angcyo.item.DslLabelTextItem 16 | import com.angcyo.item.DslSwitchInfoItem 17 | import com.angcyo.item.DslTextInfoItem 18 | import com.angcyo.item.DslTextItem 19 | import com.angcyo.item.style.itemEditText 20 | import com.angcyo.item.style.renderNestedAdapter 21 | import com.angcyo.item2.DslBannerItem 22 | 23 | class MainActivity : AppCompatActivity() { 24 | 25 | override fun onCreate(savedInstanceState: Bundle?) { 26 | super.onCreate(savedInstanceState) 27 | setContentView(R.layout.activity_main) 28 | 29 | findViewById(R.id.recycler_view)?.initDslAdapter { 30 | render { 31 | DslBannerItem()() { 32 | itemHeight = 200 * dpi 33 | renderNestedAdapter { 34 | SingleImageItem()() { 35 | itemImageUri = 36 | "https://scpic.chinaz.net/files/default/imgs/2023-04-26/22c25fc6b5b32280.jpg" 37 | } 38 | SingleImageItem()() { 39 | itemImageUri = 40 | "https://scpic.chinaz.net/files/default/imgs/2023-04-26/927afbe5af4fec22.jpg" 41 | } 42 | } 43 | } 44 | 45 | DslBaseEditItem()() { 46 | itemEditText = this::class.java.simpleName 47 | editItemConfig._lastEditSelectionStart = itemEditText?.length ?: -1 48 | configEditTextStyle { 49 | hint = "请输入..." 50 | } 51 | } 52 | 53 | DslBaseInfoItem()() { 54 | itemInfoText = this::class.java.simpleName 55 | } 56 | 57 | DslBaseLabelItem()() { 58 | itemLabelText = this::class.java.simpleName 59 | } 60 | 61 | DslButtonItem()() { 62 | itemButtonText = this::class.java.simpleName 63 | } 64 | 65 | DslButtonItem()() { 66 | itemButtonText = this::class.java.simpleName 67 | configButtonStyle { 68 | themeStyle() 69 | } 70 | } 71 | DslButtonItem()() { 72 | itemButtonText = this::class.java.simpleName 73 | configButtonStyle { 74 | fillStyle() 75 | } 76 | } 77 | DslButtonItem()() { 78 | itemButtonText = this::class.java.simpleName 79 | configButtonStyle { 80 | solidStyle() 81 | } 82 | } 83 | 84 | DslGridItem()() { 85 | itemText = this::class.java.simpleName 86 | itemIcon = R.drawable.png 87 | } 88 | 89 | DslLabelEditItem()() { 90 | itemLabelText = "Label" 91 | itemEditText = this::class.java.simpleName 92 | editItemConfig._lastEditSelectionStart = itemEditText?.length ?: -1 93 | 94 | configEditTextStyle { 95 | hint = "请输入..." 96 | } 97 | } 98 | 99 | DslLabelTextItem()() { 100 | itemLabelText = "Label" 101 | itemText = this::class.java.simpleName 102 | } 103 | 104 | DslSwitchInfoItem()() { 105 | itemInfoText = this::class.java.simpleName 106 | } 107 | 108 | DslTextInfoItem()() { 109 | itemInfoText = this::class.java.simpleName 110 | itemDarkText = "DarkText" 111 | } 112 | 113 | DslTextItem()() { 114 | itemText = this::class.java.simpleName 115 | } 116 | } 117 | } 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /demo/src/main/java/com/angcyo/dslitem/demo/dslitem/SingleImageItem.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.dslitem.demo.dslitem 2 | 3 | import com.angcyo.dsladapter.DslAdapterItem 4 | import com.angcyo.dsladapter.DslViewHolder 5 | import com.angcyo.dslitem.demo.R 6 | import com.bumptech.glide.Glide 7 | 8 | /** 9 | * Email:angcyo@126.com 10 | * @author angcyo 11 | * @date 2023/04/28 12 | */ 13 | class SingleImageItem : DslAdapterItem() { 14 | 15 | var itemImageUri: String? = null 16 | 17 | init { 18 | itemLayoutId = R.layout.item_single_image 19 | } 20 | 21 | override fun onItemBind( 22 | itemHolder: DslViewHolder, 23 | itemPosition: Int, 24 | adapterItem: DslAdapterItem, 25 | payloads: List 26 | ) { 27 | super.onItemBind(itemHolder, itemPosition, adapterItem, payloads) 28 | 29 | itemHolder.img(R.id.lib_image_view)?.let { 30 | Glide.with(itemHolder.itemView).load(itemImageUri).centerCrop().into(it) 31 | } 32 | } 33 | 34 | } -------------------------------------------------------------------------------- /demo/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /demo/src/main/res/drawable-xhdpi/png.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angcyo/DslItem/92c5a7c665636c7af4c1f497c41657653ae80326/demo/src/main/res/drawable-xhdpi/png.png -------------------------------------------------------------------------------- /demo/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 | -------------------------------------------------------------------------------- /demo/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /demo/src/main/res/layout/item_single_image.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 11 | 12 | -------------------------------------------------------------------------------- /demo/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /demo/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /demo/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angcyo/DslItem/92c5a7c665636c7af4c1f497c41657653ae80326/demo/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angcyo/DslItem/92c5a7c665636c7af4c1f497c41657653ae80326/demo/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /demo/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angcyo/DslItem/92c5a7c665636c7af4c1f497c41657653ae80326/demo/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angcyo/DslItem/92c5a7c665636c7af4c1f497c41657653ae80326/demo/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /demo/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angcyo/DslItem/92c5a7c665636c7af4c1f497c41657653ae80326/demo/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angcyo/DslItem/92c5a7c665636c7af4c1f497c41657653ae80326/demo/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /demo/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angcyo/DslItem/92c5a7c665636c7af4c1f497c41657653ae80326/demo/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angcyo/DslItem/92c5a7c665636c7af4c1f497c41657653ae80326/demo/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /demo/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angcyo/DslItem/92c5a7c665636c7af4c1f497c41657653ae80326/demo/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angcyo/DslItem/92c5a7c665636c7af4c1f497c41657653ae80326/demo/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /demo/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #6200EE 4 | #3700B3 5 | #03DAC5 6 | 7 | -------------------------------------------------------------------------------- /demo/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | DslItem 3 | 4 | -------------------------------------------------------------------------------- /demo/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /demo/src/test/java/com/angcyo/dslitem/demo/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.dslitem.demo 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /dslitem/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /dslitem/README.md: -------------------------------------------------------------------------------- 1 | # dslitem 2 | 2020-01-01 3 | 4 | 常用 `DslItem`, 如果此库丰富了, 那么UI, 就是`乐高`拼出来的. 5 | 6 | ```kotlin 7 | renderDslAdapter{ 8 | dslItem1() 9 | dslItem2() 10 | dslItem3() 11 | ... 12 | dslItemX() 13 | dslItemY() 14 | dslItemZ() 15 | } 16 | ``` -------------------------------------------------------------------------------- /dslitem/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'kotlin-android' 3 | 4 | android { 5 | compileSdk Integer.parseInt(C_SDK) 6 | 7 | defaultConfig { 8 | vectorDrawables.useSupportLibrary = true 9 | 10 | minSdk Integer.parseInt(M_SDK) 11 | targetSdk Integer.parseInt(T_SDK) 12 | 13 | consumerProguardFiles 'consumer-rules.pro' 14 | } 15 | namespace 'com.angcyo.item' 16 | } 17 | 18 | dependencies { 19 | //https://mvnrepository.com/artifact/androidx.appcompat/appcompat 20 | implementation 'androidx.appcompat:appcompat:1.6.1' 21 | 22 | //https://mvnrepository.com/artifact/androidx.constraintlayout/constraintlayout 23 | api 'androidx.constraintlayout:constraintlayout:2.1.4' 24 | 25 | //https://mvnrepository.com/artifact/androidx.recyclerview/recyclerview 26 | api 'androidx.recyclerview:recyclerview:1.3.0' 27 | 28 | //https://github.com/angcyo/DslAdapter 29 | api 'com.github.angcyo:DslAdapter:6.0.1' 30 | 31 | //https://github.com/angcyo/DslSpan 32 | api 'com.github.angcyo:DslSpan:1.1.0' 33 | 34 | //https://github.com/angcyo/DslButton 35 | api 'com.github.angcyo:DslButton:1.3.0' 36 | } 37 | -------------------------------------------------------------------------------- /dslitem/consumer-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angcyo/DslItem/92c5a7c665636c7af4c1f497c41657653ae80326/dslitem/consumer-rules.pro -------------------------------------------------------------------------------- /dslitem/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 | -------------------------------------------------------------------------------- /dslitem/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/drawable/DslAttrBadgeDrawable.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.drawable 2 | 3 | import android.content.Context 4 | import android.graphics.Canvas 5 | import android.graphics.Color 6 | import android.util.AttributeSet 7 | import android.view.Gravity 8 | import com.angcyo.dpi 9 | import com.angcyo.item.R 10 | 11 | /** 12 | * 角标 13 | * Email:angcyo@126.com 14 | * @author angcyo 15 | * @date 2019/12/13 16 | * Copyright (c) 2019 ShenZhen O&M Cloud Co., Ltd. All rights reserved. 17 | */ 18 | open class DslAttrBadgeDrawable : DslBadgeDrawable() { 19 | 20 | /**是否要绘制角标*/ 21 | var drawBadge: Boolean = true 22 | 23 | override fun initAttribute(context: Context, attributeSet: AttributeSet?) { 24 | val typedArray = 25 | context.obtainStyledAttributes(attributeSet, R.styleable.DslAttrBadgeDrawable) 26 | drawBadge = typedArray.getBoolean(R.styleable.DslAttrBadgeDrawable_r_draw_badge, drawBadge) 27 | gradientSolidColor = 28 | typedArray.getColor( 29 | R.styleable.DslAttrBadgeDrawable_r_badge_solid_color, 30 | Color.RED 31 | ) 32 | badgeTextColor = 33 | typedArray.getColor( 34 | R.styleable.DslAttrBadgeDrawable_r_badge_text_color, 35 | Color.WHITE 36 | ) 37 | badgeGravity = typedArray.getInt( 38 | R.styleable.DslAttrBadgeDrawable_r_badge_gravity, 39 | Gravity.TOP or Gravity.RIGHT 40 | ) 41 | badgeOffsetX = typedArray.getDimensionPixelOffset( 42 | R.styleable.DslAttrBadgeDrawable_r_badge_offset_x, 43 | badgeOffsetX 44 | ) 45 | badgeCircleRadius = typedArray.getDimensionPixelOffset( 46 | R.styleable.DslAttrBadgeDrawable_r_badge_circle_radius, 47 | 4 * dpi 48 | ) 49 | val badgeRadius = typedArray.getDimensionPixelOffset( 50 | R.styleable.DslAttrBadgeDrawable_r_badge_radius, 51 | 10 * dpi 52 | ) 53 | cornerRadius(badgeRadius.toFloat()) 54 | badgeOffsetY = typedArray.getDimensionPixelOffset( 55 | R.styleable.DslAttrBadgeDrawable_r_badge_offset_y, 56 | badgeOffsetY 57 | ) 58 | badgePaddingLeft = typedArray.getDimensionPixelOffset( 59 | R.styleable.DslAttrBadgeDrawable_r_badge_padding_left, 60 | 4 * dpi 61 | ) 62 | badgePaddingRight = typedArray.getDimensionPixelOffset( 63 | R.styleable.DslAttrBadgeDrawable_r_badge_padding_right, 64 | 4 * dpi 65 | ) 66 | badgePaddingTop = typedArray.getDimensionPixelOffset( 67 | R.styleable.DslAttrBadgeDrawable_r_badge_padding_top, 68 | 0 69 | ) 70 | badgePaddingBottom = typedArray.getDimensionPixelOffset( 71 | R.styleable.DslAttrBadgeDrawable_r_badge_padding_bottom, 72 | 0 73 | ) 74 | //脚本文本内容 75 | badgeText = typedArray.getString(R.styleable.DslAttrBadgeDrawable_r_badge_text) 76 | badgeTextSize = typedArray.getDimensionPixelOffset( 77 | R.styleable.DslAttrBadgeDrawable_r_badge_text_size, 78 | 12 * dpi 79 | ).toFloat() 80 | 81 | //自定义的背景 82 | originDrawable = 83 | typedArray.getDrawable(R.styleable.DslAttrBadgeDrawable_r_badge_bg_drawable) 84 | 85 | badgeTextOffsetX = typedArray.getDimensionPixelOffset( 86 | R.styleable.DslAttrBadgeDrawable_r_badge_text_offset_x, 87 | badgeTextOffsetX 88 | ) 89 | 90 | badgeTextOffsetY = typedArray.getDimensionPixelOffset( 91 | R.styleable.DslAttrBadgeDrawable_r_badge_text_offset_y, 92 | badgeTextOffsetY 93 | ) 94 | 95 | badgeCircleOffsetX = typedArray.getDimensionPixelOffset( 96 | R.styleable.DslAttrBadgeDrawable_r_badge_circle_offset_x, 97 | badgeTextOffsetX 98 | ) 99 | 100 | badgeCircleOffsetY = typedArray.getDimensionPixelOffset( 101 | R.styleable.DslAttrBadgeDrawable_r_badge_circle_offset_y, 102 | badgeTextOffsetY 103 | ) 104 | typedArray.recycle() 105 | super.initAttribute(context, attributeSet) 106 | } 107 | 108 | override fun draw(canvas: Canvas) { 109 | if (drawBadge) { 110 | super.draw(canvas) 111 | } 112 | } 113 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/extend/IToText.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.extend 2 | 3 | /** 4 | * 5 | * Email:angcyo@126.com 6 | * @author angcyo 7 | * @date 2021/07/20 8 | * Copyright (c) 2020 ShenZhen Wayto Ltd. All rights reserved. 9 | */ 10 | interface IToText { 11 | fun toText(): CharSequence? 12 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/extend/IToValue.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.extend 2 | 3 | /** 4 | * 5 | * Email:angcyo@126.com 6 | * @author angcyo 7 | * @date 2021/07/20 8 | * Copyright (c) 2020 ShenZhen Wayto Ltd. All rights reserved. 9 | */ 10 | interface IToValue { 11 | fun toValue(): Any? 12 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/item/DslBaseEditItem.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item 2 | 3 | import com.angcyo.dsladapter.DslAdapterItem 4 | import com.angcyo.dsladapter.DslViewHolder 5 | import com.angcyo.item.style.EditItemConfig 6 | import com.angcyo.item.style.IEditItem 7 | 8 | /** 9 | * 输入框item基类 10 | * Email:angcyo@126.com 11 | * @author angcyo 12 | * @date 2020/03/23 13 | * Copyright (c) 2019 ShenZhen O&M Cloud Co., Ltd. All rights reserved. 14 | */ 15 | 16 | open class DslBaseEditItem : DslBaseLabelItem(), IEditItem { 17 | 18 | companion object { 19 | /**允许默认输入的字符长度*/ 20 | var DEFAULT_MAX_INPUT_LENGTH = 30 21 | 22 | /**输入框文本改变节流时长, 毫秒*/ 23 | var DEFAULT_INPUT_SHAKE_DELAY = 300L 24 | } 25 | 26 | override var editItemConfig: EditItemConfig = EditItemConfig() 27 | 28 | init { 29 | itemLayoutId = R.layout.dsl_edit_item 30 | } 31 | 32 | override fun onItemBind( 33 | itemHolder: DslViewHolder, 34 | itemPosition: Int, 35 | adapterItem: DslAdapterItem 36 | ) { 37 | super.onItemBind(itemHolder, itemPosition, adapterItem) 38 | } 39 | 40 | override fun onItemViewDetachedToWindow(itemHolder: DslViewHolder, itemPosition: Int) { 41 | super.onItemViewDetachedToWindow(itemHolder, itemPosition) 42 | //itemHolder.ev(R.id.lib_edit_view)?.clearListeners() 43 | } 44 | 45 | override fun onItemViewRecycled(itemHolder: DslViewHolder, itemPosition: Int) { 46 | super.onItemViewRecycled(itemHolder, itemPosition) 47 | itemHolder.ev(editItemConfig.itemEditTextViewId)?.clearListeners() 48 | } 49 | 50 | override fun onItemChangeListener(item: DslAdapterItem) { 51 | //super.onItemChangeListener(item) 52 | updateItemOnHaveDepend() 53 | } 54 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/item/DslBaseInfoItem.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item 2 | 3 | import androidx.annotation.DrawableRes 4 | import androidx.annotation.LayoutRes 5 | import com.angcyo.dsladapter.DslAdapterItem 6 | import com.angcyo.dsladapter.DslViewHolder 7 | import com.angcyo.widget.span.colorFilter 8 | import com.angcyo.widget.span.undefined_res 9 | 10 | /** 11 | * 横条文本信息基类item, 右边布局支持扩展自定义 12 | * Email:angcyo@126.com 13 | * @author angcyo 14 | * @date 2019/08/09 15 | * Copyright (c) 2019 ShenZhen O&M Cloud Co., Ltd. All rights reserved. 16 | */ 17 | open class DslBaseInfoItem : DslAdapterItem() { 18 | 19 | /**条目文本*/ 20 | var itemInfoText: CharSequence? = null 21 | 22 | @DrawableRes 23 | var itemInfoIcon: Int = undefined_res 24 | 25 | var itemInfoIconColor: Int = undefined_res 26 | 27 | /**扩展布局信息*/ 28 | @LayoutRes 29 | var itemExtendLayoutId: Int = undefined_res 30 | 31 | init { 32 | itemLayoutId = R.layout.dsl_info_item 33 | } 34 | 35 | override fun onItemBind( 36 | itemHolder: DslViewHolder, 37 | itemPosition: Int, 38 | adapterItem: DslAdapterItem, 39 | payloads: List 40 | ) { 41 | super.onItemBind(itemHolder, itemPosition, adapterItem, payloads) 42 | 43 | //文本信息 44 | itemHolder.tv(R.id.lib_text_view)?.apply { 45 | text = itemInfoText 46 | 47 | if (itemInfoIconColor == undefined_res) { 48 | setLeftIco(itemInfoIcon) 49 | } else { 50 | setLeftIco(loadDrawable(itemInfoIcon).colorFilter(itemInfoIconColor)) 51 | } 52 | } 53 | 54 | //扩展布局 55 | if (itemExtendLayoutId != undefined_res) { 56 | var inflateLayoutId = undefined_res //已经inflate的布局id 57 | itemHolder.group(R.id.wrap_layout)?.apply { 58 | if (childCount > 0) { 59 | inflateLayoutId = (getChildAt(0).getTag(R.id.tag) as? Int) ?: undefined_res 60 | } 61 | 62 | if (itemExtendLayoutId != inflateLayoutId) { 63 | //两次inflate的布局不同 64 | itemHolder.clear() 65 | inflate(itemExtendLayoutId, true) 66 | val view = getChildAt(0) 67 | view.setTag(R.id.tag, itemExtendLayoutId) 68 | } 69 | } 70 | } else { 71 | itemHolder.group(R.id.wrap_layout)?.removeAllViews() 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/item/DslBaseLabelItem.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item 2 | 3 | import android.content.res.ColorStateList 4 | import android.graphics.drawable.Drawable 5 | import android.util.TypedValue 6 | import android.view.Gravity 7 | import android.widget.TextView 8 | import com.angcyo.dsladapter.DslAdapterItem 9 | import com.angcyo.dsladapter.DslViewHolder 10 | import com.angcyo.dsladapter.UndefinedDrawable 11 | import com.angcyo.dsladapter.setBgDrawable 12 | import com.angcyo.widget.span.undefined_color 13 | import com.angcyo.widget.span.undefined_float 14 | 15 | 16 | /** 17 | * 带有Label的item 18 | * Email:angcyo@126.com 19 | * @author angcyo 20 | * @date 2020/03/23 21 | * Copyright (c) 2019 ShenZhen O&M Cloud Co., Ltd. All rights reserved. 22 | */ 23 | 24 | open class DslBaseLabelItem : DslAdapterItem() { 25 | 26 | /**左边的Label文本*/ 27 | var itemLabelText: CharSequence? = null 28 | set(value) { 29 | field = value 30 | itemLabelTextStyle.text = value 31 | } 32 | 33 | /**统一样式配置*/ 34 | var itemLabelTextStyle = TextStyleConfig() 35 | 36 | init { 37 | itemLayoutId = R.layout.dsl_label_item 38 | } 39 | 40 | override fun onItemBind( 41 | itemHolder: DslViewHolder, 42 | itemPosition: Int, 43 | adapterItem: DslAdapterItem, 44 | payloads: List 45 | ) { 46 | super.onItemBind(itemHolder, itemPosition, adapterItem, payloads) 47 | 48 | itemHolder.gone(R.id.lib_label_view, itemLabelText == null) 49 | 50 | itemHolder.tv(R.id.lib_label_view)?.apply { 51 | itemLabelTextStyle.updateStyle(this) 52 | } 53 | } 54 | 55 | open fun configLabelTextStyle(action: TextStyleConfig.() -> Unit) { 56 | itemLabelTextStyle.action() 57 | } 58 | } 59 | 60 | /**文本样式配置*/ 61 | open class TextStyleConfig { 62 | var text: CharSequence? = null 63 | var hint: CharSequence? = null 64 | var textBold: Boolean = false 65 | var textColor: Int = undefined_color 66 | var textColors: ColorStateList? = null 67 | var textSize: Float = undefined_float 68 | var textGravity: Int = Gravity.LEFT or Gravity.CENTER_VERTICAL 69 | var backgroundDrawable: Drawable? = UndefinedDrawable() 70 | 71 | /**生效*/ 72 | open fun updateStyle(textView: TextView) { 73 | with(textView) { 74 | if (backgroundDrawable is UndefinedDrawable) { 75 | backgroundDrawable = background 76 | } 77 | setBgDrawable(backgroundDrawable) 78 | 79 | text = this@TextStyleConfig.text 80 | hint = this@TextStyleConfig.hint 81 | 82 | gravity = textGravity 83 | 84 | setBoldText(textBold) 85 | 86 | //颜色, 防止复用. 所以在未指定的情况下, 要获取默认的颜色. 87 | val colors = when { 88 | this@TextStyleConfig.textColors != null -> { 89 | this@TextStyleConfig.textColors 90 | } 91 | textColor != undefined_color -> { 92 | ColorStateList.valueOf(textColor) 93 | } 94 | else -> { 95 | textColors 96 | } 97 | } 98 | if (colors != this@TextStyleConfig.textColors) { 99 | this@TextStyleConfig.textColors = colors 100 | } 101 | setTextColor(colors) 102 | 103 | //字体大小同理. 104 | val size = if (this@TextStyleConfig.textSize != undefined_float) { 105 | this@TextStyleConfig.textSize 106 | } else { 107 | textSize 108 | } 109 | this@TextStyleConfig.textSize = size 110 | setTextSize(TypedValue.COMPLEX_UNIT_PX, size) 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/item/DslBottomButtonItem.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item 2 | 3 | /** 4 | * 显示的[RecyclerView]底部的item 5 | * Email:angcyo@126.com 6 | * @author angcyo 7 | * @date 2020/03/26 8 | * Copyright (c) 2019 ShenZhen O&M Cloud Co., Ltd. All rights reserved. 9 | */ 10 | open class DslBottomButtonItem : DslButtonItem() { 11 | init { 12 | itemLayoutId = R.layout.dsl_bottom_button_item 13 | itemButtonStyle.themeStyle() 14 | } 15 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/item/DslBottomItem.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item 2 | 3 | import com.angcyo.dsladapter.DslAdapterItem 4 | import com.angcyo.dsladapter.DslViewHolder 5 | 6 | /** 7 | * 在[RecyclerView]底部显示的文本item 8 | * Email:angcyo@126.com 9 | * @author angcyo 10 | * @date 2020/02/29 11 | */ 12 | open class DslBottomItem : DslAdapterItem() { 13 | 14 | /**显示的文本*/ 15 | var itemText: CharSequence? = null 16 | set(value) { 17 | field = value 18 | itemTextStyle.text = value 19 | } 20 | 21 | /**统一样式配置*/ 22 | var itemTextStyle = TextStyleConfig() 23 | 24 | init { 25 | itemLayoutId = R.layout.dsl_bottom_item 26 | } 27 | 28 | override fun onItemBind( 29 | itemHolder: DslViewHolder, 30 | itemPosition: Int, 31 | adapterItem: DslAdapterItem, 32 | payloads: List 33 | ) { 34 | super.onItemBind(itemHolder, itemPosition, adapterItem, payloads) 35 | 36 | itemHolder.tv(R.id.lib_text_view)?.apply { 37 | itemTextStyle.updateStyle(this) 38 | } 39 | } 40 | 41 | override fun _initItemSize(itemHolder: DslViewHolder) { 42 | //super._initItemSize(itemHolder) 43 | } 44 | 45 | open fun configTextStyle(action: TextStyleConfig.() -> Unit) { 46 | itemTextStyle.action() 47 | } 48 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/item/DslButtonItem.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item 2 | 3 | import android.graphics.Color 4 | import android.view.Gravity 5 | import android.widget.TextView 6 | import com.angcyo.dsladapter.DslAdapterItem 7 | import com.angcyo.dsladapter.DslViewHolder 8 | import com.angcyo.widget.DslButton 9 | import com.angcyo.widget.colorState 10 | import com.angcyo.widget.span.dpi 11 | import com.angcyo.widget.span.undefined_float 12 | 13 | 14 | /** 15 | * 带有[DslButton]的item 16 | * Email:angcyo@126.com 17 | * @author angcyo 18 | * @date 2020/03/26 19 | * Copyright (c) 2019 ShenZhen O&M Cloud Co., Ltd. All rights reserved. 20 | */ 21 | open class DslButtonItem : DslAdapterItem() { 22 | 23 | /**按钮显示的文本*/ 24 | var itemButtonText: CharSequence? = null 25 | set(value) { 26 | field = value 27 | itemButtonStyle.text = value 28 | } 29 | 30 | /**按钮样式配置项*/ 31 | var itemButtonStyle = ButtonStyleConfig().apply { 32 | textGravity = Gravity.CENTER 33 | } 34 | 35 | /**按钮配置回调*/ 36 | var itemButtonConfig: (DslButton) -> Unit = { 37 | 38 | } 39 | 40 | init { 41 | itemLayoutId = R.layout.dsl_button_item 42 | } 43 | 44 | override fun onItemBind( 45 | itemHolder: DslViewHolder, 46 | itemPosition: Int, 47 | adapterItem: DslAdapterItem, 48 | payloads: List 49 | ) { 50 | super.onItemBind(itemHolder, itemPosition, adapterItem, payloads) 51 | itemHolder.itemView.isClickable = false 52 | 53 | itemHolder.v(R.id.lib_button)?.apply { 54 | itemButtonStyle.updateStyle(this) 55 | itemButtonConfig(this) 56 | 57 | setOnClickListener(_clickListener) 58 | } 59 | } 60 | 61 | open fun configButtonStyle(action: ButtonStyleConfig.() -> Unit) { 62 | itemButtonStyle.action() 63 | } 64 | } 65 | 66 | open class ButtonStyleConfig : TextStyleConfig() { 67 | 68 | companion object { 69 | //主题渐变样式 70 | val BUTTON_STYLE_THEME = 1 71 | 72 | //填充颜色的样式 73 | val BUTTON_STYLE_SOLID = 2 74 | 75 | //边框->主题渐变 76 | val BUTTON_STYLE_FILL = 3 77 | } 78 | 79 | /**特定样式*/ 80 | var style: Int = BUTTON_STYLE_THEME 81 | 82 | /**样式[BUTTON_STYLE_THEME] [BUTTON_STYLE_FILL]时, 渐变的颜色*/ 83 | var styleThemeColors = intArrayOf( 84 | _color(R.color.colorPrimary), 85 | _color(R.color.colorPrimaryDark) 86 | ) 87 | 88 | /**样式[BUTTON_STYLE_THEME] [BUTTON_STYLE_FILL]时, 文本的颜色*/ 89 | var styleThemeTextColor = Color.WHITE 90 | 91 | /**样式[BUTTON_STYLE_SOLID]时, solid的颜色*/ 92 | var styleSolidSolidColor = Color.WHITE 93 | 94 | /**样式[BUTTON_STYLE_FILL]时, solid的颜色*/ 95 | var styleFillSolidColor = Color.TRANSPARENT 96 | 97 | /**样式[BUTTON_STYLE_SOLID] [BUTTON_STYLE_FILL]时, 文本的颜色*/ 98 | var styleSolidTextColor = _color(R.color.text_general_color) 99 | set(value) { 100 | field = value 101 | textColor = value 102 | } 103 | 104 | /**[BUTTON_STYLE_FILL]*/ 105 | var styleFillStrokeWidth = 2 * dpi 106 | 107 | /**[BUTTON_STYLE_FILL]*/ 108 | var styleFillStrokeColor = _color(R.color.colorPrimary) 109 | 110 | var buttonRadius: Float = undefined_float 111 | 112 | init { 113 | themeStyle() 114 | } 115 | 116 | override fun updateStyle(textView: TextView) { 117 | super.updateStyle(textView) 118 | 119 | if (textView is DslButton) { 120 | 121 | //不支持不同圆角大小的样式 122 | if (buttonRadius == undefined_float) { 123 | buttonRadius = textView.normalRadii.first() 124 | } 125 | textView.setButtonRadius(buttonRadius) 126 | 127 | when (style) { 128 | BUTTON_STYLE_THEME -> { 129 | textView.enableTextStyle = true 130 | textView.setButtonGradientColors(styleThemeColors) 131 | textView.setButtonTextColor(textColor) 132 | textView.setButtonStrokeWidth(0) 133 | } 134 | BUTTON_STYLE_SOLID -> { 135 | textView.enableTextStyle = true 136 | textView.setButtonGradientColors(null) 137 | textView.setButtonSolidColor(styleSolidSolidColor) 138 | textView.setButtonTextColor(textColor) 139 | textView.setButtonStrokeWidth(0) 140 | } 141 | BUTTON_STYLE_FILL -> { 142 | textView.enableTextStyle = false 143 | textView.setButtonGradientColors(null) 144 | textView.setButtonSolidColor(styleFillSolidColor) 145 | textView.setButtonStrokeWidth(styleFillStrokeWidth) 146 | textView.setButtonStrokeColor(styleFillStrokeColor) 147 | 148 | textView.pressStrokeWidth = 0 149 | textView.pressGradientColors = styleThemeColors 150 | } 151 | } 152 | 153 | textView.updateDrawable() 154 | } 155 | } 156 | 157 | /**使用主题样式, 颜色渐变*/ 158 | fun themeStyle() { 159 | style = BUTTON_STYLE_THEME 160 | textColor = styleThemeTextColor 161 | } 162 | 163 | /**使用渐变样式*/ 164 | fun gradientStyle(gradientStartColor: Int, gradientEndColor: Int = gradientStartColor) { 165 | themeStyle() 166 | styleThemeColors = intArrayOf(gradientStartColor, gradientEndColor) 167 | } 168 | 169 | /**填充颜色的样式*/ 170 | fun solidStyle() { 171 | style = BUTTON_STYLE_SOLID 172 | textColor = styleSolidTextColor 173 | } 174 | 175 | /**边框 填充样式*/ 176 | fun fillStyle() { 177 | style = BUTTON_STYLE_FILL 178 | textColors = colorState( 179 | DslButton.ATTR_PRESSED to styleThemeTextColor, 180 | DslButton.ATTR_NORMAL to styleSolidTextColor 181 | ) 182 | } 183 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/item/DslGridItem.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item 2 | 3 | import android.graphics.drawable.Drawable 4 | import android.view.ViewGroup 5 | import com.angcyo.dsladapter.* 6 | 7 | /** 8 | * 普通的网格item 9 | * Email:angcyo@126.com 10 | * @author angcyo 11 | * @date 2020/03/22 12 | */ 13 | open class DslGridItem : DslAdapterItem() { 14 | 15 | /**显示的文本*/ 16 | var itemText: CharSequence? = null 17 | 18 | /**图标*/ 19 | var itemIcon: Int = -1 20 | 21 | /**图标背景*/ 22 | var itemImageBg: Drawable? = null 23 | var itemImagePadding: Int = 12 * dpi 24 | var itemTextPadding: Int = 8 * dpi 25 | 26 | /**图标是1:1的大小*/ 27 | var itemIconSize: Int = ViewGroup.LayoutParams.WRAP_CONTENT 28 | 29 | /**开启智能分割线, 只有在非边界的item才绘制*/ 30 | var itemGridInsert = -1 31 | 32 | init { 33 | itemLayoutId = R.layout.dsl_grid_item 34 | } 35 | 36 | override fun onItemBind( 37 | itemHolder: DslViewHolder, 38 | itemPosition: Int, 39 | adapterItem: DslAdapterItem, 40 | payloads: List 41 | ) { 42 | super.onItemBind(itemHolder, itemPosition, adapterItem, payloads) 43 | 44 | //文本 45 | itemHolder.tv(R.id.lib_text_view)?.apply { 46 | text = itemText 47 | padding(itemTextPadding) 48 | } 49 | 50 | //图标 51 | itemHolder.img(R.id.lib_image_view)?.apply { 52 | padding(itemImagePadding) 53 | 54 | setImageDrawable(loadDrawable(itemIcon)) 55 | setWidth(itemIconSize) 56 | 57 | setBgDrawable(itemImageBg) 58 | } 59 | 60 | //智能分割线 61 | if (itemGridInsert > 0) { 62 | itemGroupParams.apply { 63 | //itemLeftInsert = itemGridInsert 64 | //itemTopInsert = itemGridInsert 65 | itemRightInsert = itemGridInsert 66 | itemBottomInsert = itemGridInsert 67 | if (isEdgeLeft()) { 68 | itemLeftInsert = 0 69 | } 70 | if (isEdgeTop()) { 71 | itemTopInsert = 0 72 | } 73 | if (isEdgeRight()) { 74 | itemRightInsert = 0 75 | } 76 | if (isEdgeBottom()) { 77 | itemBottomInsert = 0 78 | } 79 | } 80 | } 81 | } 82 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/item/DslLabelEditItem.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item 2 | 3 | import android.graphics.drawable.Drawable 4 | import android.view.View 5 | import com.angcyo.dsladapter.DslAdapterItem 6 | import com.angcyo.dsladapter.DslViewHolder 7 | 8 | /** 9 | * 带有label的单行输入item 10 | * Email:angcyo@126.com 11 | * @author angcyo 12 | * @date 2020/03/23 13 | * Copyright (c) 2019 ShenZhen O&M Cloud Co., Ltd. All rights reserved. 14 | */ 15 | open class DslLabelEditItem : DslBaseEditItem() { 16 | 17 | /**编辑提示按钮, 负数会返回null对象*/ 18 | var itemEditTipIcon: Int = R.drawable.lib_icon_edit_tip 19 | 20 | /**优先于属性[itemEditTipIcon]*/ 21 | var itemEditTipDrawable: Drawable? = null 22 | 23 | /**右边图标点击事件, 如果设置回调. 会影响默认的事件处理*/ 24 | var itemRightIcoClick: ((DslViewHolder, View) -> Unit)? = null 25 | 26 | /**右边的文本*/ 27 | var itemRightText: CharSequence? = null 28 | set(value) { 29 | field = value 30 | itemRightTextStyle.text = value 31 | } 32 | 33 | /**统一样式配置*/ 34 | var itemRightTextStyle = TextStyleConfig() 35 | 36 | init { 37 | itemLayoutId = R.layout.dsl_label_edit_item 38 | } 39 | 40 | override fun onItemBind( 41 | itemHolder: DslViewHolder, 42 | itemPosition: Int, 43 | adapterItem: DslAdapterItem, 44 | payloads: List 45 | ) { 46 | super.onItemBind(itemHolder, itemPosition, adapterItem, payloads) 47 | 48 | itemHolder.img(R.id.lib_right_ico_view)?.apply { 49 | val drawable = itemEditTipDrawable ?: loadDrawable(itemEditTipIcon) 50 | if (drawable == null || editItemConfig.itemNoEditModel == true /*不可编辑*/) { 51 | gone() 52 | } else { 53 | visible() 54 | setImageDrawable(drawable) 55 | } 56 | 57 | //处理默认弹出软键盘 58 | if (itemRightIcoClick == null) { 59 | if (editItemConfig.itemEditTextStyle.noEditModel) { 60 | gone() 61 | } else { 62 | throttleClickIt { 63 | itemHolder.focus(editItemConfig.itemEditTextViewId)?.showSoftInput() 64 | } 65 | } 66 | } else { 67 | throttleClickIt { 68 | itemRightIcoClick?.invoke(itemHolder, it) 69 | } 70 | } 71 | 72 | } 73 | 74 | //右边文本, cm unit 75 | itemHolder.gone(R.id.lib_right_text_view, itemRightTextStyle.text == null) 76 | itemHolder.tv(R.id.lib_right_text_view)?.apply { 77 | itemRightTextStyle.updateStyle(this) 78 | } 79 | } 80 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/item/DslLabelTextItem.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item 2 | 3 | import com.angcyo.dsladapter.DslAdapterItem 4 | import com.angcyo.dsladapter.DslViewHolder 5 | 6 | /** 7 | * 简单的文本显示item 8 | * Email:angcyo@126.com 9 | * @author angcyo 10 | * @date 2020/03/23 11 | * Copyright (c) 2019 ShenZhen O&M Cloud Co., Ltd. All rights reserved. 12 | */ 13 | open class DslLabelTextItem : DslBaseLabelItem() { 14 | 15 | /**显示的文本*/ 16 | var itemText: CharSequence? = null 17 | set(value) { 18 | field = value 19 | itemTextStyle.text = value 20 | } 21 | 22 | /**统一样式配置*/ 23 | var itemTextStyle = TextStyleConfig() 24 | 25 | init { 26 | itemLayoutId = R.layout.dsl_label_text_item 27 | } 28 | 29 | override fun onItemBind( 30 | itemHolder: DslViewHolder, 31 | itemPosition: Int, 32 | adapterItem: DslAdapterItem, 33 | payloads: List 34 | ) { 35 | super.onItemBind(itemHolder, itemPosition, adapterItem, payloads) 36 | 37 | itemHolder.tv(R.id.lib_text_view)?.apply { 38 | itemTextStyle.updateStyle(this) 39 | } 40 | } 41 | 42 | open fun configTextStyle(action: TextStyleConfig.() -> Unit) { 43 | itemTextStyle.action() 44 | } 45 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/item/DslNestedRecyclerItem.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item 2 | 3 | import androidx.fragment.app.Fragment 4 | import androidx.recyclerview.widget.RecyclerView 5 | import com.angcyo.dsladapter.item.IFragmentItem 6 | import com.angcyo.dsladapter.DslAdapterItem 7 | import com.angcyo.item.style.INestedRecyclerItem 8 | import com.angcyo.item.style.NestedRecyclerItemConfig 9 | import com.angcyo.dsladapter.DslViewHolder 10 | 11 | /** 12 | * 内嵌[RecyclerView]的item 13 | * Email:angcyo@126.com 14 | * @author angcyo 15 | * @date 2020/03/19 16 | * Copyright (c) 2019 ShenZhen O&M Cloud Co., Ltd. All rights reserved. 17 | */ 18 | open class DslNestedRecyclerItem : DslAdapterItem(), INestedRecyclerItem, IFragmentItem { 19 | 20 | override var nestedRecyclerItemConfig: NestedRecyclerItemConfig = NestedRecyclerItemConfig() 21 | 22 | override var itemFragment: Fragment? = null 23 | 24 | init { 25 | itemLayoutId = R.layout.dsl_nested_recycler_item 26 | } 27 | 28 | override fun onItemBind( 29 | itemHolder: DslViewHolder, 30 | itemPosition: Int, 31 | adapterItem: DslAdapterItem, 32 | payloads: List 33 | ) { 34 | super.onItemBind(itemHolder, itemPosition, adapterItem, payloads) 35 | } 36 | 37 | override fun onItemViewRecycled(itemHolder: DslViewHolder, itemPosition: Int) { 38 | super.onItemViewRecycled(itemHolder, itemPosition) 39 | onNestedRecyclerViewRecycled(itemHolder, itemPosition) 40 | } 41 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/item/DslSwitchInfoItem.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item 2 | 3 | import com.angcyo.dsladapter.DslAdapterItem 4 | import com.angcyo.github.SwitchButton 5 | import com.angcyo.dsladapter.DslViewHolder 6 | 7 | /** 8 | * 9 | * Email:angcyo@126.com 10 | * @author angcyo 11 | * @date 2019/08/09 12 | * Copyright (c) 2019 ShenZhen O&M Cloud Co., Ltd. All rights reserved. 13 | */ 14 | open class DslSwitchInfoItem : DslBaseInfoItem() { 15 | 16 | /**是否选中*/ 17 | var itemSwitchChecked = false 18 | 19 | /**状态回调, 提供一个可以完全覆盖的方法*/ 20 | var itemSwitchChanged: (checked: Boolean) -> Unit = { 21 | onItemSwitchChanged(it) 22 | } 23 | 24 | init { 25 | itemExtendLayoutId = R.layout.dsl_extent_switch_item 26 | } 27 | 28 | override fun onItemBind( 29 | itemHolder: DslViewHolder, 30 | itemPosition: Int, 31 | adapterItem: DslAdapterItem, 32 | payloads: List 33 | ) { 34 | super.onItemBind(itemHolder, itemPosition, adapterItem, payloads) 35 | 36 | itemHolder.v(R.id.lib_switch_view)?.apply { 37 | 38 | setOnCheckedChangeListener(object : SwitchButton.OnCheckedChangeListener { 39 | override fun onCheckedChanged(view: SwitchButton, isChecked: Boolean) { 40 | val old = itemSwitchChecked 41 | itemSwitchChecked = isChecked 42 | if (old != itemSwitchChecked) { 43 | itemSwitchChanged(itemSwitchChecked) 44 | } 45 | } 46 | }) 47 | 48 | //刷新界面的时候, 不执行动画 49 | val old = isEnableEffect 50 | isEnableEffect = false 51 | isChecked = itemSwitchChecked 52 | isEnableEffect = old 53 | } 54 | } 55 | 56 | /**提供一个可以被重写的子类方法*/ 57 | open fun onItemSwitchChanged(checked: Boolean) { 58 | 59 | } 60 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/item/DslTextInfoItem.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item 2 | 3 | import androidx.annotation.DrawableRes 4 | import com.angcyo.dsladapter.DslAdapterItem 5 | import com.angcyo.dsladapter.DslViewHolder 6 | import com.angcyo.widget.span.colorFilter 7 | import com.angcyo.widget.span.undefined_res 8 | 9 | /** 10 | * 横条左右都是文本控件的item 11 | * Email:angcyo@126.com 12 | * @author angcyo 13 | * @date 2019/08/09 14 | * Copyright (c) 2019 ShenZhen O&M Cloud Co., Ltd. All rights reserved. 15 | */ 16 | open class DslTextInfoItem : DslBaseInfoItem() { 17 | 18 | /**描述文本*/ 19 | var itemDarkText: CharSequence? = null 20 | 21 | @DrawableRes 22 | var itemDarkIcon: Int = undefined_res 23 | var itemDarkIconColor: Int = undefined_res 24 | 25 | init { 26 | itemExtendLayoutId = R.layout.dsl_extent_text_item 27 | } 28 | 29 | override fun onItemBind( 30 | itemHolder: DslViewHolder, 31 | itemPosition: Int, 32 | adapterItem: DslAdapterItem, 33 | payloads: List 34 | ) { 35 | super.onItemBind(itemHolder, itemPosition, adapterItem, payloads) 36 | 37 | //文本 38 | itemHolder.tv(R.id.lib_dark_text_view)?.apply { 39 | text = itemDarkText 40 | 41 | if (itemDarkIconColor == undefined_res) { 42 | setRightIco(itemDarkIcon) 43 | } else { 44 | setRightIco(loadDrawable(itemDarkIcon).colorFilter(itemDarkIconColor)) 45 | } 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/item/DslTextItem.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item 2 | 3 | import com.angcyo.dsladapter.DslAdapterItem 4 | import com.angcyo.dsladapter.DslViewHolder 5 | 6 | /** 7 | * 简单的文本显示item 8 | * Email:angcyo@126.com 9 | * @author angcyo 10 | * @date 2020/04/23 11 | * Copyright (c) 2020 ShenZhen Wayto Ltd. All rights reserved. 12 | */ 13 | open class DslTextItem : DslAdapterItem() { 14 | 15 | /**文本*/ 16 | var itemText: CharSequence? = null 17 | set(value) { 18 | field = value 19 | itemTextStyle.text = value 20 | } 21 | 22 | /**统一样式配置*/ 23 | var itemTextStyle = TextStyleConfig() 24 | 25 | init { 26 | itemLayoutId = R.layout.dsl_text_item 27 | } 28 | 29 | override fun onItemBind( 30 | itemHolder: DslViewHolder, 31 | itemPosition: Int, 32 | adapterItem: DslAdapterItem, 33 | payloads: List 34 | ) { 35 | super.onItemBind(itemHolder, itemPosition, adapterItem, payloads) 36 | 37 | itemHolder.tv(R.id.lib_text_view)?.apply { 38 | itemTextStyle.updateStyle(this) 39 | } 40 | } 41 | 42 | open fun configTextStyle(action: TextStyleConfig.() -> Unit) { 43 | itemTextStyle.action() 44 | } 45 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/item/RAnimatorListener.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item 2 | 3 | import android.animation.Animator 4 | 5 | /** 6 | * 7 | * Email:angcyo@126.com 8 | * @author angcyo 9 | * @date 2019/12/31 10 | * Copyright (c) 2019 ShenZhen O&M Cloud Co., Ltd. All rights reserved. 11 | */ 12 | open class RAnimatorListener : Animator.AnimatorListener { 13 | 14 | private var isCancel = false 15 | 16 | var onAnimatorFinish: (animator: Animator, fromCancel: Boolean) -> Unit = 17 | { animator, fromCancel -> 18 | _onAnimatorFinish(animator, fromCancel) 19 | } 20 | 21 | override fun onAnimationRepeat(animation: Animator) { 22 | } 23 | 24 | override fun onAnimationEnd(animation: Animator) { 25 | if (isCancel) { 26 | //当动画被取消的时候, 系统会回调onAnimationCancel, 然后 onAnimationEnd 27 | //所以, 这里过滤一下 28 | } else { 29 | onAnimatorFinish(animation, false) 30 | } 31 | } 32 | 33 | override fun onAnimationCancel(animation: Animator) { 34 | isCancel = true 35 | onAnimatorFinish(animation, true) 36 | } 37 | 38 | override fun onAnimationStart(animation: Animator) { 39 | isCancel = false 40 | } 41 | 42 | open fun _onAnimatorFinish(animator: Animator, fromCancel: Boolean) { 43 | 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/item/base/LibInitProvider.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item.base 2 | 3 | import android.content.ContentProvider 4 | import android.content.ContentValues 5 | import android.content.Context 6 | import android.database.Cursor 7 | import android.net.Uri 8 | 9 | /** 10 | * 免入侵, 获取[Content]对象 11 | * Email:angcyo@126.com 12 | * @author angcyo 13 | * @date 2020/04/23 14 | * Copyright (c) 2020 ShenZhen Wayto Ltd. All rights reserved. 15 | */ 16 | class LibInitProvider : ContentProvider() { 17 | 18 | companion object { 19 | lateinit var contentProvider: Context 20 | } 21 | 22 | override fun onCreate(): Boolean { 23 | contentProvider = context!!.applicationContext 24 | return true 25 | } 26 | 27 | override fun insert(uri: Uri, values: ContentValues?): Uri? = null 28 | 29 | override fun query( 30 | uri: Uri, 31 | projection: Array?, 32 | selection: String?, 33 | selectionArgs: Array?, 34 | sortOrder: String? 35 | ): Cursor? = null 36 | 37 | override fun update( 38 | uri: Uri, 39 | values: ContentValues?, 40 | selection: String?, 41 | selectionArgs: Array? 42 | ): Int = -1 43 | 44 | override fun delete(uri: Uri, selection: String?, selectionArgs: Array?): Int = -1 45 | 46 | override fun getType(uri: Uri): String? = null 47 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/item/base/RAnimationListener.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item.base 2 | 3 | import android.view.animation.Animation 4 | 5 | /** 6 | * 7 | * Email:angcyo@126.com 8 | * @author angcyo 9 | * @date 2019/12/31 10 | * Copyright (c) 2019 ShenZhen O&M Cloud Co., Ltd. All rights reserved. 11 | */ 12 | open class RAnimationListener : Animation.AnimationListener { 13 | override fun onAnimationRepeat(animation: Animation) { 14 | } 15 | 16 | override fun onAnimationEnd(animation: Animation) { 17 | } 18 | 19 | override fun onAnimationStart(animation: Animation) { 20 | } 21 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/item/base/SingleTextWatcher.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.widget.edit 2 | 3 | import android.text.Editable 4 | import android.text.TextWatcher 5 | 6 | /** 7 | * Email:angcyo@126.com 8 | * 9 | * @author angcyo 10 | * @date 2019/06/06 11 | * Copyright (c) 2019 ShenZhen O&M Cloud Co., Ltd. All rights reserved. 12 | */ 13 | open class SingleTextWatcher : TextWatcher { 14 | override fun beforeTextChanged(sequence: CharSequence?, start: Int, count: Int, after: Int) { 15 | } 16 | 17 | override fun onTextChanged(sequence: CharSequence?, start: Int, before: Int, count: Int) { 18 | } 19 | 20 | override fun afterTextChanged(editable: Editable?) {} 21 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/item/style/ButtonStyleConfig.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item.style 2 | 3 | import android.graphics.Color 4 | import android.view.View 5 | import com.angcyo.dpi 6 | import com.angcyo.item.R 7 | import com.angcyo.item._color 8 | import com.angcyo.widget.DslButton 9 | import com.angcyo.widget.colorState 10 | import com.angcyo.widget.span.undefined_float 11 | 12 | /** 13 | * 按钮样式配置 14 | * Email:angcyo@126.com 15 | * @author angcyo 16 | * @date 2020/06/09 17 | * Copyright (c) 2020 ShenZhen Wayto Ltd. All rights reserved. 18 | */ 19 | open class ButtonStyleConfig : TextStyleConfig() { 20 | 21 | companion object { 22 | //主题渐变样式, 标准的填充色按钮 23 | val BUTTON_STYLE_THEME = 1 24 | 25 | //填充颜色的样式, 无渐变, 纯色填充+波纹效果 26 | val BUTTON_STYLE_SOLID = 2 27 | 28 | //边框->主题渐变填充 29 | val BUTTON_STYLE_FILL = 3 30 | } 31 | 32 | /**特定样式*/ 33 | var style: Int = BUTTON_STYLE_THEME 34 | 35 | /**样式[BUTTON_STYLE_THEME] [BUTTON_STYLE_FILL]时, 渐变的颜色*/ 36 | var styleThemeColors = intArrayOf( 37 | _color(R.color.colorPrimary), 38 | _color(R.color.colorPrimaryDark) 39 | ) 40 | 41 | /**样式[BUTTON_STYLE_THEME] [BUTTON_STYLE_FILL]时, 文本的颜色*/ 42 | var styleThemeTextColor = Color.WHITE 43 | 44 | /**样式[BUTTON_STYLE_SOLID]时, solid的颜色*/ 45 | var styleSolidSolidColor = Color.WHITE 46 | 47 | /**样式[BUTTON_STYLE_FILL]时, solid的颜色*/ 48 | var styleFillSolidColor = Color.TRANSPARENT 49 | 50 | /**样式[BUTTON_STYLE_SOLID] [BUTTON_STYLE_FILL]时, 文本的颜色*/ 51 | var styleSolidTextColor = _color(R.color.text_general_color) 52 | set(value) { 53 | field = value 54 | textColor = value 55 | } 56 | 57 | /**[BUTTON_STYLE_FILL]*/ 58 | var styleFillStrokeWidth = 2 * dpi 59 | 60 | /**[BUTTON_STYLE_FILL]*/ 61 | var styleFillStrokeColor = _color(R.color.colorPrimary) 62 | 63 | var buttonRadius: Float = undefined_float 64 | 65 | init { 66 | themeStyle() 67 | } 68 | 69 | override fun updateStyle(view: View) { 70 | super.updateStyle(view) 71 | 72 | if (view is DslButton) { 73 | 74 | //不支持不同圆角大小的样式 75 | if (buttonRadius == undefined_float) { 76 | buttonRadius = view.normalRadii.first() 77 | } 78 | view.setButtonRadius(buttonRadius) 79 | 80 | when (style) { 81 | BUTTON_STYLE_THEME -> { 82 | view.enableTextStyle = true 83 | view.setButtonGradientColors(styleThemeColors) 84 | view.setButtonTextColor(textColor) 85 | view.setButtonStrokeWidth(0) 86 | } 87 | 88 | BUTTON_STYLE_SOLID -> { 89 | view.enableTextStyle = true 90 | view.setButtonGradientColors(null) 91 | view.setButtonSolidColor(styleSolidSolidColor) 92 | view.setButtonTextColor(textColor) 93 | view.setButtonStrokeWidth(0) 94 | } 95 | 96 | BUTTON_STYLE_FILL -> { 97 | view.enableTextStyle = false 98 | view.setButtonGradientColors(null) 99 | view.setButtonSolidColor(styleFillSolidColor) 100 | view.setButtonStrokeWidth(styleFillStrokeWidth) 101 | view.setButtonStrokeColor(styleFillStrokeColor) 102 | 103 | view.pressStrokeWidth = 0 104 | view.pressGradientColors = styleThemeColors 105 | } 106 | } 107 | 108 | view.updateDrawable() 109 | } 110 | } 111 | 112 | /**使用主题样式, 颜色渐变*/ 113 | fun themeStyle() { 114 | style = BUTTON_STYLE_THEME 115 | textColor = styleThemeTextColor 116 | } 117 | 118 | /**使用渐变样式*/ 119 | fun gradientStyle(gradientStartColor: Int, gradientEndColor: Int = gradientStartColor) { 120 | themeStyle() 121 | styleThemeColors = intArrayOf(gradientStartColor, gradientEndColor) 122 | } 123 | 124 | /**填充颜色的样式*/ 125 | fun solidStyle() { 126 | style = BUTTON_STYLE_SOLID 127 | textColor = styleSolidTextColor 128 | } 129 | 130 | /**边框 填充样式*/ 131 | fun fillStyle() { 132 | style = BUTTON_STYLE_FILL 133 | textColors = colorState( 134 | DslButton.ATTR_PRESSED to styleThemeTextColor, 135 | DslButton.ATTR_NORMAL to styleThemeColors[0] 136 | ) 137 | } 138 | 139 | /**白底黑字样式*/ 140 | fun whiteStyle() { 141 | style = BUTTON_STYLE_SOLID 142 | textColor = styleSolidTextColor 143 | styleSolidSolidColor = Color.WHITE 144 | } 145 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/item/style/EditStyleConfig.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item.style 2 | 3 | import android.text.InputFilter 4 | import android.text.InputType 5 | import android.text.method.DigitsKeyListener 6 | import android.view.Gravity 7 | import android.view.View 8 | import android.widget.EditText 9 | import android.widget.TextView 10 | import com.angcyo.item.DslBaseEditItem 11 | import com.angcyo.item.add 12 | import com.angcyo.item.addFilter 13 | import com.angcyo.item.clearListeners 14 | import com.angcyo.item.remove 15 | import com.angcyo.item.removeFilter 16 | import com.angcyo.item.setInputText 17 | import com.angcyo.item.setMaxLine 18 | import com.angcyo.widget.CharLengthFilter 19 | 20 | /** 21 | * 输入框样式配置 22 | * Email:angcyo@126.com 23 | * @author angcyo 24 | * @date 2020/06/09 25 | * Copyright (c) 2020 ShenZhen Wayto Ltd. All rights reserved. 26 | */ 27 | 28 | class EditStyleConfig : TextStyleConfig() { 29 | 30 | /**文本输入类型*/ 31 | var editInputType = InputType.TYPE_CLASS_TEXT 32 | 33 | /**最大输入字符数, -1取消限制*/ 34 | var editMaxInputLength = DslBaseEditItem.DEFAULT_MAX_INPUT_LENGTH 35 | 36 | /**输入过滤器*/ 37 | var editInputFilterList = mutableListOf() 38 | 39 | /**输入限制, 此属性和[editInputFilterList]互斥 40 | * [R.string.lib_number_digits] 41 | * [R.string.lib_password_digits] 42 | * [R.string.lib_en_digits]*/ 43 | var editDigits: String? = null 44 | 45 | /**输入框不可编辑*/ 46 | var noEditModel: Boolean = false 47 | 48 | /**最大输入行数, <=1 单行*/ 49 | var editMaxLine: Int = 1 50 | set(value) { 51 | field = value 52 | if (value <= 1) { 53 | textGravity = Gravity.LEFT or Gravity.CENTER_VERTICAL 54 | editInputType = editInputType.remove(InputType.TYPE_TEXT_FLAG_MULTI_LINE) 55 | } else { 56 | textGravity = Gravity.TOP or Gravity.LEFT 57 | editInputType = editInputType.add(InputType.TYPE_TEXT_FLAG_MULTI_LINE) 58 | } 59 | } 60 | 61 | override fun updateStyle(view: View) { 62 | super.updateStyle(view) 63 | 64 | if (view is TextView) { 65 | with(view) { 66 | //清空text change监听 67 | clearListeners() 68 | 69 | //过滤器 70 | filters = editInputFilterList.toTypedArray() 71 | 72 | //单行 or 多行 73 | setMaxLine(editMaxLine) 74 | 75 | inputType = editInputType 76 | isEnabled = !noEditModel 77 | 78 | if (editMaxInputLength > 0) { 79 | addFilter(InputFilter.LengthFilter(editMaxInputLength)) 80 | } else { 81 | removeFilter { 82 | this is InputFilter.LengthFilter || this is CharLengthFilter 83 | } 84 | } 85 | 86 | //digits 放在[inputType]后面 87 | editDigits?.let { 88 | keyListener = DigitsKeyListener.getInstance(it) 89 | } 90 | 91 | if (this is EditText) { 92 | setInputText(this@EditStyleConfig.text) 93 | } 94 | } 95 | } 96 | } 97 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/item/style/IAutoInitItem.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item.style 2 | 3 | import com.angcyo.dsladapter.DslAdapterItem 4 | import com.angcyo.dsladapter.DslViewHolder 5 | import com.angcyo.dsladapter.annotation.ItemInitEntryPoint 6 | import com.angcyo.dsladapter.item.IDslItem 7 | 8 | /** 9 | * 自动初始化, 继承此类的item, 可以实现自动初始化 10 | * [com.angcyo.dsladapter.DslAdapterItem._initItemConfig] 11 | * Email:angcyo@126.com 12 | * @author angcyo 13 | * @date 2021/09/23 14 | * Copyright (c) 2020 ShenZhen Wayto Ltd. All rights reserved. 15 | */ 16 | interface IAutoInitItem : IDslItem { 17 | 18 | /**自动初始化入口, 统一入口*/ 19 | @ItemInitEntryPoint 20 | override fun initItemConfig( 21 | itemHolder: DslViewHolder, 22 | itemPosition: Int, 23 | adapterItem: DslAdapterItem, 24 | payloads: List 25 | ) { 26 | super.initItemConfig(itemHolder, itemPosition, adapterItem, payloads) 27 | 28 | //分发具体的初始化方法 29 | if (this is IBadgeItem) { 30 | initBadgeItem(itemHolder, itemPosition, adapterItem, payloads) 31 | } 32 | if (this is IDesItem) { 33 | initDesItem(itemHolder, itemPosition, adapterItem, payloads) 34 | } 35 | if (this is ITextItem) { 36 | initTextItem(itemHolder, itemPosition, adapterItem, payloads) 37 | } 38 | if (this is IEditItem) { 39 | initEditItem(itemHolder, itemPosition, adapterItem, payloads) 40 | } 41 | if (this is ILabelItem) { 42 | initLabelItem(itemHolder, itemPosition, adapterItem, payloads) 43 | } 44 | if (this is ITextInfoItem) { 45 | initInfoTextItem(itemHolder, itemPosition, adapterItem, payloads) 46 | } 47 | if (this is IBodyItem) { 48 | initBodyItem(itemHolder, itemPosition, adapterItem, payloads) 49 | } 50 | if (this is IButtonItem) { 51 | initButtonItem(itemHolder, itemPosition, adapterItem, payloads) 52 | } 53 | if (this is INestedRecyclerItem) { 54 | initNestedRecyclerItem(itemHolder, itemPosition, adapterItem, payloads) 55 | } 56 | if (this is ICheckItem) { 57 | initCheckItem(itemHolder, itemPosition, adapterItem, payloads) 58 | } 59 | if (this is ISwitchItem) { 60 | initSwitchItem(itemHolder, itemPosition, adapterItem, payloads) 61 | } 62 | if (this is ICheckGroupItem) { 63 | initCheckGroupItem(itemHolder, itemPosition, adapterItem, payloads) 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/item/style/IBadgeItem.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item.style 2 | 3 | import com.angcyo.dsladapter.DslAdapterItem 4 | import com.angcyo.dsladapter.DslViewHolder 5 | import com.angcyo.dsladapter.annotation.ItemInitEntryPoint 6 | import com.angcyo.dsladapter.item.IDslItemConfig 7 | import com.angcyo.item.R 8 | import com.angcyo.widget.IBadgeView 9 | 10 | /** 11 | * 角标文本[BadgeTextView]item 12 | * Email:angcyo@126.com 13 | * @author angcyo 14 | * @date 2021/09/23 15 | * Copyright (c) 2020 ShenZhen Wayto Ltd. All rights reserved. 16 | */ 17 | interface IBadgeItem : IAutoInitItem { 18 | 19 | var badgeItemConfig: BadgeItemConfig 20 | 21 | /**初始化*/ 22 | @ItemInitEntryPoint 23 | fun initBadgeItem( 24 | itemHolder: DslViewHolder, 25 | itemPosition: Int, 26 | adapterItem: DslAdapterItem, 27 | payloads: List 28 | ) { 29 | itemHolder.view(badgeItemConfig.itemBadgeViewId)?.apply { 30 | if (this is IBadgeView) { 31 | dslBadeDrawable.apply { 32 | drawBadge = true 33 | badgeText = badgeItemConfig.itemBadgeText 34 | requestLayout() 35 | } 36 | } 37 | } 38 | } 39 | } 40 | 41 | var IBadgeItem.itemBadgeText: String? 42 | get() = badgeItemConfig.itemBadgeText 43 | set(value) { 44 | badgeItemConfig.itemBadgeText = value 45 | } 46 | 47 | 48 | class BadgeItemConfig : IDslItemConfig { 49 | 50 | var itemBadgeViewId: Int = R.id.lib_badge_view 51 | 52 | /**[com.angcyo.drawable.text.DslBadgeDrawable.badgeText]*/ 53 | var itemBadgeText: String? = null 54 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/item/style/IBodyItem.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item.style 2 | 3 | import com.angcyo.dsladapter.DslAdapterItem 4 | import com.angcyo.dsladapter.annotation.ItemInitEntryPoint 5 | import com.angcyo.dsladapter.item.IDslItemConfig 6 | import com.angcyo.item.R 7 | import com.angcyo.dsladapter.DslViewHolder 8 | 9 | /** 10 | * 11 | * Email:angcyo@126.com 12 | * @author angcyo 13 | * @date 2021/09/23 14 | * Copyright (c) 2020 ShenZhen Wayto Ltd. All rights reserved. 15 | */ 16 | interface IBodyItem : IAutoInitItem { 17 | 18 | /**统一样式配置*/ 19 | var bodyItemConfig: BodyItemConfig 20 | 21 | /**初始化*/ 22 | @ItemInitEntryPoint 23 | fun initBodyItem(itemHolder: DslViewHolder, 24 | itemPosition: Int, 25 | adapterItem: DslAdapterItem, 26 | payloads: List) { 27 | itemHolder.tv(bodyItemConfig.itemBodyViewId)?.apply { 28 | bodyItemConfig.itemBodyStyle.updateStyle(this) 29 | } 30 | } 31 | 32 | fun configBodyStyle(action: TextStyleConfig.() -> Unit) { 33 | bodyItemConfig.itemBodyStyle.action() 34 | } 35 | } 36 | 37 | var IBodyItem.itemBodyText: CharSequence? 38 | get() = bodyItemConfig.itemBodyText 39 | set(value) { 40 | bodyItemConfig.itemBodyText = value 41 | } 42 | 43 | class BodyItemConfig : IDslItemConfig { 44 | 45 | var itemBodyViewId: Int = R.id.lib_body_view 46 | 47 | /**文本*/ 48 | var itemBodyText: CharSequence? = null 49 | set(value) { 50 | field = value 51 | itemBodyStyle.text = value 52 | } 53 | 54 | /**统一样式配置*/ 55 | var itemBodyStyle = TextStyleConfig() 56 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/item/style/IButtonItem.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item.style 2 | 3 | import android.view.Gravity 4 | import com.angcyo.dsladapter.DslAdapterItem 5 | import com.angcyo.dsladapter.annotation.ItemInitEntryPoint 6 | import com.angcyo.dsladapter.item.IDslItemConfig 7 | import com.angcyo.item.R 8 | import com.angcyo.widget.DslButton 9 | import com.angcyo.dsladapter.DslViewHolder 10 | import com.angcyo.item.button 11 | 12 | /** 13 | * 14 | * Email:angcyo@126.com 15 | * @author angcyo 16 | * @date 2021/09/24 17 | * Copyright (c) 2020 ShenZhen Wayto Ltd. All rights reserved. 18 | */ 19 | interface IButtonItem : IAutoInitItem { 20 | 21 | var buttonItemConfig: ButtonItemConfig 22 | 23 | @ItemInitEntryPoint 24 | fun initButtonItem(itemHolder: DslViewHolder, 25 | itemPosition: Int, 26 | adapterItem: DslAdapterItem, 27 | payloads: List) { 28 | itemHolder.itemView.isClickable = false 29 | 30 | itemHolder.button(buttonItemConfig.itemButtonViewId)?.apply { 31 | buttonItemConfig.itemButtonStyle.updateStyle(this) 32 | buttonItemConfig.itemButtonConfig(this) 33 | 34 | if (this@IButtonItem is DslAdapterItem) { 35 | setOnClickListener(_clickListener) 36 | setOnLongClickListener(_longClickListener) 37 | } 38 | } 39 | } 40 | 41 | fun configButtonStyle(action: ButtonStyleConfig.() -> Unit) { 42 | buttonItemConfig.itemButtonStyle.action() 43 | } 44 | } 45 | 46 | var IButtonItem.itemButtonText: CharSequence? 47 | get() = buttonItemConfig.itemButtonText 48 | set(value) { 49 | buttonItemConfig.itemButtonText = value 50 | } 51 | 52 | class ButtonItemConfig : IDslItemConfig { 53 | 54 | var itemButtonViewId: Int = R.id.lib_button 55 | 56 | /**按钮显示的文本*/ 57 | var itemButtonText: CharSequence? = null 58 | set(value) { 59 | field = value 60 | itemButtonStyle.text = value 61 | } 62 | 63 | /**按钮样式配置项*/ 64 | var itemButtonStyle = ButtonStyleConfig().apply { 65 | textGravity = Gravity.CENTER 66 | } 67 | 68 | /**按钮配置回调*/ 69 | var itemButtonConfig: (DslButton) -> Unit = { 70 | 71 | } 72 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/item/style/ICheckGroupItem.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item.style 2 | 3 | import android.view.View 4 | import android.view.ViewGroup 5 | import android.widget.TextView 6 | import com.angcyo.dsladapter.DslAdapterItem 7 | import com.angcyo.dsladapter.DslViewHolder 8 | import com.angcyo.dsladapter.annotation.ItemInitEntryPoint 9 | import com.angcyo.dsladapter.item.IDslItemConfig 10 | import com.angcyo.extend.IToText 11 | import com.angcyo.extend.IToValue 12 | import com.angcyo.item.R 13 | import com.angcyo.item.string 14 | import com.angcyo.item.toStr 15 | import com.angcyo.widget.DslSelector 16 | import com.angcyo.widget.find 17 | import com.angcyo.widget.resetChild 18 | 19 | /** 20 | * @author angcyo 21 | * @since 2022/06/20 22 | */ 23 | interface ICheckGroupItem : IAutoInitItem { 24 | 25 | /**配置项*/ 26 | var checkGroupItemConfig: CheckGroupItemConfig 27 | 28 | @ItemInitEntryPoint 29 | fun initCheckGroupItem( 30 | itemHolder: DslViewHolder, 31 | itemPosition: Int, 32 | adapterItem: DslAdapterItem, 33 | payloads: List 34 | ) { 35 | itemHolder.v(checkGroupItemConfig.itemCheckGroupViewId) 36 | ?.apply { 37 | 38 | resetChild( 39 | checkGroupItemConfig.itemCheckItems.size, 40 | checkGroupItemConfig.itemCheckLayoutId 41 | ) { itemView, itemIndex -> 42 | val item = checkGroupItemConfig.itemCheckItems[itemIndex] 43 | itemView.tag = checkGroupItemConfig.itemCheckItemToValue(item) //保存数据 44 | itemView.find(R.id.lib_text_view)?.text = 45 | checkGroupItemConfig.itemCheckItemToText(item) 46 | } 47 | 48 | /**安装选择组件*/ 49 | checkGroupItemConfig.itemSelectorHelper.install(this) { 50 | dslMultiMode = checkGroupItemConfig.itemMultiMode 51 | dslMinSelectLimit = 52 | if (checkGroupItemConfig.itemMultiMode) checkGroupItemConfig.itemMinSelectLimit else 1 53 | 54 | onSelectItemView = this@ICheckGroupItem::onCheckInterceptSelectView 55 | onSelectViewChange = this@ICheckGroupItem::onCheckSelectViewChange 56 | onSelectIndexChange = this@ICheckGroupItem::onCheckSelectIndexChange 57 | } 58 | 59 | val indexList = mutableListOf() 60 | checkGroupItemConfig.itemCheckedItems.forEach { 61 | indexList.add(checkGroupItemConfig.itemCheckItems.indexOf(it)) 62 | } 63 | checkGroupItemConfig.itemSelectorHelper.selector( 64 | indexList, 65 | fromUser = checkGroupItemConfig.itemFirstNotifyChange 66 | ) 67 | checkGroupItemConfig.itemFirstNotifyChange = false 68 | } 69 | } 70 | 71 | /**是否需要拦截选中*/ 72 | fun onCheckInterceptSelectView( 73 | itemView: View, 74 | index: Int, 75 | select: Boolean, 76 | fromUser: Boolean 77 | ): Boolean { 78 | return false 79 | } 80 | 81 | /**选中后的view改变的回调*/ 82 | fun onCheckSelectViewChange( 83 | fromView: View?, 84 | selectViewList: List, 85 | reselect: Boolean, 86 | fromUser: Boolean 87 | ) { 88 | 89 | } 90 | 91 | /**选中后的index改变的回调*/ 92 | fun onCheckSelectIndexChange( 93 | fromIndex: Int, 94 | selectIndexList: List, 95 | reselect: Boolean, 96 | fromUser: Boolean 97 | ) { 98 | checkGroupItemConfig._itemCheckedIndexList.clear() 99 | checkGroupItemConfig._itemCheckedIndexList.addAll(selectIndexList) 100 | 101 | //清空之前 102 | checkGroupItemConfig.itemCheckedItems.clear() 103 | 104 | //当前选中项 105 | selectIndexList.forEach { 106 | checkGroupItemConfig.itemCheckedItems.add(checkGroupItemConfig.itemCheckItems[it]) 107 | } 108 | 109 | //回调 110 | checkGroupItemConfig.itemCheckChangedAction(fromIndex, selectIndexList, reselect, fromUser) 111 | 112 | //更新依赖 113 | if (fromUser) { 114 | if (this is DslAdapterItem) { 115 | itemChanging = true 116 | } 117 | } 118 | } 119 | 120 | /**Dsl*/ 121 | fun configCheckGroupItem(block: CheckGroupItemConfig.() -> Unit) { 122 | checkGroupItemConfig.block() 123 | } 124 | } 125 | 126 | /**需要选择的项*/ 127 | var ICheckGroupItem.itemCheckItems: List 128 | get() = checkGroupItemConfig.itemCheckItems 129 | set(value) { 130 | checkGroupItemConfig.itemCheckItems = value 131 | } 132 | 133 | /**选中的项*/ 134 | var ICheckGroupItem.itemCheckedItems: MutableList 135 | get() = checkGroupItemConfig.itemCheckedItems 136 | set(value) { 137 | checkGroupItemConfig.itemCheckedItems = value 138 | } 139 | 140 | /**只读属性, 选中的索引值*/ 141 | val ICheckGroupItem._itemCheckedIndexList: List 142 | get() = checkGroupItemConfig._itemCheckedIndexList 143 | 144 | /**布局id*/ 145 | var ICheckGroupItem.itemCheckLayoutId: Int 146 | get() = checkGroupItemConfig.itemCheckLayoutId 147 | set(value) { 148 | checkGroupItemConfig.itemCheckLayoutId = value 149 | } 150 | 151 | /**回调*/ 152 | var ICheckGroupItem.itemCheckChangedAction: (fromIndex: Int, selectIndexList: List, reselect: Boolean, fromUser: Boolean) -> Unit 153 | get() = checkGroupItemConfig.itemCheckChangedAction 154 | set(value) { 155 | checkGroupItemConfig.itemCheckChangedAction = value 156 | } 157 | 158 | class CheckGroupItemConfig : IDslItemConfig { 159 | 160 | /**需要操作的控件id[R.id.lib_flow_layout]*/ 161 | var itemCheckGroupViewId: Int = R.id.lib_flow_layout 162 | 163 | /**选项列表*/ 164 | var itemCheckItems = listOf() 165 | 166 | /**选中的列表*/ 167 | var itemCheckedItems = mutableListOf() 168 | 169 | /**选项布局*/ 170 | var itemCheckLayoutId: Int = R.layout.layout_check 171 | 172 | /**是否是多选模式*/ 173 | var itemMultiMode = false 174 | 175 | /**多选时, 最小选中数量*/ 176 | var itemMinSelectLimit = 0 177 | 178 | /**将选项[item], 转成可以显示在界面的 文本类型*/ 179 | var itemCheckItemToText: (item: Any) -> CharSequence? = { item -> 180 | if (item is IToText) { 181 | item.toText() 182 | } else { 183 | item.string() 184 | } 185 | } 186 | 187 | /**将选项[item], 转成表单上传的数据*/ 188 | var itemCheckItemToValue: (item: Any) -> Any? = { item -> 189 | if (item is IToValue) { 190 | item.toValue() 191 | } else { 192 | item.toStr() 193 | } 194 | } 195 | 196 | var itemFirstNotifyChange = true 197 | 198 | /**回调*/ 199 | var itemCheckChangedAction: (fromIndex: Int, selectIndexList: List, reselect: Boolean, fromUser: Boolean) -> Unit = 200 | { fromIndex, selectIndexList, reselect, fromUser -> 201 | 202 | } 203 | 204 | /**单选/多选支持*/ 205 | val itemSelectorHelper = DslSelector() 206 | 207 | //内部使用 208 | var _itemCheckedIndexList = mutableListOf() 209 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/item/style/ICheckItem.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item.style 2 | 3 | import android.view.View 4 | import android.widget.CompoundButton 5 | import android.widget.ImageView 6 | import com.angcyo.dsladapter.* 7 | import com.angcyo.dsladapter.annotation.ItemInitEntryPoint 8 | import com.angcyo.dsladapter.item.IDslItemConfig 9 | import com.angcyo.item.R 10 | import com.angcyo.dsladapter.DslViewHolder 11 | 12 | /** 13 | * 14 | * Email:angcyo@126.com 15 | * @author angcyo 16 | * @date 2022/02/25 17 | * Copyright (c) 2020 ShenZhen Wayto Ltd. All rights reserved. 18 | */ 19 | interface ICheckItem : IAutoInitItem { 20 | 21 | /**配置项*/ 22 | var checkItemConfig: CheckItemConfig 23 | 24 | @ItemInitEntryPoint 25 | fun initCheckItem( 26 | itemHolder: DslViewHolder, 27 | itemPosition: Int, 28 | adapterItem: DslAdapterItem, 29 | payloads: List 30 | ) { 31 | val item = this 32 | itemHolder.view(checkItemConfig.itemCheckViewId)?.apply { 33 | when (this) { 34 | is ImageView -> setImageResource(checkItemConfig.itemCheckResId) 35 | is CompoundButton -> setButtonDrawable(checkItemConfig.itemCheckResId) 36 | else -> setBackgroundResource(checkItemConfig.itemCheckResId) 37 | } 38 | } 39 | 40 | //[DslAdapterItem] 41 | if (item is DslAdapterItem) { 42 | item.itemDslAdapter?.apply { 43 | if (itemSelectorHelper.selectorModel == ItemSelectorHelper.MODEL_NORMAL) { 44 | //开启多选模式 45 | multiModel() 46 | } 47 | } 48 | item.itemClick = this::onItemClick 49 | item.onItemSelectorChange = this::onItemSelectorChange 50 | 51 | //重新初始化一下Listener 52 | item._initItemListener(itemHolder) 53 | 54 | //状态 55 | itemHolder.selected(checkItemConfig.itemCheckViewId, item.itemIsSelected) 56 | } 57 | } 58 | 59 | /**点击事件的绑定*/ 60 | fun onItemClick(view: View) { 61 | val item = this 62 | if (item is DslAdapterItem) { 63 | //切换选中状态 64 | item.select { 65 | //不通知界面更新, 因为如果使用此方式更新界面, item原本的背景波纹效果会丢失 66 | notifyItemChanged = false 67 | } 68 | } 69 | } 70 | 71 | /**选中状态改变后, 通过本地更新的方式更新界面*/ 72 | fun onItemSelectorChange(selectorParams: SelectorParams) { 73 | val item = this 74 | if (item is DslAdapterItem) { 75 | item.itemViewHolder()?.apply { 76 | selected(checkItemConfig.itemCheckViewId, item.itemIsSelected) 77 | } 78 | } 79 | } 80 | } 81 | 82 | class CheckItemConfig : IDslItemConfig { 83 | 84 | /**需要操作的控件id[R.id.lib_check_view]*/ 85 | var itemCheckViewId: Int = R.id.lib_check_view 86 | 87 | /**选中状态提示资源*/ 88 | var itemCheckResId: Int = R.drawable.lib_check_selector 89 | 90 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/item/style/IDesItem.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item.style 2 | 3 | import com.angcyo.dsladapter.DslAdapterItem 4 | import com.angcyo.dsladapter.annotation.ItemInitEntryPoint 5 | import com.angcyo.dsladapter.item.IDslItemConfig 6 | import com.angcyo.item.R 7 | import com.angcyo.dsladapter.DslViewHolder 8 | 9 | /** 10 | * 11 | * Email:angcyo@126.com 12 | * @author angcyo 13 | * @date 2021/09/23 14 | * Copyright (c) 2020 ShenZhen Wayto Ltd. All rights reserved. 15 | */ 16 | interface IDesItem : IAutoInitItem { 17 | 18 | /**统一样式配置*/ 19 | var desItemConfig: DesItemConfig 20 | 21 | /**初始化*/ 22 | @ItemInitEntryPoint 23 | fun initDesItem(itemHolder: DslViewHolder, 24 | itemPosition: Int, 25 | adapterItem: DslAdapterItem, 26 | payloads: List) { 27 | itemHolder.tv(desItemConfig.itemDesViewId)?.apply { 28 | desItemConfig.itemDesStyle.updateStyle(this) 29 | } 30 | } 31 | 32 | fun configDesStyle(action: TextStyleConfig.() -> Unit) { 33 | desItemConfig.itemDesStyle.action() 34 | } 35 | } 36 | 37 | var IDesItem.itemDes: CharSequence? 38 | get() = desItemConfig.itemDes 39 | set(value) { 40 | desItemConfig.itemDes = value 41 | } 42 | 43 | class DesItemConfig : IDslItemConfig { 44 | 45 | var itemDesViewId: Int = R.id.lib_des_view 46 | 47 | /**文本*/ 48 | var itemDes: CharSequence? = null 49 | set(value) { 50 | field = value 51 | itemDesStyle.text = value 52 | } 53 | 54 | /**统一样式配置*/ 55 | var itemDesStyle = TextStyleConfig() 56 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/item/style/IEditItem.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item.style 2 | 3 | import android.text.InputFilter 4 | import android.text.InputType 5 | import com.angcyo.dsladapter.DslAdapterItem 6 | import com.angcyo.dsladapter.DslViewHolder 7 | import com.angcyo.dsladapter.annotation.ItemInitEntryPoint 8 | import com.angcyo.dsladapter.item.IDslItemConfig 9 | import com.angcyo.item.DslBaseEditItem 10 | import com.angcyo.item.R 11 | import com.angcyo.item.clearListeners 12 | import com.angcyo.item.onTextChange 13 | import com.angcyo.item.restoreSelection 14 | 15 | /** 16 | * 输入框item 17 | * Email:angcyo@126.com 18 | * @author angcyo 19 | * @date 2021/06/28 20 | * Copyright (c) 2020 angcyo. All rights reserved. 21 | */ 22 | 23 | /**文本改变通知回调*/ 24 | typealias TextChangeAction = (CharSequence) -> Unit 25 | 26 | interface IEditItem : IAutoInitItem { 27 | 28 | /**配置项*/ 29 | var editItemConfig: EditItemConfig 30 | 31 | /**初始化*/ 32 | @ItemInitEntryPoint 33 | fun initEditItem( 34 | itemHolder: DslViewHolder, 35 | itemPosition: Int, 36 | adapterItem: DslAdapterItem, 37 | payloads: List 38 | ) { 39 | itemHolder.ev(editItemConfig.itemEditTextViewId)?.apply { 40 | clearListeners() 41 | 42 | //[EditStyleConfig]样式初始化 43 | editItemConfig.itemEditTextStyle.updateStyle(this) 44 | 45 | onTextChange { 46 | editItemConfig._lastEditSelectionStart = selectionStart 47 | editItemConfig._lastEditSelectionEnd = selectionEnd 48 | 49 | editItemConfig.itemEditText = it 50 | } 51 | 52 | //放在最后监听, 防止首次setInputText, 就触发事件. 53 | onTextChange(shakeDelay = editItemConfig.itemTextChangeShakeDelay) { 54 | if (this@IEditItem is DslAdapterItem) { 55 | itemChanging = true 56 | } 57 | onItemEditTextChange(itemHolder, it) 58 | } 59 | 60 | restoreSelection( 61 | editItemConfig._lastEditSelectionStart, 62 | editItemConfig._lastEditSelectionEnd 63 | ) 64 | } 65 | } 66 | 67 | fun configEditTextStyle(action: EditStyleConfig.() -> Unit) { 68 | editItemConfig.itemEditTextStyle.action() 69 | } 70 | 71 | /**清除之前的监听*/ 72 | fun clearEditListeners(itemHolder: DslViewHolder) { 73 | itemHolder.ev(editItemConfig.itemEditTextViewId)?.clearListeners() 74 | } 75 | 76 | /**编辑的文本改变后*/ 77 | fun onItemEditTextChange(itemHolder: DslViewHolder, text: CharSequence) { 78 | editItemConfig.itemTextChangeAction?.invoke(text) 79 | } 80 | } 81 | 82 | var IEditItem.itemEditText: CharSequence? 83 | get() = editItemConfig.itemEditText 84 | set(value) { 85 | editItemConfig.itemEditText = value 86 | } 87 | 88 | var IEditItem.itemEditHint: CharSequence? 89 | get() = editItemConfig.itemEditTextStyle.hint 90 | set(value) { 91 | editItemConfig.itemEditTextStyle.hint = value 92 | } 93 | 94 | /** 95 | * 输入类型 96 | * [InputType.TYPE_CLASS_TEXT] 97 | * [InputType.TYPE_CLASS_NUMBER] 98 | * 99 | * [InputType.TYPE_TEXT_FLAG_MULTI_LINE] 100 | * 101 | * [InputType.TYPE_NUMBER_FLAG_DECIMAL] 102 | * [InputType.TYPE_NUMBER_FLAG_SIGNED] 103 | * */ 104 | var IEditItem.itemEditInputType: Int 105 | get() = editItemConfig.itemEditTextStyle.editInputType 106 | set(value) { 107 | editItemConfig.itemEditTextStyle.editInputType = value 108 | } 109 | 110 | 111 | var IEditItem.itemMaxInputLength: Int 112 | get() = editItemConfig.itemEditTextStyle.editMaxInputLength 113 | set(value) { 114 | editItemConfig.itemEditTextStyle.editMaxInputLength = value 115 | } 116 | 117 | /**输入过滤*/ 118 | var IEditItem.itemInputFilterList: MutableList 119 | get() = editItemConfig.itemEditTextStyle.editInputFilterList 120 | set(value) { 121 | editItemConfig.itemEditTextStyle.editInputFilterList = value 122 | } 123 | 124 | /**输入过滤*/ 125 | var IEditItem.itemEditDigits: String? 126 | get() = editItemConfig.itemEditTextStyle.editDigits 127 | set(value) { 128 | editItemConfig.itemEditTextStyle.editDigits = value 129 | } 130 | 131 | var IEditItem.itemTextChangeAction: TextChangeAction? 132 | get() = editItemConfig.itemTextChangeAction 133 | set(value) { 134 | editItemConfig.itemTextChangeAction = value 135 | } 136 | 137 | class EditItemConfig : IDslItemConfig { 138 | 139 | /**[R.id.lib_edit_view]*/ 140 | var itemEditTextViewId: Int = R.id.lib_edit_view 141 | 142 | /**输入框内容*/ 143 | var itemEditText: CharSequence? = null 144 | set(value) { 145 | field = value 146 | itemEditTextStyle.text = value 147 | } 148 | 149 | /**是否可编辑*/ 150 | var itemNoEditModel: Boolean? = null 151 | set(value) { 152 | field = value 153 | if (value == true) { 154 | itemEditTextStyle.hint = null 155 | } 156 | } 157 | 158 | /**统一样式配置*/ 159 | var itemEditTextStyle: EditStyleConfig = EditStyleConfig() 160 | 161 | /**文本改变*/ 162 | var itemTextChangeAction: TextChangeAction? = null 163 | 164 | /**文本改变去频限制, 负数表示不开启, 如果短时间内关闭界面了, 可能会获取不到最新的输入框数据*/ 165 | var itemTextChangeShakeDelay: Long = DslBaseEditItem.DEFAULT_INPUT_SHAKE_DELAY 166 | 167 | //用于恢复光标的位置 168 | var _lastEditSelectionStart: Int = -1 169 | 170 | var _lastEditSelectionEnd: Int = -1 171 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/item/style/ILabelItem.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item.style 2 | 3 | import com.angcyo.dsladapter.DslAdapterItem 4 | import com.angcyo.dsladapter.annotation.ItemInitEntryPoint 5 | import com.angcyo.dsladapter.item.IDslItemConfig 6 | import com.angcyo.item.R 7 | import com.angcyo.dsladapter.DslViewHolder 8 | 9 | /** 10 | * 带Label的item 11 | * Email:angcyo@126.com 12 | * @author angcyo 13 | * @date 2021/06/28 14 | * Copyright (c) 2020 angcyo. All rights reserved. 15 | */ 16 | interface ILabelItem : IAutoInitItem { 17 | 18 | /**统一样式配置*/ 19 | var labelItemConfig: LabelItemConfig 20 | 21 | /**初始化*/ 22 | @ItemInitEntryPoint 23 | fun initLabelItem( 24 | itemHolder: DslViewHolder, 25 | itemPosition: Int, 26 | adapterItem: DslAdapterItem, 27 | payloads: List 28 | ) { 29 | itemHolder.tv(labelItemConfig.itemLabelViewId)?.apply { 30 | labelItemConfig.itemLabelTextStyle.updateStyle(this) 31 | } 32 | } 33 | 34 | fun configLabelTextStyle(action: TextStyleConfig.() -> Unit) { 35 | labelItemConfig.itemLabelTextStyle.action() 36 | } 37 | } 38 | 39 | var ILabelItem.itemLabelText: CharSequence? 40 | get() = labelItemConfig.itemLabelText 41 | set(value) { 42 | labelItemConfig.itemLabelText = value 43 | } 44 | 45 | var ILabelItem.itemLabel: CharSequence? 46 | get() = labelItemConfig.itemLabelText 47 | set(value) { 48 | labelItemConfig.itemLabelText = value 49 | } 50 | 51 | /**label视图的最小宽度*/ 52 | var ILabelItem.itemLabelMinWidth: Int 53 | get() = labelItemConfig.itemLabelTextStyle.viewMinWidth 54 | set(value) { 55 | configLabelTextStyle { 56 | viewMinWidth = value 57 | } 58 | } 59 | 60 | class LabelItemConfig : IDslItemConfig { 61 | 62 | /**[R.id.lib_label_view]*/ 63 | var itemLabelViewId: Int = R.id.lib_label_view 64 | 65 | /**Label文本*/ 66 | var itemLabelText: CharSequence? = null 67 | set(value) { 68 | field = value 69 | itemLabelTextStyle.text = value 70 | } 71 | 72 | /**统一样式配置*/ 73 | var itemLabelTextStyle: TextStyleConfig = TextStyleConfig() 74 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/item/style/ISwitchItem.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item.style 2 | 3 | import com.angcyo.dsladapter.DslAdapterItem 4 | import com.angcyo.dsladapter.annotation.ItemInitEntryPoint 5 | import com.angcyo.dsladapter.item.IDslItemConfig 6 | import com.angcyo.github.SwitchButton 7 | import com.angcyo.item.R 8 | import com.angcyo.dsladapter.DslViewHolder 9 | 10 | /** 11 | * [com.angcyo.github.SwitchButton] 12 | * [com.angcyo.item.DslPropertySwitchItem] 13 | * [com.angcyo.item.DslSwitchInfoItem] 14 | * @author angcyo 15 | * @since 2022/06/08 16 | */ 17 | interface ISwitchItem : IAutoInitItem { 18 | 19 | /**统一样式配置*/ 20 | var switchItemConfig: SwitchItemConfig 21 | 22 | @ItemInitEntryPoint 23 | fun initSwitchItem( 24 | itemHolder: DslViewHolder, 25 | itemPosition: Int, 26 | adapterItem: DslAdapterItem, 27 | payloads: List 28 | ) { 29 | itemHolder.v(switchItemConfig.itemSwitchViewId)?.apply { 30 | setOnCheckedChangeListener(null) 31 | 32 | //刷新界面的时候, 不执行动画 33 | val old = isEnableEffect 34 | isEnableEffect = false 35 | isChecked = itemSwitchChecked 36 | isEnableEffect = old 37 | 38 | setOnCheckedChangeListener(object : SwitchButton.OnCheckedChangeListener { 39 | override fun onCheckedChanged(view: SwitchButton, isChecked: Boolean) { 40 | val checked = itemSwitchChecked 41 | itemSwitchChecked = isChecked 42 | if (checked != itemSwitchChecked) { 43 | if (this@ISwitchItem is DslAdapterItem) { 44 | itemChanging = true 45 | } 46 | switchItemConfig.itemSwitchChangedAction(itemSwitchChecked) 47 | } 48 | } 49 | }) 50 | } 51 | } 52 | 53 | /**config*/ 54 | fun configSwitchItem(action: SwitchItemConfig.() -> Unit) { 55 | switchItemConfig.action() 56 | } 57 | } 58 | 59 | var ISwitchItem.itemSwitchChecked: Boolean 60 | get() = switchItemConfig.itemSwitchChecked 61 | set(value) { 62 | switchItemConfig.itemSwitchChecked = value 63 | } 64 | 65 | var ISwitchItem.itemSwitchChangedAction: (checked: Boolean) -> Unit 66 | get() = switchItemConfig.itemSwitchChangedAction 67 | set(value) { 68 | switchItemConfig.itemSwitchChangedAction = value 69 | } 70 | 71 | class SwitchItemConfig : IDslItemConfig { 72 | 73 | /**[R.id.lib_switch_view]*/ 74 | var itemSwitchViewId: Int = R.id.lib_switch_view 75 | 76 | /**是否选中*/ 77 | var itemSwitchChecked = false 78 | 79 | /**状态回调, 提供一个可以完全覆盖的方法*/ 80 | var itemSwitchChangedAction: (checked: Boolean) -> Unit = { 81 | } 82 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/item/style/ITextInfoItem.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item.style 2 | 3 | import com.angcyo.dsladapter.DslAdapterItem 4 | import com.angcyo.dsladapter.annotation.ItemInitEntryPoint 5 | import com.angcyo.dsladapter.item.IDslItemConfig 6 | import com.angcyo.item.R 7 | import com.angcyo.dsladapter.DslViewHolder 8 | 9 | /** 10 | * 带Text的item 11 | * Email:angcyo@126.com 12 | * @author angcyo 13 | * @date 2021/07/16 14 | * Copyright (c) 2020 angcyo. All rights reserved. 15 | */ 16 | interface ITextInfoItem : IAutoInitItem { 17 | 18 | var textInfoItemConfig: TextInfoItemConfig 19 | 20 | /**初始化*/ 21 | @ItemInitEntryPoint 22 | fun initInfoTextItem( 23 | itemHolder: DslViewHolder, 24 | itemPosition: Int, 25 | adapterItem: DslAdapterItem, 26 | payloads: List 27 | ) { 28 | itemHolder.tv(textInfoItemConfig.itemInfoTextViewId)?.apply { 29 | textInfoItemConfig.itemInfoTextStyle.updateStyle(this) 30 | } 31 | } 32 | 33 | fun configInfoTextStyle(action: TextStyleConfig.() -> Unit) { 34 | textInfoItemConfig.itemInfoTextStyle.action() 35 | } 36 | } 37 | 38 | var ITextInfoItem.itemInfoText: CharSequence? 39 | get() = textInfoItemConfig.itemInfoText 40 | set(value) { 41 | textInfoItemConfig.itemInfoText = value 42 | } 43 | 44 | class TextInfoItemConfig : IDslItemConfig { 45 | /**[R.id.lib_text_view]*/ 46 | var itemInfoTextViewId: Int = R.id.lib_text_view 47 | 48 | /**条目文本*/ 49 | var itemInfoText: CharSequence? = null 50 | set(value) { 51 | field = value 52 | itemInfoTextStyle.text = value 53 | } 54 | 55 | /**统一样式配置*/ 56 | var itemInfoTextStyle: TextStyleConfig = TextStyleConfig() 57 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/item/style/ITextItem.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item.style 2 | 3 | import com.angcyo.dsladapter.DslAdapterItem 4 | import com.angcyo.dsladapter.DslViewHolder 5 | import com.angcyo.dsladapter.annotation.ItemInitEntryPoint 6 | import com.angcyo.dsladapter.item.IDslItemConfig 7 | import com.angcyo.item.R 8 | import com.angcyo.item._dimen 9 | import com.angcyo.widget.span.undefined_float 10 | 11 | /** 12 | * 13 | * Email:angcyo@126.com 14 | * @author angcyo 15 | * @date 2021/09/18 16 | * Copyright (c) 2020 ShenZhen Wayto Ltd. All rights reserved. 17 | */ 18 | interface ITextItem : IAutoInitItem { 19 | 20 | /**配置类 */ 21 | var textItemConfig: TextItemConfig 22 | 23 | /**初始化*/ 24 | @ItemInitEntryPoint 25 | fun initTextItem( 26 | itemHolder: DslViewHolder, 27 | itemPosition: Int, 28 | adapterItem: DslAdapterItem, 29 | payloads: List 30 | ) { 31 | itemHolder.tv(textItemConfig.itemTextViewId)?.apply { 32 | textItemConfig.itemTextStyle.updateStyle(this) 33 | } 34 | } 35 | 36 | fun configTextStyle(action: TextStyleConfig.() -> Unit) { 37 | textItemConfig.itemTextStyle.action() 38 | } 39 | 40 | /**加粗样式*/ 41 | fun boldStyle() { 42 | configTextStyle { 43 | textBold = true 44 | if (textSize == undefined_float) { 45 | textSize = _dimen(R.dimen.text_sub_size).toFloat() 46 | } 47 | } 48 | } 49 | } 50 | 51 | var ITextItem.itemText: CharSequence? 52 | get() = textItemConfig.itemText 53 | set(value) { 54 | textItemConfig.itemText = value 55 | } 56 | 57 | var ITextItem.itemHint: CharSequence? 58 | get() = textItemConfig.itemTextStyle.hint 59 | set(value) { 60 | textItemConfig.itemTextStyle.hint = value 61 | } 62 | 63 | class TextItemConfig : IDslItemConfig { 64 | 65 | /**[R.id.lib_text_view]*/ 66 | var itemTextViewId: Int = R.id.lib_text_view 67 | 68 | /**条目文本*/ 69 | var itemText: CharSequence? = null 70 | set(value) { 71 | field = value 72 | itemTextStyle.text = value 73 | } 74 | 75 | /**统一样式配置*/ 76 | var itemTextStyle: TextStyleConfig = TextStyleConfig() 77 | 78 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/item/style/ImageStyleConfig.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item.style 2 | 3 | import android.view.View 4 | import android.widget.ImageView 5 | 6 | /** 7 | * 图片控件样式 8 | * Email:angcyo@126.com 9 | * @author angcyo 10 | * @date 2021/09/23 11 | * Copyright (c) 2020 ShenZhen Wayto Ltd. All rights reserved. 12 | */ 13 | class ImageStyleConfig : ViewStyleConfig() { 14 | 15 | var imageScaleType: ImageView.ScaleType? = null 16 | 17 | override fun updateStyle(view: View) { 18 | super.updateStyle(view) 19 | 20 | if (view is ImageView) { 21 | // 22 | if (imageScaleType == null) { 23 | imageScaleType = view.scaleType 24 | } 25 | view.scaleType = imageScaleType 26 | 27 | // 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/item/style/TextStyleConfig.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item.style 2 | 3 | import android.content.res.ColorStateList 4 | import android.graphics.drawable.Drawable 5 | import android.util.TypedValue 6 | import android.view.Gravity 7 | import android.view.View 8 | import android.widget.TextView 9 | import com.angcyo.dsladapter.UndefinedDrawable 10 | import com.angcyo.dsladapter.undefined_size 11 | import com.angcyo.dsladapter.visible 12 | import com.angcyo.item.bottomIco 13 | import com.angcyo.item.leftIco 14 | import com.angcyo.item.rightIco 15 | import com.angcyo.item.setBoldText 16 | import com.angcyo.item.topIco 17 | import com.angcyo.widget.span.undefined_color 18 | import com.angcyo.widget.span.undefined_float 19 | 20 | /** 21 | * 文本样式配置 22 | * Email:angcyo@126.com 23 | * @author angcyo 24 | * @date 2020/06/09 25 | * Copyright (c) 2020 ShenZhen Wayto Ltd. All rights reserved. 26 | */ 27 | 28 | open class TextStyleConfig : ViewStyleConfig() { 29 | 30 | /**显示的文本内容*/ 31 | var text: CharSequence? = null 32 | 33 | /**当[text]为null时, 隐藏控件*/ 34 | var goneOnTextEmpty: Boolean = false 35 | 36 | /**提示文本内容*/ 37 | var hint: CharSequence? = null 38 | var textBold: Boolean = false 39 | var textColor: Int = undefined_color 40 | var textColors: ColorStateList? = null 41 | 42 | var textSize: Float = undefined_float 43 | var textGravity: Int = Gravity.LEFT or Gravity.CENTER_VERTICAL 44 | 45 | /**四向图标, 需要指定bounds*/ 46 | var leftDrawable: Drawable? = UndefinedDrawable() 47 | var topDrawable: Drawable? = UndefinedDrawable() 48 | var rightDrawable: Drawable? = UndefinedDrawable() 49 | var bottomDrawable: Drawable? = UndefinedDrawable() 50 | var drawablePadding = undefined_size 51 | 52 | /**生效*/ 53 | override fun updateStyle(view: View) { 54 | super.updateStyle(view) 55 | 56 | if (view is TextView) { 57 | 58 | if (text == null) { 59 | text = view.text 60 | } 61 | 62 | if (hint == null) { 63 | hint = view.hint 64 | } 65 | 66 | with(view) { 67 | text = this@TextStyleConfig.text 68 | 69 | //[TextView]设置最小宽度和最小高度 70 | if (viewMinWidth != undefined_size) { 71 | minWidth = viewMinWidth 72 | 73 | } 74 | if (viewMinHeight != undefined_size) { 75 | minHeight = viewMinHeight 76 | } 77 | 78 | if (goneOnTextEmpty) { 79 | visible(!this@TextStyleConfig.text.isNullOrEmpty()) 80 | } 81 | 82 | //兼容 83 | view.hint = hint 84 | 85 | gravity = textGravity 86 | 87 | setBoldText(textBold) 88 | 89 | //颜色, 防止复用. 所以在未指定的情况下, 要获取默认的颜色. 90 | val colors = when { 91 | this@TextStyleConfig.textColors != null -> { 92 | this@TextStyleConfig.textColors 93 | } 94 | 95 | textColor != undefined_color -> { 96 | ColorStateList.valueOf(textColor) 97 | } 98 | 99 | else -> { 100 | textColors 101 | } 102 | } 103 | if (colors != this@TextStyleConfig.textColors) { 104 | this@TextStyleConfig.textColors = colors 105 | } 106 | setTextColor(colors) 107 | 108 | //字体大小同理. 109 | val size = if (this@TextStyleConfig.textSize != undefined_float) { 110 | this@TextStyleConfig.textSize 111 | } else { 112 | textSize 113 | } 114 | this@TextStyleConfig.textSize = size 115 | setTextSize(TypedValue.COMPLEX_UNIT_PX, size) 116 | 117 | //padding 118 | if (drawablePadding == undefined_size) { 119 | drawablePadding = compoundDrawablePadding 120 | } 121 | compoundDrawablePadding = drawablePadding 122 | 123 | //四向图标修改 124 | if (leftDrawable is UndefinedDrawable) { 125 | leftDrawable = leftIco() 126 | } 127 | if (topDrawable is UndefinedDrawable) { 128 | topDrawable = topIco() 129 | } 130 | if (rightDrawable is UndefinedDrawable) { 131 | rightDrawable = rightIco() 132 | } 133 | if (bottomDrawable is UndefinedDrawable) { 134 | bottomDrawable = bottomIco() 135 | } 136 | setCompoundDrawablesRelative( 137 | leftDrawable, 138 | topDrawable, 139 | rightDrawable, 140 | bottomDrawable 141 | ) 142 | } 143 | } 144 | } 145 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/item/style/ViewStyleConfig.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item.style 2 | 3 | import android.graphics.drawable.Drawable 4 | import android.os.Build 5 | import android.view.Gravity 6 | import android.view.View 7 | import android.widget.FrameLayout 8 | import androidx.constraintlayout.widget.ConstraintLayout 9 | import com.angcyo.dsladapter.UndefinedDrawable 10 | import com.angcyo.dsladapter.setBgDrawable 11 | import com.angcyo.dsladapter.setWidthHeight 12 | import com.angcyo.dsladapter.undefined_size 13 | import com.angcyo.widget.span.undefined_int 14 | 15 | /** 16 | * View基础样式配置 17 | * Email:angcyo@126.com 18 | * @author angcyo 19 | * @date 2020/06/09 20 | * Copyright (c) 2020 ShenZhen Wayto Ltd. All rights reserved. 21 | */ 22 | 23 | open class ViewStyleConfig { 24 | 25 | /**限制最小宽高*/ 26 | var viewWidth: Int = undefined_size 27 | var viewMinWidth: Int = undefined_size 28 | 29 | /**指定宽高*/ 30 | var viewHeight: Int = undefined_size 31 | var viewMinHeight: Int = undefined_size 32 | 33 | /**视图可见性[visibility]*/ 34 | var viewVisibility: Int = undefined_int 35 | 36 | /**padding值*/ 37 | var paddingLeft: Int = undefined_size 38 | var paddingRight: Int = undefined_size 39 | var paddingTop: Int = undefined_size 40 | var paddingBottom: Int = undefined_size 41 | 42 | /**背景*/ 43 | var backgroundDrawable: Drawable? = UndefinedDrawable() 44 | 45 | /**部分布局支持*/ 46 | var layoutGravity: Int = Gravity.NO_GRAVITY 47 | 48 | /** 49 | * 需要parent为[ConstraintLayout] 50 | * [androidx.constraintlayout.widget.ConstraintLayout.LayoutParams.dimensionRatio]*/ 51 | var viewDimensionRatio: String? = null 52 | 53 | /**更新样式*/ 54 | open fun updateStyle(view: View) { 55 | with(view) { 56 | //初始化默认值 57 | if (this@ViewStyleConfig.paddingLeft == undefined_size) { 58 | this@ViewStyleConfig.paddingLeft = paddingLeft 59 | } 60 | if (this@ViewStyleConfig.paddingRight == undefined_size) { 61 | this@ViewStyleConfig.paddingRight = paddingRight 62 | } 63 | if (this@ViewStyleConfig.paddingTop == undefined_size) { 64 | this@ViewStyleConfig.paddingTop = paddingTop 65 | } 66 | if (this@ViewStyleConfig.paddingBottom == undefined_size) { 67 | this@ViewStyleConfig.paddingBottom = paddingBottom 68 | } 69 | 70 | //可见性 71 | if (viewVisibility == undefined_int) { 72 | viewVisibility = visibility 73 | } 74 | visibility = viewVisibility 75 | 76 | //设置 77 | setPadding( 78 | this@ViewStyleConfig.paddingLeft, 79 | this@ViewStyleConfig.paddingTop, 80 | this@ViewStyleConfig.paddingRight, 81 | this@ViewStyleConfig.paddingBottom 82 | ) 83 | 84 | val lp = layoutParams 85 | 86 | if (backgroundDrawable is UndefinedDrawable) { 87 | backgroundDrawable = background 88 | } 89 | setBgDrawable(backgroundDrawable) 90 | 91 | //初始化默认值 92 | if (viewMinWidth == undefined_size && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { 93 | viewMinWidth = minimumWidth 94 | } 95 | if (viewMinHeight == undefined_size && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { 96 | viewMinHeight = minimumHeight 97 | } 98 | //设置 99 | if (viewMinWidth != undefined_size) { 100 | minimumWidth = viewMinWidth 101 | when (view) { 102 | is ConstraintLayout -> view.minWidth = viewMinWidth 103 | } 104 | } 105 | if (viewMinHeight != undefined_size) { 106 | minimumHeight = viewMinHeight 107 | when (view) { 108 | is ConstraintLayout -> view.minHeight = viewMinHeight 109 | } 110 | } 111 | 112 | //初始化默认值 113 | if (viewWidth == undefined_size) { 114 | viewWidth = lp.width 115 | } 116 | if (viewHeight == undefined_size) { 117 | viewHeight = lp.height 118 | } 119 | //设置 120 | setWidthHeight(viewWidth, viewHeight) 121 | if (lp is ConstraintLayout.LayoutParams) { 122 | if (viewDimensionRatio == null) { 123 | viewDimensionRatio = lp.dimensionRatio 124 | } else { 125 | lp.dimensionRatio = viewDimensionRatio 126 | layoutParams = lp 127 | } 128 | } 129 | 130 | //Gravity 131 | if (lp is FrameLayout.LayoutParams) { 132 | val oldGravity = lp.gravity 133 | if (layoutGravity == Gravity.NO_GRAVITY) { 134 | layoutGravity = oldGravity 135 | } 136 | lp.gravity = layoutGravity 137 | if (oldGravity != layoutGravity) { 138 | layoutParams = lp 139 | } 140 | } 141 | } 142 | } 143 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/widget/BadgeTextView.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.widget 2 | 3 | import android.content.Context 4 | import android.graphics.Canvas 5 | import android.util.AttributeSet 6 | import androidx.appcompat.widget.AppCompatTextView 7 | import com.angcyo.drawable.DslAttrBadgeDrawable 8 | import com.angcyo.item.isNotSpecified 9 | 10 | /** 11 | * 单纯的用来绘制角标的控件 12 | * 使用属性[app:r_badge_text="xxx"]设置角标 13 | * 14 | * badgePaddingLeft 15 | * badgePaddingRight 16 | * badgePaddingTop 17 | * badgePaddingBottom 18 | * 19 | * Email:angcyo@126.com 20 | * @author angcyo 21 | * @date 2021/09/23 22 | * Copyright (c) 2020 ShenZhen Wayto Ltd. All rights reserved. 23 | */ 24 | class BadgeTextView : AppCompatTextView, IBadgeView { 25 | 26 | /**角标绘制*/ 27 | override var dslBadeDrawable = DslAttrBadgeDrawable() 28 | 29 | constructor(context: Context) : super(context) { 30 | initAttribute(context, null) 31 | } 32 | 33 | constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) { 34 | initAttribute(context, attrs) 35 | } 36 | 37 | constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super( 38 | context, 39 | attrs, 40 | defStyleAttr 41 | ) { 42 | initAttribute(context, attrs) 43 | } 44 | 45 | private fun initAttribute(context: Context, attributeSet: AttributeSet?) { 46 | dslBadeDrawable.apply { 47 | badgeOffsetX = 0 48 | badgeOffsetY = 0 49 | initAttribute(context, attributeSet) 50 | callback = this@BadgeTextView 51 | dslGravity.gravityRelativeCenter = false 52 | } 53 | } 54 | 55 | override fun onDraw(canvas: Canvas) { 56 | super.onDraw(canvas) 57 | 58 | dslBadeDrawable.apply { 59 | setBounds(0, 0, measuredWidth, measuredHeight) 60 | draw(canvas) 61 | } 62 | } 63 | 64 | /*override fun setText(text: CharSequence?, type: BufferType?) { 65 | super.setText(text, type) 66 | //在构造方法中调用此方法[dslBadeDrawable]为空 67 | dslBadeDrawable?.badgeText = text.toString() 68 | }*/ 69 | 70 | /**角标的文本, 空字符串会绘制成小圆点*/ 71 | fun updateBadge(text: String? = null, action: DslAttrBadgeDrawable.() -> Unit = {}) { 72 | dslBadeDrawable.apply { 73 | drawBadge = true 74 | //badgeGravity = Gravity.TOP or Gravity.RIGHT 75 | badgeText = text 76 | //badgeCircleRadius 77 | //badgeOffsetY = 4 * dpi 78 | //cornerRadius(25 * dp) 79 | action() 80 | } 81 | postInvalidateOnAnimation() 82 | } 83 | 84 | override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { 85 | //of kotlin 86 | //val widthSize = MeasureSpec.getSize(widthMeasureSpec) 87 | val widthMode = MeasureSpec.getMode(widthMeasureSpec) 88 | //val heightSize = MeasureSpec.getSize(heightMeasureSpec) 89 | val heightMode = MeasureSpec.getMode(heightMeasureSpec) 90 | 91 | if (widthMode.isNotSpecified() && heightMode.isNotSpecified()) { 92 | setMeasuredDimension( 93 | dslBadeDrawable.intrinsicWidth + paddingLeft + paddingRight, 94 | dslBadeDrawable.intrinsicHeight + paddingTop + paddingBottom 95 | ) 96 | } else { 97 | super.onMeasure(widthMeasureSpec, heightMeasureSpec) 98 | } 99 | } 100 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/widget/CharLengthFilter.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.widget 2 | 3 | import android.text.InputFilter 4 | import android.text.Spanned 5 | 6 | /** 7 | * 使用英文字符数过滤, 一个汉字等于2个英文, 一个emoji表情等于2个汉字 8 | * Created by angcyo on 2018-08-10. 9 | * Email:angcyo@126.com 10 | */ 11 | class CharLengthFilter(var maxLen: Int) : InputFilter { 12 | 13 | companion object { 14 | const val MAX_CHAR: Char = 255.toChar() 15 | } 16 | 17 | /** 18 | * 将 dest 字符中, 的dstart 位置到 dend 位置的字符串, 19 | * 替换成 source 字符中, 的start 位置到 end 对应的字符串 20 | */ 21 | override fun filter( 22 | source: CharSequence, 23 | start: Int, 24 | end: Int, 25 | dest: Spanned, 26 | dstart: Int, 27 | dend: Int 28 | ): CharSequence? { 29 | var dIndex = 0 30 | var count = 0 31 | var dCount = 0 //dest 中, 需要替换掉多少个char 32 | //当前已经存在char数量 33 | while (count <= maxLen && dIndex < dest.length) { 34 | val c = dest[dIndex++] 35 | if (c <= MAX_CHAR) { 36 | count += 1 37 | if (dIndex in dstart until dend) { 38 | dCount += 1 39 | } 40 | } else { 41 | if (dIndex in dstart until dend) { 42 | dCount += 1 43 | } 44 | count += 2 45 | } 46 | } 47 | count -= dCount 48 | if (count > maxLen) { 49 | return dest.subSequence(0, dIndex - 1) 50 | } 51 | //本次需要输入的char数量 52 | var sIndex = 0 53 | while (count <= maxLen && sIndex < source.length) { 54 | val c = source[sIndex++] 55 | count = if (c <= MAX_CHAR) { 56 | count + 1 57 | } else { 58 | count + 2 59 | } 60 | } 61 | return if (count > maxLen) { //已经存在的char长度, + 输入的char长度, 大于限制长度 62 | //越界 63 | sIndex-- 64 | source.subSequence(0, sIndex) 65 | } else { // keep original 66 | null 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/widget/IBadgeView.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.widget 2 | 3 | import com.angcyo.drawable.DslAttrBadgeDrawable 4 | 5 | /** 6 | * 7 | * Email:angcyo@126.com 8 | * @author angcyo 9 | * @date 2021/09/23 10 | * Copyright (c) 2020 ShenZhen Wayto Ltd. All rights reserved. 11 | */ 12 | interface IBadgeView { 13 | var dslBadeDrawable: DslAttrBadgeDrawable 14 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/widget/ITouchDelegate.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.widget 2 | 3 | import android.view.MotionEvent 4 | 5 | /** 6 | * 7 | * Email:angcyo@126.com 8 | * @author angcyo 9 | * @date 2021/11/19 10 | * Copyright (c) 2020 ShenZhen Wayto Ltd. All rights reserved. 11 | */ 12 | interface ITouchDelegate { 13 | fun getTouchActionDelegate(): TouchActionDelegate 14 | } 15 | 16 | fun ITouchDelegate.onDispatchTouchEventAction(action: (ev: MotionEvent) -> Unit): TouchListener { 17 | val listener = object : TouchListener { 18 | override fun onDispatchTouchEventAction(ev: MotionEvent) { 19 | action(ev) 20 | } 21 | } 22 | getTouchActionDelegate()?.touchListener?.add(listener) 23 | return listener 24 | } 25 | 26 | fun ITouchDelegate.onInterceptTouchEventAction(action: (ev: MotionEvent) -> Unit): TouchListener { 27 | val listener = object : TouchListener { 28 | override fun onInterceptTouchEventAction(ev: MotionEvent) { 29 | action(ev) 30 | } 31 | } 32 | getTouchActionDelegate()?.touchListener?.add(listener) 33 | return listener 34 | } 35 | 36 | fun ITouchDelegate.onTouchEventAction(action: (ev: MotionEvent) -> Unit): TouchListener { 37 | val listener = object : TouchListener { 38 | override fun onTouchEventAction(ev: MotionEvent) { 39 | action(ev) 40 | } 41 | } 42 | getTouchActionDelegate()?.touchListener?.add(listener) 43 | return listener 44 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/widget/ITouchHold.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.widget 2 | 3 | /** 4 | * 5 | * Email:angcyo@126.com 6 | * @author angcyo 7 | * @date 2021/06/28 8 | * Copyright (c) 2020 ShenZhen Wayto Ltd. All rights reserved. 9 | */ 10 | interface ITouchHold { 11 | /**手势是否为松开*/ 12 | var isTouchHold: Boolean 13 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/widget/TouchActionDelegate.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.widget 2 | 3 | import android.view.MotionEvent 4 | 5 | /** 6 | * 手势代理 7 | * Email:angcyo@126.com 8 | * @author angcyo 9 | * @date 2021/11/19 10 | * Copyright (c) 2020 ShenZhen Wayto Ltd. All rights reserved. 11 | */ 12 | open class TouchActionDelegate { 13 | 14 | val touchListener = mutableSetOf() 15 | 16 | fun dispatchTouchEvent(ev: MotionEvent) { 17 | touchListener.forEach { 18 | it.onDispatchTouchEventAction(ev) 19 | } 20 | } 21 | 22 | fun onInterceptTouchEvent(ev: MotionEvent) { 23 | touchListener.forEach { 24 | it.onInterceptTouchEventAction(ev) 25 | } 26 | } 27 | 28 | fun onTouchEvent(ev: MotionEvent) { 29 | touchListener.forEach { 30 | it.onTouchEventAction(ev) 31 | } 32 | } 33 | 34 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/widget/TouchListener.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.widget 2 | 3 | import android.view.MotionEvent 4 | 5 | /** 6 | * Touch监听 7 | * Email:angcyo@126.com 8 | * @author angcyo 9 | * @date 2021/11/19 10 | * Copyright (c) 2020 ShenZhen Wayto Ltd. All rights reserved. 11 | */ 12 | interface TouchListener { 13 | 14 | fun onDispatchTouchEventAction(ev: MotionEvent) { 15 | 16 | } 17 | 18 | fun onInterceptTouchEventAction(ev: MotionEvent) { 19 | 20 | } 21 | 22 | fun onTouchEventAction(ev: MotionEvent) { 23 | 24 | } 25 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/widget/ViewGroupEx.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.widget 2 | 3 | import android.view.LayoutInflater 4 | import android.view.View 5 | import android.view.ViewGroup 6 | import androidx.annotation.IdRes 7 | import com.angcyo.dsladapter.size 8 | import com.angcyo.item.R 9 | import kotlin.math.absoluteValue 10 | import kotlin.math.min 11 | 12 | /** 13 | * Kotlin ViewGroup的扩展 14 | * Created by angcyo on 2017-07-26. 15 | */ 16 | 17 | fun View?.find(@IdRes id: Int): T? { 18 | return this?.findViewById(id) 19 | } 20 | 21 | fun ViewGroup.resetChild( 22 | list: List?, 23 | layoutId: Int, 24 | init: (itemView: View, item: T, itemIndex: Int) -> Unit = { _, _, _ -> } 25 | ) { 26 | resetChild(list.size(), layoutId) { itemView, itemIndex -> 27 | val item = list!!.get(itemIndex) 28 | init(itemView, item, itemIndex) 29 | } 30 | } 31 | 32 | fun ViewGroup.resetChild( 33 | size: Int, 34 | layoutId: Int, 35 | init: (itemView: View, itemIndex: Int) -> Unit = { _, _ -> } 36 | ) { 37 | //如果布局id不一样, 说明child不一样, 需要remove 38 | for (index in childCount - 1 downTo 0) { 39 | val tag = getChildAt(index).getTag(R.id.tag) 40 | if (tag == null || (tag is Int && tag != layoutId)) { 41 | removeViewAt(index) 42 | } 43 | } 44 | 45 | resetChildCount(size) { childIndex, childView -> 46 | if (childView == null) { 47 | val itemView = LayoutInflater.from(context).inflate(layoutId, this, false) 48 | itemView.setTag(R.id.tag, layoutId) 49 | itemView 50 | } else { 51 | childView 52 | } 53 | } 54 | 55 | for (i in 0 until size) { 56 | init(getChildAt(i), i) 57 | } 58 | } 59 | 60 | /**将子View的数量, 重置到指定的数量*/ 61 | fun ViewGroup.resetChildCount( 62 | newSize: Int, 63 | createOrInitView: (childIndex: Int, childView: View?) -> View 64 | ) { 65 | val oldSize = childCount 66 | val count = newSize - oldSize 67 | if (count > 0) { 68 | //需要补充子View 69 | for (i in 0 until count) { 70 | addView(createOrInitView.invoke(oldSize + i, null)) 71 | } 72 | } else if (count < 0) { 73 | //需要移除子View 74 | for (i in 0 until count.absoluteValue) { 75 | removeViewAt(oldSize - 1 - i) 76 | } 77 | } 78 | 79 | //初始化 80 | for (i in 0 until min(oldSize, newSize)) { 81 | createOrInitView.invoke(i, getChildAt(i)) 82 | } 83 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/widget/recycler/GridLayoutManagerWrap.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.widget.recycler 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import androidx.recyclerview.widget.GridLayoutManager 6 | import androidx.recyclerview.widget.RecyclerView 7 | 8 | /** 9 | * 10 | * Email:angcyo@126.com 11 | * @author angcyo 12 | * @date 2020/01/02 13 | * Copyright (c) 2019 ShenZhen O&M Cloud Co., Ltd. All rights reserved. 14 | */ 15 | class GridLayoutManagerWrap : GridLayoutManager { 16 | 17 | constructor(context: Context, spanCount: Int) : super(context, spanCount) 18 | 19 | constructor( 20 | context: Context, 21 | attrs: AttributeSet?, 22 | defStyleAttr: Int, 23 | defStyleRes: Int 24 | ) : super(context, attrs, defStyleAttr, defStyleRes) 25 | 26 | constructor( 27 | context: Context, 28 | spanCount: Int, 29 | orientation: Int, 30 | reverseLayout: Boolean 31 | ) : super(context, spanCount, orientation, reverseLayout) 32 | 33 | override fun onLayoutChildren( 34 | recycler: RecyclerView.Recycler, 35 | state: RecyclerView.State 36 | ) { 37 | try { 38 | super.onLayoutChildren(recycler, state) 39 | } catch (e: Exception) { 40 | e.printStackTrace() 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/widget/recycler/LinearLayoutManagerWrap.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.widget.recycler 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import androidx.recyclerview.widget.LinearLayoutManager 6 | import androidx.recyclerview.widget.RecyclerView 7 | 8 | /** 9 | * 10 | * Email:angcyo@126.com 11 | * @author angcyo 12 | * @date 2020/01/02 13 | * Copyright (c) 2019 ShenZhen O&M Cloud Co., Ltd. All rights reserved. 14 | */ 15 | 16 | class LinearLayoutManagerWrap : LinearLayoutManager { 17 | 18 | constructor(context: Context) : super(context) 19 | 20 | constructor( 21 | context: Context, 22 | orientation: Int = RecyclerView.VERTICAL 23 | ) : super(context, orientation, false) 24 | 25 | constructor( 26 | context: Context, 27 | orientation: Int, 28 | reverseLayout: Boolean 29 | ) : super(context, orientation, reverseLayout) 30 | 31 | constructor( 32 | context: Context, 33 | attrs: AttributeSet?, 34 | defStyleAttr: Int, 35 | defStyleRes: Int 36 | ) : super(context, attrs, defStyleAttr, defStyleRes) 37 | 38 | override fun onLayoutChildren(recycler: RecyclerView.Recycler, state: RecyclerView.State) { 39 | try { 40 | super.onLayoutChildren(recycler, state) 41 | } catch (e: Exception) { 42 | e.printStackTrace() 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/widget/recycler/ScrollPositionConfig.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.widget.recycler 2 | 3 | import androidx.recyclerview.widget.RecyclerView 4 | 5 | /** 6 | * 记录[RecyclerView]的滚动位置状态 7 | * Email:angcyo@126.com 8 | * @author angcyo 9 | * @date 2020/03/19 10 | * Copyright (c) 2019 ShenZhen O&M Cloud Co., Ltd. All rights reserved. 11 | */ 12 | 13 | data class ScrollPositionConfig( 14 | //位置 15 | var adapterPosition: Int = RecyclerView.NO_POSITION, 16 | 17 | //上下距离 18 | var left: Int = 0, 19 | var top: Int = 0 20 | ) -------------------------------------------------------------------------------- /dslitem/src/main/java/com/angcyo/widget/recycler/StaggeredGridLayoutManagerWrap.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.widget.recycler 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import androidx.recyclerview.widget.RecyclerView 6 | import androidx.recyclerview.widget.StaggeredGridLayoutManager 7 | 8 | /** 9 | * 10 | * Email:angcyo@126.com 11 | * @author angcyo 12 | * @date 2020/01/02 13 | * Copyright (c) 2019 ShenZhen O&M Cloud Co., Ltd. All rights reserved. 14 | */ 15 | 16 | class StaggeredGridLayoutManagerWrap : StaggeredGridLayoutManager { 17 | 18 | constructor(spanCount: Int, orientation: Int) : super(spanCount, orientation) 19 | 20 | constructor( 21 | context: Context, 22 | attrs: AttributeSet?, 23 | defStyleAttr: Int, 24 | defStyleRes: Int 25 | ) : super(context, attrs, defStyleAttr, defStyleRes) 26 | 27 | override fun onLayoutChildren( 28 | recycler: RecyclerView.Recycler, 29 | state: RecyclerView.State 30 | ) { 31 | try { 32 | super.onLayoutChildren(recycler, state) 33 | } catch (e: Exception) { 34 | e.printStackTrace() 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /dslitem/src/main/res/drawable-anydpi/lib_audio_cover_tip.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /dslitem/src/main/res/drawable-anydpi/lib_audio_tip.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /dslitem/src/main/res/drawable-anydpi/lib_check_checked.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /dslitem/src/main/res/drawable-anydpi/lib_check_normal.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /dslitem/src/main/res/drawable-anydpi/lib_icon_edit_tip.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /dslitem/src/main/res/drawable-anydpi/lib_image_remove.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /dslitem/src/main/res/drawable-anydpi/lib_image_tip.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 15 | 16 | -------------------------------------------------------------------------------- /dslitem/src/main/res/drawable-anydpi/lib_video_cover_tip.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /dslitem/src/main/res/drawable-anydpi/lib_video_tip.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 15 | 16 | -------------------------------------------------------------------------------- /dslitem/src/main/res/drawable-v21/lib_bg2_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | -------------------------------------------------------------------------------- /dslitem/src/main/res/drawable-v21/lib_bg_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | -------------------------------------------------------------------------------- /dslitem/src/main/res/drawable-v21/lib_ripple_shape.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | -------------------------------------------------------------------------------- /dslitem/src/main/res/drawable/lib_bottom_line_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /dslitem/src/main/res/drawable/lib_check_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /dslitem/src/main/res/drawable/lib_dark_bottom_line_shape.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /dslitem/src/main/res/drawable/lib_duration_bg_shape.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | -------------------------------------------------------------------------------- /dslitem/src/main/res/drawable/lib_image_remove_circle_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /dslitem/src/main/res/drawable/lib_remove_circle_shape.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /dslitem/src/main/res/drawable/lib_theme_bottom_line_shape.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /dslitem/src/main/res/drawable/lib_theme_circle_shape.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /dslitem/src/main/res/drawable/lib_theme_press_circle_shape.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /dslitem/src/main/res/layout/dsl_bottom_button_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 24 | 25 | -------------------------------------------------------------------------------- /dslitem/src/main/res/layout/dsl_bottom_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 17 | 18 | -------------------------------------------------------------------------------- /dslitem/src/main/res/layout/dsl_button_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 16 | 17 | -------------------------------------------------------------------------------- /dslitem/src/main/res/layout/dsl_edit_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 15 | 16 | -------------------------------------------------------------------------------- /dslitem/src/main/res/layout/dsl_extent_switch_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 18 | -------------------------------------------------------------------------------- /dslitem/src/main/res/layout/dsl_extent_text_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 23 | -------------------------------------------------------------------------------- /dslitem/src/main/res/layout/dsl_grid_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 23 | 24 | 36 | 37 | -------------------------------------------------------------------------------- /dslitem/src/main/res/layout/dsl_info_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 30 | 31 | 42 | 43 | -------------------------------------------------------------------------------- /dslitem/src/main/res/layout/dsl_label_edit_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 17 | 18 | 26 | 27 | 35 | 36 | 43 | 44 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /dslitem/src/main/res/layout/dsl_label_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | -------------------------------------------------------------------------------- /dslitem/src/main/res/layout/dsl_label_text_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 21 | 22 | 35 | 36 | -------------------------------------------------------------------------------- /dslitem/src/main/res/layout/dsl_nested_recycler_item.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /dslitem/src/main/res/layout/dsl_text_item.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /dslitem/src/main/res/layout/layout_check.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /dslitem/src/main/res/layout/lib_tab_item_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 23 | 24 | 37 | 38 | 48 | 49 | -------------------------------------------------------------------------------- /dslitem/src/main/res/values/attr_badge_view.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 | -------------------------------------------------------------------------------- /dslitem/src/main/res/values/attr_dsl_recycler_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /dslitem/src/main/res/values/item_ids.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /dslitem/src/main/res/values/item_styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 75dp 5 | 2dp 6 | 1dp 7 | 8 | 9 | 50dp 10 | 11 | 20dp 12 | 13 | @dimen/text_assist_size 14 | 15 | 50dp 16 | 17 | #C3C7CF 18 | 19 | 29 | 30 | 40 | 41 | 48 | 49 | 50 | 59 | 60 | 63 | 64 | -------------------------------------------------------------------------------- /dslitem/src/main/res/values/switch_button_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 | -------------------------------------------------------------------------------- /dslitem2/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /dslitem2/README.md: -------------------------------------------------------------------------------- 1 | # dslitem 2 | 2020-01-01 3 | 4 | 常用 `DslItem`, 如果此库丰富了, 那么UI, 就是`乐高`拼出来的. 5 | 6 | ```kotlin 7 | renderDslAdapter{ 8 | dslItem1() 9 | dslItem2() 10 | dslItem3() 11 | ... 12 | dslItemX() 13 | dslItemY() 14 | dslItemZ() 15 | } 16 | ``` -------------------------------------------------------------------------------- /dslitem2/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'kotlin-android' 3 | 4 | android { 5 | compileSdk Integer.parseInt(C_SDK) 6 | 7 | defaultConfig { 8 | vectorDrawables.useSupportLibrary = true 9 | 10 | minSdk Integer.parseInt(M_SDK) 11 | targetSdk Integer.parseInt(T_SDK) 12 | 13 | consumerProguardFiles 'consumer-rules.pro' 14 | } 15 | namespace 'com.angcyo.item2' 16 | } 17 | 18 | dependencies { 19 | api project(":dslitem") 20 | 21 | //https://jcenter.bintray.com/rouchuan/viewpagerlayoutmanager/viewpagerlayoutmanager/ 22 | //https://github.com/leochuan/ViewPagerLayoutManager 23 | //https://github.com/angcyo/ViewPagerLayoutManager 24 | //api 'rouchuan.viewpagerlayoutmanager:viewpagerlayoutmanager:2.0.22' 25 | api 'com.github.angcyo:ViewPagerLayoutManager:2.1.3' 26 | 27 | //https://mvnrepository.com/artifact/androidx.appcompat/appcompat 28 | implementation 'androidx.appcompat:appcompat:1.6.1' 29 | } 30 | -------------------------------------------------------------------------------- /dslitem2/consumer-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angcyo/DslItem/92c5a7c665636c7af4c1f497c41657653ae80326/dslitem2/consumer-rules.pro -------------------------------------------------------------------------------- /dslitem2/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 | -------------------------------------------------------------------------------- /dslitem2/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /dslitem2/src/main/java/com/angcyo/item2/DslBannerItem.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item2 2 | 3 | import android.widget.LinearLayout 4 | import androidx.recyclerview.widget.RecyclerView 5 | import com.angcyo.dsladapter.DslAdapterItem 6 | import com.angcyo.dsladapter.DslViewHolder 7 | import com.angcyo.item.DslNestedRecyclerItem 8 | import com.angcyo.item.base.LibInitProvider 9 | import com.angcyo.item2.widget.recycler.DrawableIndicator 10 | import com.leochuan.ScaleLayoutManager 11 | import com.leochuan.ViewPagerLayoutManager 12 | 13 | /** 14 | * 轮播图切换item 15 | * Email:angcyo@126.com 16 | * @author angcyo 17 | * @date 2020/03/18 18 | * Copyright (c) 2019 ShenZhen O&M Cloud Co., Ltd. All rights reserved. 19 | */ 20 | open class DslBannerItem : DslNestedRecyclerItem() { 21 | 22 | init { 23 | itemLayoutId = R.layout.dsl_banner_item 24 | 25 | nestedRecyclerItemConfig.itemNestedLayoutManager = 26 | ScaleLayoutManager(LibInitProvider.contentProvider, 0).apply { 27 | recycleChildrenOnDetach = true 28 | isFullItem = true //全屏item 29 | maxVisibleItemCount = 3 //最大可见item数量 30 | infinite = true //无限滚动 31 | itemSpace = 0 //item之间的间隙 32 | minScale = 1f 33 | maxScale = 1f 34 | maxAlpha = 1f 35 | minAlpha = 1f 36 | } 37 | 38 | itemHeight = LinearLayout.LayoutParams.WRAP_CONTENT 39 | } 40 | 41 | val pagerLayoutManager: ViewPagerLayoutManager? 42 | get() = nestedRecyclerItemConfig.itemNestedLayoutManager as? ViewPagerLayoutManager 43 | 44 | override fun onBindNestedRecyclerView( 45 | recyclerView: RecyclerView, 46 | itemHolder: DslViewHolder, 47 | itemPosition: Int, 48 | adapterItem: DslAdapterItem, 49 | payloads: List 50 | ) { 51 | super.onBindNestedRecyclerView( 52 | recyclerView, itemHolder, itemPosition, adapterItem, payloads 53 | ) 54 | 55 | val drawableIndicator: DrawableIndicator? = itemHolder.v(R.id.lib_drawable_indicator) 56 | 57 | //page切换监听 58 | pagerLayoutManager?.setOnPageChangeListener(object : 59 | ViewPagerLayoutManager.OnPageChangeListener { 60 | override fun onPageScrollStateChanged(state: Int) { 61 | //L.v(state) 62 | } 63 | 64 | override fun onPageSelected(position: Int) { 65 | //L.v(position), 相当页面滑动也会通知. 66 | nestedRecyclerItemConfig._scrollPositionConfig?.adapterPosition = position 67 | drawableIndicator?.animatorToIndex(position) 68 | } 69 | }) 70 | 71 | //列表 72 | recyclerView.apply { 73 | drawableIndicator?.indicatorCount = nestedRecyclerItemConfig.itemNestedAdapter.itemCount 74 | 75 | nestedRecyclerItemConfig.itemNestedAdapter.onDispatchUpdatesOnce { 76 | drawableIndicator?.indicatorCount = it.itemCount 77 | } 78 | 79 | if (nestedRecyclerItemConfig.itemKeepScrollPosition) { 80 | nestedRecyclerItemConfig._scrollPositionConfig?.run { 81 | scrollToPosition(adapterPosition) 82 | } 83 | } 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /dslitem2/src/main/java/com/angcyo/item2/ILoopAdapterItem.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item2 2 | 3 | import com.angcyo.dsladapter.item.IDslItem 4 | import com.leochuan.AutoPlaySnapHelper 5 | 6 | /** 7 | * 8 | * Email:angcyo@126.com 9 | * @author angcyo 10 | * @date 2020/03/18 11 | * Copyright (c) 2019 ShenZhen O&M Cloud Co., Ltd. All rights reserved. 12 | */ 13 | interface ILoopAdapterItem : IDslItem { 14 | 15 | /**获取轮播图循环间隔时长, 毫秒*/ 16 | fun getLoopInterval(): Int = AutoPlaySnapHelper.TIME_INTERVAL 17 | } -------------------------------------------------------------------------------- /dslitem2/src/main/java/com/angcyo/item2/widget/recycler/DrawableIndicator.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item2.widget.recycler 2 | 3 | import android.animation.ValueAnimator 4 | import android.content.Context 5 | import android.graphics.Canvas 6 | import android.graphics.drawable.Drawable 7 | import android.util.AttributeSet 8 | import android.view.View 9 | import com.angcyo.dpi 10 | import com.angcyo.item.anim 11 | import com.angcyo.item.drawHeight 12 | import com.angcyo.item.getMode 13 | import com.angcyo.item.getSize 14 | import com.angcyo.item.loadDrawable 15 | import com.angcyo.item2.R 16 | import kotlin.math.max 17 | 18 | /** 19 | * 2种Drawable切换的指示器 20 | * Email:angcyo@126.com 21 | * @author angcyo 22 | * @date 2020/03/18 23 | */ 24 | class DrawableIndicator(context: Context, attributeSet: AttributeSet? = null) : 25 | View(context, attributeSet) { 26 | 27 | /**影响宽高*/ 28 | var drawableSize: Int by RequestLayoutProperty(6 * dpi) 29 | 30 | /**影响宽度*/ 31 | var drawableSizeFocus: Int by RequestLayoutProperty(12 * dpi) 32 | 33 | var indicatorDrawable: Drawable? = loadDrawable(R.drawable.lib_indicator_normal) 34 | var indicatorDrawableFocus: Drawable? = loadDrawable(R.drawable.lib_indicator_focus) 35 | 36 | /**指示器数量*/ 37 | var indicatorCount: Int by RequestLayoutProperty(0) 38 | 39 | /**当前显示*/ 40 | var indicatorIndex: Int by InvalidateProperty(0) 41 | 42 | /**间隙*/ 43 | var indicatorSpace: Int by RequestLayoutProperty(4 * dpi) 44 | 45 | init { 46 | val typedArray = context.obtainStyledAttributes(attributeSet, R.styleable.DrawableIndicator) 47 | 48 | if (typedArray.hasValue(R.styleable.DrawableIndicator_r_indicator_drawable)) { 49 | indicatorDrawable = 50 | typedArray.getDrawable(R.styleable.DrawableIndicator_r_indicator_drawable) 51 | } 52 | if (typedArray.hasValue(R.styleable.DrawableIndicator_r_indicator_drawable_focus)) { 53 | indicatorDrawableFocus = 54 | typedArray.getDrawable(R.styleable.DrawableIndicator_r_indicator_drawable_focus) 55 | } 56 | 57 | drawableSize = typedArray.getDimensionPixelOffset( 58 | R.styleable.DrawableIndicator_r_indicator_size, 59 | drawableSize 60 | ) 61 | drawableSizeFocus = typedArray.getDimensionPixelOffset( 62 | R.styleable.DrawableIndicator_r_indicator_size_focus, 63 | drawableSizeFocus 64 | ) 65 | indicatorSpace = typedArray.getDimensionPixelOffset( 66 | R.styleable.DrawableIndicator_r_indicator_space, 67 | indicatorSpace 68 | ) 69 | typedArray.recycle() 70 | 71 | if (isInEditMode) { 72 | indicatorCount = 5 73 | indicatorIndex = 2 74 | } 75 | } 76 | 77 | override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { 78 | var widthSize = widthMeasureSpec.getSize() 79 | var heightSize = heightMeasureSpec.getSize() 80 | if (widthMeasureSpec.getMode() != MeasureSpec.EXACTLY) { 81 | widthSize = paddingLeft + paddingRight + 82 | drawableSize * (indicatorCount - 1) + drawableSizeFocus + 83 | indicatorSpace * (indicatorCount - 1) 84 | } 85 | if (heightMeasureSpec.getMode() != MeasureSpec.EXACTLY) { 86 | heightSize = paddingTop + paddingBottom + max(drawableSize, drawableSizeFocus) 87 | } 88 | //super.onMeasure(widthMeasureSpec, heightMeasureSpec) 89 | setMeasuredDimension( 90 | max(widthSize, suggestedMinimumWidth), 91 | max(heightSize, suggestedMinimumHeight) 92 | ) 93 | } 94 | 95 | override fun onDraw(canvas: Canvas) { 96 | super.onDraw(canvas) 97 | 98 | if (indicatorCount > 1) { 99 | //大于1个时, 才绘制 100 | var left = paddingLeft 101 | var top = paddingTop 102 | for (i in 0 until indicatorCount) { 103 | val width: Int = when { 104 | _animator?.isStarted == true && i == indicatorIndex -> (drawableSize - (drawableSize - drawableSizeFocus) * _animatorFraction).toInt() 105 | _animator?.isStarted == true && i == _animatorFromIndex -> (drawableSizeFocus - (drawableSizeFocus - drawableSize) * _animatorFraction).toInt() 106 | i == indicatorIndex -> drawableSizeFocus 107 | else -> drawableSize 108 | } 109 | 110 | val height = drawableSize 111 | 112 | top = paddingTop + (drawHeight - height) / 2 113 | 114 | val drawable = if (i == indicatorIndex) { 115 | indicatorDrawableFocus 116 | } else { 117 | indicatorDrawable 118 | } 119 | drawable?.apply { 120 | val right = left + width 121 | setBounds(left, top, right, top + height) 122 | left = right + indicatorSpace 123 | draw(canvas) 124 | } 125 | } 126 | } 127 | } 128 | 129 | var _animator: ValueAnimator? = null 130 | var _animatorFromIndex: Int = -1 131 | var _animatorFraction: Float = 1f 132 | 133 | /**使用动画的方式切换*/ 134 | fun animatorToIndex(index: Int) { 135 | _animator?.cancel() 136 | _animator = null 137 | 138 | _animatorFromIndex = indicatorIndex 139 | indicatorIndex = index 140 | 141 | if (_animatorFromIndex == indicatorIndex) { 142 | return 143 | } 144 | 145 | _animator = anim(0f, 1f) { 146 | onAnimatorUpdateValue = { value, fraction -> 147 | _animatorFraction = fraction 148 | postInvalidateOnAnimation() 149 | } 150 | } 151 | } 152 | } -------------------------------------------------------------------------------- /dslitem2/src/main/java/com/angcyo/item2/widget/recycler/InvalidateProperty.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item2.widget.recycler 2 | 3 | import android.graphics.drawable.Drawable 4 | import android.view.View 5 | import kotlin.properties.ReadWriteProperty 6 | import kotlin.reflect.KProperty 7 | 8 | /** 9 | * 属性改变时, 自动触发[android.view.View.invalidate] 10 | * @author angcyo 11 | * @since 2022/08/06 12 | */ 13 | class InvalidateProperty(var value: VALUE) : ReadWriteProperty { 14 | 15 | override fun getValue(thisRef: VIEW, property: KProperty<*>): VALUE { 16 | val v = value 17 | if (v is Drawable) { 18 | if (v.callback != thisRef) { 19 | v.callback = thisRef 20 | } 21 | } 22 | return v 23 | } 24 | 25 | override fun setValue(thisRef: VIEW, property: KProperty<*>, value: VALUE) { 26 | val old = this.value 27 | this.value = value 28 | if (old != value) { 29 | thisRef.invalidate() 30 | } 31 | } 32 | 33 | } -------------------------------------------------------------------------------- /dslitem2/src/main/java/com/angcyo/item2/widget/recycler/LoopRecyclerView.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item2.widget.recycler 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import android.view.MotionEvent 6 | import android.view.View 7 | import com.angcyo.item2.R 8 | import com.angcyo.widget.recycler.DslRecyclerView 9 | import com.leochuan.AutoPlaySnapHelper 10 | 11 | /** 12 | * 13 | * Email:angcyo@126.com 14 | * @author angcyo 15 | * @date 2020/03/18 16 | * Copyright (c) 2019 ShenZhen O&M Cloud Co., Ltd. All rights reserved. 17 | */ 18 | open class LoopRecyclerView(context: Context, attributeSet: AttributeSet? = null) : 19 | DslRecyclerView(context, attributeSet) { 20 | 21 | /**是否自动开始循环滚动*/ 22 | var autoStartLoop: Boolean = true 23 | 24 | /**循环滚动助手*/ 25 | var loopSnapHelper: LoopSnapHelper = 26 | LoopSnapHelper(AutoPlaySnapHelper.TIME_INTERVAL, AutoPlaySnapHelper.RIGHT) 27 | 28 | /**一个一个滑动*/ 29 | var snapByOne: Boolean = true 30 | 31 | val enableLoop: Boolean 32 | get() = (adapter?.itemCount ?: 0) > 1 33 | 34 | init { 35 | val typedArray = context.obtainStyledAttributes(attributeSet, R.styleable.LoopRecyclerView) 36 | val timeInterval = typedArray.getInt( 37 | R.styleable.LoopRecyclerView_r_loop_interval, 38 | 3000 39 | ) 40 | val direction = 41 | typedArray.getInt( 42 | R.styleable.LoopRecyclerView_r_loop_direction, 43 | AutoPlaySnapHelper.RIGHT 44 | ) 45 | autoStartLoop = 46 | typedArray.getBoolean(R.styleable.LoopRecyclerView_r_auto_start, autoStartLoop) 47 | 48 | snapByOne = typedArray.getBoolean(R.styleable.LoopRecyclerView_r_snap_by_one, snapByOne) 49 | 50 | loopSnapHelper.loopDuration = typedArray.getInt( 51 | R.styleable.LoopRecyclerView_r_loop_duration, 52 | loopSnapHelper.loopDuration 53 | ) 54 | 55 | typedArray.recycle() 56 | 57 | loopSnapHelper.setTimeInterval(timeInterval) 58 | loopSnapHelper.setDirection(direction) 59 | loopSnapHelper.snapScrollOne = snapByOne 60 | } 61 | 62 | override fun onAttachedToWindow() { 63 | super.onAttachedToWindow() 64 | _startInner() 65 | } 66 | 67 | override fun onDetachedFromWindow() { 68 | super.onDetachedFromWindow() 69 | pause() 70 | } 71 | 72 | override fun onVisibilityChanged(changedView: View, visibility: Int) { 73 | super.onVisibilityChanged(changedView, visibility) 74 | if (visibility == View.VISIBLE) { 75 | _startInner() 76 | } else { 77 | pause() 78 | } 79 | } 80 | 81 | override fun setLayoutManager(layout: LayoutManager?) { 82 | super.setLayoutManager(layout) 83 | 84 | if (!isInEditMode) { 85 | loopSnapHelper.detachFromRecyclerView() 86 | //如果在super的构造方法里面调用了setLayoutManager, 此时[loopSnapHelper]还未初始化, 就会报空指针 87 | loopSnapHelper.attachToRecyclerView(this) //会自动开启无线循环 88 | _startInner() 89 | } 90 | } 91 | 92 | override fun dispatchTouchEvent(ev: MotionEvent): Boolean { 93 | val result = super.dispatchTouchEvent(ev) 94 | when (ev.action) { 95 | MotionEvent.ACTION_DOWN -> pause() 96 | MotionEvent.ACTION_UP -> _startInner() 97 | } 98 | return result 99 | } 100 | 101 | override fun onTouchEvent(ev: MotionEvent): Boolean { 102 | return super.onTouchEvent(ev) 103 | } 104 | 105 | override fun scrollBy(x: Int, y: Int) { 106 | super.scrollBy(x, y) 107 | } 108 | 109 | override fun scrollTo(x: Int, y: Int) { 110 | super.scrollTo(x, y) 111 | } 112 | 113 | fun _startInner() { 114 | if (autoStartLoop) { 115 | start() 116 | } 117 | } 118 | 119 | open fun start() { 120 | if (enableLoop) { 121 | //大于一个时才滚动 122 | loopSnapHelper.start() 123 | } else { 124 | pause() 125 | } 126 | } 127 | 128 | open fun pause() { 129 | loopSnapHelper.pause() 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /dslitem2/src/main/java/com/angcyo/item2/widget/recycler/LoopSnapHelper.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item2.widget.recycler 2 | 3 | import android.view.animation.DecelerateInterpolator 4 | import android.view.animation.Interpolator 5 | import androidx.recyclerview.widget.RecyclerView 6 | import com.angcyo.dsladapter.DslAdapter 7 | import com.angcyo.item2.ILoopAdapterItem 8 | import com.leochuan.AutoPlaySnapHelper 9 | import com.leochuan.ViewPagerLayoutManager 10 | 11 | /** 12 | * 13 | * Email:angcyo@126.com 14 | * @author angcyo 15 | * @date 2020/03/18 16 | * Copyright (c) 2019 ShenZhen O&M Cloud Co., Ltd. All rights reserved. 17 | */ 18 | class LoopSnapHelper(val interval: Int, direction: Int) : AutoPlaySnapHelper(interval, direction) { 19 | 20 | var loopInterpolator: Interpolator? = DecelerateInterpolator() 21 | 22 | var loopDuration: Int = 1000//UNDEFINED_DURATION 23 | 24 | /**替换默认的时间间隔*/ 25 | fun hookInterval() { 26 | if (mRecyclerView.adapter is DslAdapter && mRecyclerView.layoutManager is ViewPagerLayoutManager) { 27 | val layoutManager: ViewPagerLayoutManager = 28 | mRecyclerView.layoutManager as ViewPagerLayoutManager 29 | 30 | val currentPosition = 31 | layoutManager.currentPosition * if (layoutManager.reverseLayout) -1 else 1 32 | 33 | (mRecyclerView.adapter as DslAdapter).getItemData(currentPosition, true)?.apply { 34 | if (this is ILoopAdapterItem) { 35 | //替换默认的时间间隔 36 | setTimeInterval(this.getLoopInterval()) 37 | } 38 | } 39 | } 40 | } 41 | 42 | /**恢复默认的时间间隔*/ 43 | fun restoreInterval() { 44 | //恢复默认的时间间隔 45 | setTimeInterval(interval) 46 | } 47 | 48 | override fun onRun(layoutManager: ViewPagerLayoutManager) { 49 | if (mRecyclerView?.adapter?.itemCount ?: 0 <= 0) { 50 | return 51 | } 52 | hookInterval() 53 | 54 | val currentPosition = 55 | layoutManager.currentPositionOffset * if (layoutManager.reverseLayout) -1 else 1 56 | 57 | val targetPosition = if (direction == RIGHT) currentPosition + 1 else currentPosition - 1 58 | 59 | val delta: Int = layoutManager.getOffsetToPosition(targetPosition) 60 | if (layoutManager.orientation == RecyclerView.VERTICAL) { 61 | mRecyclerView?.smoothScrollBy(0, delta, loopInterpolator, loopDuration) 62 | } else { 63 | mRecyclerView?.smoothScrollBy(delta, 0, loopInterpolator, loopDuration) 64 | } 65 | 66 | handler.postDelayed(autoPlayRunnable, timeInterval.toLong()) 67 | 68 | restoreInterval() 69 | } 70 | 71 | override fun start() { 72 | if (mRecyclerView == null) { 73 | return 74 | } 75 | 76 | if (mRecyclerView.layoutManager == null) { 77 | return 78 | } 79 | 80 | if (mRecyclerView.layoutManager !is ViewPagerLayoutManager) { 81 | return 82 | } 83 | hookInterval() 84 | super.start() 85 | restoreInterval() 86 | } 87 | 88 | fun detachFromRecyclerView() { 89 | if (mRecyclerView != null) { 90 | destroyCallbacks() 91 | } 92 | mRecyclerView = null 93 | } 94 | } -------------------------------------------------------------------------------- /dslitem2/src/main/java/com/angcyo/item2/widget/recycler/RequestLayoutProperty.kt: -------------------------------------------------------------------------------- 1 | package com.angcyo.item2.widget.recycler 2 | 3 | import android.view.View 4 | import kotlin.properties.ReadWriteProperty 5 | import kotlin.reflect.KProperty 6 | 7 | /** 8 | * 9 | * Email:angcyo@126.com 10 | * @author angcyo 11 | * @date 2019/12/24 12 | * Copyright (c) 2019 ShenZhen O&M Cloud Co., Ltd. All rights reserved. 13 | */ 14 | class RequestLayoutProperty(var value: T) : ReadWriteProperty { 15 | override fun getValue(thisRef: View, property: KProperty<*>): T = value 16 | 17 | override fun setValue(thisRef: View, property: KProperty<*>, value: T) { 18 | this.value = value 19 | thisRef.requestLayout() 20 | } 21 | } 22 | 23 | class RequestLayoutAnyProperty(var value: T, val view: View?) : ReadWriteProperty { 24 | override fun getValue(thisRef: Any, property: KProperty<*>): T = value 25 | 26 | override fun setValue(thisRef: Any, property: KProperty<*>, value: T) { 27 | this.value = value 28 | view?.requestLayout() 29 | } 30 | } -------------------------------------------------------------------------------- /dslitem2/src/main/res/drawable/lib_indicator_focus.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /dslitem2/src/main/res/drawable/lib_indicator_normal.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /dslitem2/src/main/res/layout/dsl_banner_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 17 | 18 | 24 | 25 | -------------------------------------------------------------------------------- /dslitem2/src/main/res/values/attr_border_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /dslitem2/src/main/res/values/attr_drawable_indicator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /dslitem2/src/main/res/values/attr_loop_recycler_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /dslitem2/src/main/res/values/item2_values.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #4D727272 4 | @color/colorAccent 5 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx1536m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app's APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Automatically convert third-party libraries to use AndroidX 19 | android.enableJetifier=true 20 | # Kotlin code style for this project: "official" or "obsolete": 21 | kotlin.code.style=official 22 | android.defaults.buildfeatures.buildconfig=true 23 | android.nonTransitiveRClass=false 24 | android.nonFinalResIds=false 25 | 26 | M_SDK=18 27 | T_SDK=33 28 | C_SDK=33 -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angcyo/DslItem/92c5a7c665636c7af4c1f497c41657653ae80326/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Apr 28 14:29:15 CST 2023 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /png/item.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angcyo/DslItem/92c5a7c665636c7af4c1f497c41657653ae80326/png/item.png -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name='DslItem' 2 | include ':demo' 3 | include ':dslitem' 4 | include ':dslitem2' 5 | --------------------------------------------------------------------------------