├── app
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── values
│ │ │ │ ├── strings.xml
│ │ │ │ ├── themes.xml
│ │ │ │ └── colors.xml
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ ├── logo.jpg
│ │ │ │ ├── zan.png
│ │ │ │ ├── caver.webp
│ │ │ │ ├── pinglun.png
│ │ │ │ ├── icon_code.png
│ │ │ │ ├── icon_copy.png
│ │ │ │ ├── icon_data.png
│ │ │ │ ├── icon_kafi.png
│ │ │ │ ├── icon_left.png
│ │ │ │ ├── logo_mini.jpg
│ │ │ │ ├── anim_draw.webp
│ │ │ │ ├── base_draw.webp
│ │ │ │ ├── head_icon.webp
│ │ │ │ ├── ic_launcher.webp
│ │ │ │ ├── icon_about.png
│ │ │ │ ├── icon_colloct.png
│ │ │ │ ├── icon_head.webp
│ │ │ │ ├── icon_share.png
│ │ │ │ ├── icon_version.png
│ │ │ │ ├── icon_app_setting.png
│ │ │ │ └── ic_launcher_round.webp
│ │ │ ├── mipmap-hdpi
│ │ │ │ ├── ic_launcher.webp
│ │ │ │ └── ic_launcher_round.webp
│ │ │ ├── mipmap-mdpi
│ │ │ │ ├── ic_launcher.webp
│ │ │ │ └── ic_launcher_round.webp
│ │ │ ├── mipmap-xhdpi
│ │ │ │ ├── ic_launcher.webp
│ │ │ │ └── ic_launcher_round.webp
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ ├── ic_launcher.webp
│ │ │ │ └── ic_launcher_round.webp
│ │ │ ├── mipmap-anydpi-v26
│ │ │ │ ├── ic_launcher.xml
│ │ │ │ └── ic_launcher_round.xml
│ │ │ ├── xml
│ │ │ │ ├── backup_rules.xml
│ │ │ │ └── data_extraction_rules.xml
│ │ │ └── drawable-v24
│ │ │ │ └── ic_launcher_foreground.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── toly1994
│ │ │ │ └── composeunit
│ │ │ │ ├── ui
│ │ │ │ └── theme
│ │ │ │ │ ├── Color.kt
│ │ │ │ │ ├── Shape.kt
│ │ │ │ │ ├── Type.kt
│ │ │ │ │ └── Theme.kt
│ │ │ │ ├── app
│ │ │ │ ├── UnitApplication.kt
│ │ │ │ ├── ComposeUnitApp.kt
│ │ │ │ ├── navigation
│ │ │ │ │ ├── RouterRes.kt
│ │ │ │ │ ├── UnitAppBar.kt
│ │ │ │ │ └── UnitNavigation.kt
│ │ │ │ ├── data_manager
│ │ │ │ │ └── DataManagePage.kt
│ │ │ │ └── splash
│ │ │ │ │ └── UnitSplash.kt
│ │ │ │ ├── repository
│ │ │ │ ├── NodeRepository.kt
│ │ │ │ ├── WidgetRepository.kt
│ │ │ │ ├── impl
│ │ │ │ │ ├── DbNodeRepository.kt
│ │ │ │ │ ├── MemoryNodeRepository.kt
│ │ │ │ │ ├── DbWidgetRepository.kt
│ │ │ │ │ └── MemoryWidgetRepository.kt
│ │ │ │ ├── database
│ │ │ │ │ ├── dao
│ │ │ │ │ │ ├── NodeDao.kt
│ │ │ │ │ │ └── WidgetDao.kt
│ │ │ │ │ ├── entity
│ │ │ │ │ │ └── WidgetPo.kt
│ │ │ │ │ └── ComposeUnitDB.kt
│ │ │ │ └── memory
│ │ │ │ │ ├── MemoryWidgetDataStore.kt
│ │ │ │ │ └── MemoryNodeDataStore.kt
│ │ │ │ ├── models
│ │ │ │ ├── NodeModel.kt
│ │ │ │ ├── WidgetModel.kt
│ │ │ │ └── state
│ │ │ │ │ └── WidgetSearchState.kt
│ │ │ │ ├── components
│ │ │ │ ├── style
│ │ │ │ │ └── Gap.kt
│ │ │ │ ├── tolyui
│ │ │ │ │ └── Panel.kt
│ │ │ │ └── CodeHighlighter.kt
│ │ │ │ ├── layouts
│ │ │ │ ├── github_search
│ │ │ │ │ ├── repository
│ │ │ │ │ │ ├── GitHubClient.kt
│ │ │ │ │ │ └── GithubRepository.kt
│ │ │ │ │ ├── view_model
│ │ │ │ │ │ └── NodeViewModel.kt
│ │ │ │ │ └── views
│ │ │ │ │ │ ├── GithubSearchPage.kt
│ │ │ │ │ │ └── GithubRepoItem.kt
│ │ │ │ ├── counter
│ │ │ │ │ ├── CounterPageV0.kt
│ │ │ │ │ └── CounterPageV1.kt
│ │ │ │ ├── home
│ │ │ │ │ └── LayoutHomePage.kt
│ │ │ │ ├── unit_widget_item
│ │ │ │ │ ├── UnitWidgetItemV1.kt
│ │ │ │ │ └── UnitWidgetItemV0.kt
│ │ │ │ ├── juejin_article_item
│ │ │ │ │ ├── JuejinArticleItemV1.kt
│ │ │ │ │ └── JuejinArticleItemV0.kt
│ │ │ │ └── wechat_item
│ │ │ │ │ └── WeChatItem.kt
│ │ │ │ ├── widgets
│ │ │ │ ├── Text
│ │ │ │ │ ├── node1.kt
│ │ │ │ │ ├── node4.kt
│ │ │ │ │ ├── node2.kt
│ │ │ │ │ ├── node3.kt
│ │ │ │ │ └── node5.kt
│ │ │ │ ├── Column
│ │ │ │ │ ├── node3.kt
│ │ │ │ │ ├── node2.kt
│ │ │ │ │ └── node1.kt
│ │ │ │ ├── Row
│ │ │ │ │ ├── node3.kt
│ │ │ │ │ ├── node2.kt
│ │ │ │ │ └── node1.kt
│ │ │ │ ├── Box
│ │ │ │ │ ├── node1.kt
│ │ │ │ │ └── node2.kt
│ │ │ │ ├── Icon
│ │ │ │ │ └── node1.kt
│ │ │ │ ├── LazyColumn
│ │ │ │ │ └── node1.kt
│ │ │ │ ├── LazyRow
│ │ │ │ │ └── node1.kt
│ │ │ │ ├── Image
│ │ │ │ │ ├── node1.kt
│ │ │ │ │ ├── node3.kt
│ │ │ │ │ ├── node2.kt
│ │ │ │ │ └── node4.kt
│ │ │ │ ├── LazyVerticalGrid
│ │ │ │ │ └── node1.kt
│ │ │ │ ├── LazyHorizontalGrid
│ │ │ │ │ └── node1.kt
│ │ │ │ └── WidgetMap.kt
│ │ │ │ ├── MainActivity.kt
│ │ │ │ ├── home
│ │ │ │ ├── WidgetViewModel.kt
│ │ │ │ └── UnitHomePage.kt
│ │ │ │ ├── details
│ │ │ │ └── NodeViewModel.kt
│ │ │ │ ├── doing
│ │ │ │ └── Doing.kt
│ │ │ │ └── user
│ │ │ │ └── UnitUserPage.kt
│ │ └── AndroidManifest.xml
│ ├── test
│ │ └── java
│ │ │ └── com
│ │ │ └── toly1994
│ │ │ └── composeunit
│ │ │ └── ExampleUnitTest.kt
│ └── androidTest
│ │ └── java
│ │ └── com
│ │ └── toly1994
│ │ └── composeunit
│ │ └── ExampleInstrumentedTest.kt
├── proguard-rules.pro
└── build.gradle
├── highlight
├── .gitignore
├── consumer-rules.pro
├── src
│ ├── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ │ └── com
│ │ │ └── neo
│ │ │ └── highlight
│ │ │ ├── util
│ │ │ ├── scheme
│ │ │ │ ├── contract
│ │ │ │ │ ├── LinkSchemeContract.java
│ │ │ │ │ └── SchemeScope.java
│ │ │ │ ├── base
│ │ │ │ │ ├── BaseColorScheme.java
│ │ │ │ │ └── BaseScheme.java
│ │ │ │ ├── BackgroundScheme.java
│ │ │ │ ├── Scope.java
│ │ │ │ ├── ColorScheme.java
│ │ │ │ ├── OnMatchScheme.java
│ │ │ │ ├── StyleScheme.java
│ │ │ │ ├── LinkScheme.java
│ │ │ │ ├── FontScheme.java
│ │ │ │ └── OnClickScheme.java
│ │ │ └── listener
│ │ │ │ └── HighlightTextWatcher.java
│ │ │ └── core
│ │ │ ├── Scheme.java
│ │ │ ├── SpanUtils.java
│ │ │ ├── HighlightContract.java
│ │ │ └── LinesTextWatcher.java
│ ├── test
│ │ └── java
│ │ │ └── com
│ │ │ └── neo
│ │ │ └── highlight
│ │ │ └── ExampleUnitTest.java
│ └── androidTest
│ │ └── java
│ │ └── com
│ │ └── neo
│ │ └── highlight
│ │ └── ExampleInstrumentedTest.java
├── proguard-rules.pro
└── build.gradle
├── .idea
├── .gitignore
├── compiler.xml
├── vcs.xml
├── misc.xml
├── gradle.xml
└── inspectionProfiles
│ └── Project_Default.xml
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .gitignore
├── settings.gradle
├── README.md
├── gradle.properties
└── gradlew.bat
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/highlight/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/highlight/consumer-rules.pro:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | ComposeUnit
3 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toly1994328/ComposeUnit/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/logo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toly1994328/ComposeUnit/HEAD/app/src/main/res/mipmap-xxhdpi/logo.jpg
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/zan.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toly1994328/ComposeUnit/HEAD/app/src/main/res/mipmap-xxhdpi/zan.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/caver.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toly1994328/ComposeUnit/HEAD/app/src/main/res/mipmap-xxhdpi/caver.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/pinglun.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toly1994328/ComposeUnit/HEAD/app/src/main/res/mipmap-xxhdpi/pinglun.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/icon_code.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toly1994328/ComposeUnit/HEAD/app/src/main/res/mipmap-xxhdpi/icon_code.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/icon_copy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toly1994328/ComposeUnit/HEAD/app/src/main/res/mipmap-xxhdpi/icon_copy.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/icon_data.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toly1994328/ComposeUnit/HEAD/app/src/main/res/mipmap-xxhdpi/icon_data.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/icon_kafi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toly1994328/ComposeUnit/HEAD/app/src/main/res/mipmap-xxhdpi/icon_kafi.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/icon_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toly1994328/ComposeUnit/HEAD/app/src/main/res/mipmap-xxhdpi/icon_left.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/logo_mini.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toly1994328/ComposeUnit/HEAD/app/src/main/res/mipmap-xxhdpi/logo_mini.jpg
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toly1994328/ComposeUnit/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toly1994328/ComposeUnit/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toly1994328/ComposeUnit/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/anim_draw.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toly1994328/ComposeUnit/HEAD/app/src/main/res/mipmap-xxhdpi/anim_draw.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/base_draw.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toly1994328/ComposeUnit/HEAD/app/src/main/res/mipmap-xxhdpi/base_draw.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/head_icon.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toly1994328/ComposeUnit/HEAD/app/src/main/res/mipmap-xxhdpi/head_icon.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toly1994328/ComposeUnit/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/icon_about.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toly1994328/ComposeUnit/HEAD/app/src/main/res/mipmap-xxhdpi/icon_about.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/icon_colloct.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toly1994328/ComposeUnit/HEAD/app/src/main/res/mipmap-xxhdpi/icon_colloct.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/icon_head.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toly1994328/ComposeUnit/HEAD/app/src/main/res/mipmap-xxhdpi/icon_head.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/icon_share.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toly1994328/ComposeUnit/HEAD/app/src/main/res/mipmap-xxhdpi/icon_share.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/icon_version.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toly1994328/ComposeUnit/HEAD/app/src/main/res/mipmap-xxhdpi/icon_version.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toly1994328/ComposeUnit/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toly1994328/ComposeUnit/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toly1994328/ComposeUnit/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toly1994328/ComposeUnit/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/icon_app_setting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toly1994328/ComposeUnit/HEAD/app/src/main/res/mipmap-xxhdpi/icon_app_setting.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toly1994328/ComposeUnit/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toly1994328/ComposeUnit/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/highlight/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Oct 31 06:38:05 CST 2022
2 | distributionBase=GRADLE_USER_HOME
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip
4 | distributionPath=wrapper/dists
5 | zipStorePath=wrapper/dists
6 | zipStoreBase=GRADLE_USER_HOME
7 |
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/ui/theme/Color.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.ui.theme
2 |
3 | import androidx.compose.ui.graphics.Color
4 |
5 | val Purple200 = Color(0xFFBB86FC)
6 | val Purple500 = Color(0xFF6200EE)
7 | val Purple700 = Color(0xFF3700B3)
8 | val Teal200 = Color(0xFF03DAC5)
--------------------------------------------------------------------------------
/.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 | local.properties
16 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/app/UnitApplication.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.app
2 |
3 | import android.app.Application
4 | import com.toly1994.composeunit.repository.database.LocalDb
5 |
6 | class UnitApplication: Application() {
7 | override fun onCreate() {
8 | super.onCreate()
9 | LocalDb.offer(this)
10 | }
11 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/repository/NodeRepository.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.repository
2 |
3 | import com.toly1994.composeunit.models.NodeModel
4 | import com.toly1994.composeunit.models.WidgetModel
5 | import kotlinx.coroutines.flow.Flow
6 |
7 | interface NodeRepository {
8 | fun queryNodeByWidgetId(widgetId:Int): Flow>
9 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/repository/WidgetRepository.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.repository
2 |
3 | import com.toly1994.composeunit.models.WidgetModel
4 | import kotlinx.coroutines.flow.Flow
5 |
6 | interface WidgetRepository {
7 | fun queryAllWidget(): Flow>
8 |
9 | fun searchWidget(arg:String): Flow>
10 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/ui/theme/Shape.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.ui.theme
2 |
3 | import androidx.compose.foundation.shape.RoundedCornerShape
4 | import androidx.compose.material.Shapes
5 | import androidx.compose.ui.unit.dp
6 |
7 | val Shapes = Shapes(
8 | small = RoundedCornerShape(4.dp),
9 | medium = RoundedCornerShape(4.dp),
10 | large = RoundedCornerShape(0.dp)
11 | )
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | gradlePluginPortal()
4 | google()
5 | mavenCentral()
6 | }
7 | }
8 | dependencyResolutionManagement {
9 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
10 | repositories {
11 | google()
12 | mavenCentral()
13 | }
14 | }
15 | rootProject.name = "ComposeUnit"
16 | include ':app'
17 | include ':highlight'
18 |
--------------------------------------------------------------------------------
/app/src/test/java/com/toly1994/composeunit/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit
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 | }
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/models/NodeModel.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.models
2 |
3 | import androidx.room.ColumnInfo
4 | import androidx.room.Entity
5 | import androidx.room.PrimaryKey
6 |
7 | @Entity(tableName = "node")
8 | data class NodeModel(
9 | @ColumnInfo(name = "widget_id")
10 | val widgetId: Int,
11 | @PrimaryKey
12 | val name: String,
13 | @ColumnInfo
14 | val info: String,
15 | @ColumnInfo
16 | val code: String,
17 | )
18 |
--------------------------------------------------------------------------------
/highlight/src/main/java/com/neo/highlight/util/scheme/contract/LinkSchemeContract.java:
--------------------------------------------------------------------------------
1 | package com.neo.highlight.util.scheme.contract;
2 |
3 | import androidx.annotation.ColorInt;
4 |
5 | import com.neo.highlight.core.Scheme;
6 | import com.neo.highlight.util.scheme.LinkScheme;
7 |
8 | public interface LinkSchemeContract {
9 | Scheme setPainText(boolean painText);
10 | Scheme setPainTextColor(@ColorInt int painTextColor);
11 | Scheme setPainTextUnderline(boolean painTextUnderline);
12 | }
13 |
--------------------------------------------------------------------------------
/highlight/src/test/java/com/neo/highlight/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.neo.highlight;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/app/src/main/res/xml/backup_rules.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
13 |
--------------------------------------------------------------------------------
/highlight/src/main/java/com/neo/highlight/core/Scheme.java:
--------------------------------------------------------------------------------
1 | package com.neo.highlight.core;
2 |
3 | import androidx.annotation.NonNull;
4 | import androidx.annotation.Nullable;
5 |
6 | import java.util.regex.Pattern;
7 |
8 | /**
9 | * @author Irineu A. Silva
10 | */
11 | public interface Scheme {
12 |
13 | @Nullable
14 | Pattern getRegex();
15 |
16 | @Nullable
17 | Object getSpan(@NonNull CharSequence text, int start, int end);
18 |
19 | boolean getClearOldSpan();
20 |
21 | @NonNull
22 | Scheme setClearOldSpan(boolean clearOldSpan);
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/highlight/src/main/java/com/neo/highlight/util/scheme/contract/SchemeScope.java:
--------------------------------------------------------------------------------
1 | package com.neo.highlight.util.scheme.contract;
2 |
3 | import androidx.annotation.NonNull;
4 | import androidx.annotation.Nullable;
5 |
6 | import com.neo.highlight.core.Scheme;
7 |
8 | import java.util.List;
9 |
10 | /**
11 | * @author Irineu A. Silva
12 | */
13 | public interface SchemeScope {
14 |
15 | @Nullable
16 | List getScopeSchemes();
17 | void setScopeSchemes(List schemes);
18 | Scheme addScopeScheme(@NonNull Scheme... schemes);
19 | Scheme clearScopeSchemes();
20 | }
21 |
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/components/style/Gap.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.components.style
2 |
3 |
4 |
5 | import androidx.compose.foundation.layout.Row
6 | import androidx.compose.foundation.layout.Spacer
7 | import androidx.compose.foundation.layout.height
8 | import androidx.compose.foundation.layout.width
9 | import androidx.compose.runtime.Composable
10 | import androidx.compose.ui.Modifier
11 | import androidx.compose.ui.unit.dp
12 |
13 |
14 | @Composable
15 | fun Gap(width: Float = 0f, height: Float = 0f) {
16 | Spacer(modifier = Modifier
17 | .width(width.dp)
18 | .height(height.dp))
19 | }
--------------------------------------------------------------------------------
/app/src/main/res/xml/data_extraction_rules.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
12 |
13 |
19 |
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/repository/impl/DbNodeRepository.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.repository.impl
2 |
3 | import com.toly1994.composeunit.models.NodeModel
4 | import com.toly1994.composeunit.repository.NodeRepository
5 | import com.toly1994.composeunit.repository.database.LocalDb
6 | import com.toly1994.composeunit.repository.memory.MemoryNodeDataStore
7 | import kotlinx.coroutines.flow.Flow
8 | import kotlinx.coroutines.flow.flow
9 |
10 |
11 | class DbNodeRepository : NodeRepository {
12 |
13 | override fun queryNodeByWidgetId(widgetId: Int): Flow> {
14 | return LocalDb.database.nodeDao().queryByWidgetId(widgetId)
15 | }
16 |
17 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/repository/impl/MemoryNodeRepository.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.repository.impl
2 |
3 | import com.toly1994.composeunit.models.NodeModel
4 | import com.toly1994.composeunit.repository.NodeRepository
5 | import com.toly1994.composeunit.repository.memory.MemoryNodeDataStore
6 | import kotlinx.coroutines.flow.Flow
7 | import kotlinx.coroutines.flow.flow
8 |
9 |
10 | class MemoryNodeRepository : NodeRepository {
11 |
12 | override fun queryNodeByWidgetId(widgetId: Int): Flow> = flow {
13 | val nodes = MemoryNodeDataStore.allNodes.filter { model -> model.widgetId == widgetId }
14 | emit(nodes)
15 | }
16 |
17 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/layouts/github_search/repository/GitHubClient.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.layouts.github_search.repository
2 |
3 | import com.toly1994.composeunit.layouts.github_search.repository.GitHubApi.searchUserRepo
4 | import com.toly1994.composeunit.layouts.github_search.repository.models.GithubRepo
5 | import retrofit2.http.GET
6 | import retrofit2.http.Path
7 |
8 | object GitHubApi {
9 | val baseUrl = "https://api.github.com/"
10 | const val searchUserRepo = "users/{username}/repos"
11 | }
12 |
13 | interface GitHubClient {
14 |
15 | @GET(searchUserRepo)
16 | suspend fun getRepositoryByUser(@Path("username") username: String): List
17 |
18 | }
--------------------------------------------------------------------------------
/highlight/src/main/java/com/neo/highlight/util/scheme/base/BaseColorScheme.java:
--------------------------------------------------------------------------------
1 | package com.neo.highlight.util.scheme.base;
2 |
3 | import androidx.annotation.ColorInt;
4 | import androidx.annotation.NonNull;
5 |
6 | import java.util.regex.Pattern;
7 |
8 | /**
9 | * Base to spannable colors
10 | * @author Irineu A. Silva
11 | */
12 | abstract public class BaseColorScheme extends BaseScheme {
13 |
14 | @ColorInt
15 | protected final int color;
16 |
17 | public BaseColorScheme(@NonNull Pattern pattern, @ColorInt int color) {
18 | super(pattern);
19 | this.color = color;
20 | }
21 |
22 | public BaseColorScheme(@ColorInt int color) {
23 | super(null);
24 | this.color = color;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFBB86FC
4 | #FF6200EE
5 | #FF3700B3
6 | #FF03DAC5
7 | #FF018786
8 | #FF000000
9 | #FFFFFFFF
10 |
11 |
12 | #009999
13 | #00627A
14 | #DD1045
15 | #93880D
16 | #FF00b0e8
17 | #FF6F42C1
18 |
19 |
--------------------------------------------------------------------------------
/highlight/src/main/java/com/neo/highlight/core/SpanUtils.java:
--------------------------------------------------------------------------------
1 | package com.neo.highlight.core;
2 |
3 | import android.text.Editable;
4 | import android.text.Spanned;
5 |
6 | /**
7 | * @author Irineu A. Silva
8 | */
9 | final public class SpanUtils {
10 |
11 | private SpanUtils() {}
12 |
13 | public static void setSpan(Editable editable, Object span, int start, int end) {
14 | editable.setSpan(span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
15 | }
16 |
17 | public static void removeSpans(Editable editable, Class tClass, int start, int end) {
18 | Object[] spans = editable.getSpans(start, end, tClass);
19 |
20 | for (Object span : spans) {
21 | editable.removeSpan(span);
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/models/WidgetModel.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.models
2 |
3 | import com.toly1994.composeunit.repository.database.entity.WidgetPo
4 | import com.toly1994.composeunit.repository.database.entity.WidgetPoMap
5 |
6 | data class WidgetModel(
7 | val id: Int,
8 | val name: String,
9 | val nameCN: String,
10 | val info: String,
11 | val family: String,
12 | val lever: Int,
13 | val collectd: Boolean,
14 | ) {
15 | fun toPo(): WidgetPo {
16 | val collectdValue = WidgetPoMap.widgetCollectdMap[collectd]!!
17 | val familyValue = WidgetPoMap.widgetFamilyMap[family]!!
18 | return WidgetPo(
19 | id, name, nameCN, info, lever, collectdValue, familyValue,
20 | )
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/repository/database/dao/NodeDao.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.repository.database.dao
2 |
3 | import androidx.room.*
4 | import com.toly1994.composeunit.models.NodeModel
5 | import com.toly1994.composeunit.models.WidgetModel
6 | import com.toly1994.composeunit.repository.database.entity.WidgetPo
7 | import com.toly1994.composeunit.repository.database.entity.WidgetPoMap
8 | import kotlinx.coroutines.flow.Flow
9 |
10 | @Dao
11 | interface NodeDao {
12 | @Query("SELECT * FROM node WHERE widget_id = :widgetId")
13 | fun queryByWidgetId(widgetId:Int):Flow>
14 |
15 | @Insert(onConflict = OnConflictStrategy.REPLACE)
16 | fun insertAll(vararg data: NodeModel)
17 |
18 | @Query("DELETE from node")
19 | fun deleteAll()
20 | }
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/toly1994/composeunit/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit
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.toly1994.composeunit", appContext.packageName)
23 | }
24 | }
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/highlight/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
--------------------------------------------------------------------------------
/highlight/src/main/java/com/neo/highlight/util/scheme/BackgroundScheme.java:
--------------------------------------------------------------------------------
1 | package com.neo.highlight.util.scheme;
2 |
3 | import android.text.style.BackgroundColorSpan;
4 |
5 | import androidx.annotation.NonNull;
6 |
7 | import com.neo.highlight.util.scheme.base.BaseColorScheme;
8 |
9 | import java.util.regex.Pattern;
10 |
11 | /**
12 | * Paint the background
13 | * @author Irineu A. Silva
14 | */
15 | final public class BackgroundScheme extends BaseColorScheme {
16 |
17 | public BackgroundScheme(@NonNull Pattern pattern, int color) {
18 | super(pattern, color);
19 | }
20 |
21 | public BackgroundScheme(int color) {
22 | super(color);
23 | }
24 |
25 | @NonNull
26 | @Override
27 | public Object getSpan(@NonNull CharSequence text, int start, int end) {
28 | return new BackgroundColorSpan(super.color);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/highlight/src/main/java/com/neo/highlight/util/scheme/Scope.java:
--------------------------------------------------------------------------------
1 | package com.neo.highlight.util.scheme;
2 |
3 | import androidx.annotation.NonNull;
4 | import androidx.annotation.Nullable;
5 |
6 | import com.neo.highlight.core.Scheme;
7 | import com.neo.highlight.util.scheme.base.BaseScheme;
8 |
9 | import java.util.ArrayList;
10 | import java.util.Arrays;
11 | import java.util.regex.Pattern;
12 |
13 | /**
14 | * Scope for schemes
15 | * @author Irineu A. Silva
16 | */
17 | final public class Scope extends BaseScheme {
18 |
19 | public Scope(@NonNull Pattern pattern, @NonNull Scheme... scopeSchemes) {
20 | super(pattern);
21 | setScopeSchemes(new ArrayList<>(Arrays.asList(scopeSchemes)));
22 | }
23 |
24 | @Override
25 | @Nullable
26 | public Object getSpan(@NonNull CharSequence text, int start, int end) {
27 | return null;
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/highlight/src/main/java/com/neo/highlight/util/scheme/ColorScheme.java:
--------------------------------------------------------------------------------
1 | package com.neo.highlight.util.scheme;
2 |
3 | import android.text.style.ForegroundColorSpan;
4 |
5 | import androidx.annotation.ColorInt;
6 | import androidx.annotation.NonNull;
7 |
8 | import com.neo.highlight.util.scheme.base.BaseColorScheme;
9 |
10 | import java.util.regex.Pattern;
11 |
12 | /**
13 | * Paint the text
14 | * @author Irineu A. Silva
15 | */
16 | final public class ColorScheme extends BaseColorScheme {
17 |
18 | public ColorScheme(@NonNull Pattern pattern, @ColorInt int color) {
19 | super(pattern, color);
20 | }
21 |
22 | public ColorScheme(@ColorInt int color) {
23 | super(color);
24 | }
25 |
26 | @Override
27 | @NonNull
28 | public Object getSpan(@NonNull CharSequence text, int start, int end) {
29 | return new ForegroundColorSpan(color);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/repository/impl/DbWidgetRepository.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.repository.impl
2 |
3 | import com.toly1994.composeunit.models.WidgetModel
4 | import com.toly1994.composeunit.repository.WidgetRepository
5 | import com.toly1994.composeunit.repository.database.LocalDb
6 | import com.toly1994.composeunit.repository.memory.MemoryWidgetDataStore
7 | import kotlinx.coroutines.flow.*
8 |
9 |
10 | class DbWidgetRepository : WidgetRepository {
11 |
12 | override fun queryAllWidget(): Flow> {
13 | val pos = LocalDb.database.widgetDao().queryAll()
14 | return pos.map { it.map { po -> po.toModel() } }
15 | }
16 |
17 | override fun searchWidget(arg: String): Flow> {
18 | val pos = LocalDb.database.widgetDao().searchByName(arg)
19 | return pos.map { it.map { po -> po.toModel() } }
20 | }
21 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | | - | - |
2 | | --- | --- |
3 | |  |  |
4 |
5 |
6 | ---
7 |
8 | | - | - |
9 | | --- | --- |
10 | |  |  |
11 |
12 |
13 | ---
14 |
15 | | - | - |
16 | | --- | --- |
17 | |  |  |
--------------------------------------------------------------------------------
/highlight/src/androidTest/java/com/neo/highlight/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.neo.highlight;
2 |
3 | import android.content.Context;
4 |
5 | import androidx.test.platform.app.InstrumentationRegistry;
6 | import androidx.test.ext.junit.runners.AndroidJUnit4;
7 |
8 | import org.junit.Test;
9 | import org.junit.runner.RunWith;
10 |
11 | import static org.junit.Assert.*;
12 |
13 | /**
14 | * Instrumented test, which will execute on an Android device.
15 | *
16 | * @see Testing documentation
17 | */
18 | @RunWith(AndroidJUnit4.class)
19 | public class ExampleInstrumentedTest {
20 | @Test
21 | public void useAppContext() {
22 | // Context of the app under test.
23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
24 | assertEquals("com.neo.highlight.test", appContext.getPackageName());
25 | }
26 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/repository/impl/MemoryWidgetRepository.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.repository.impl
2 |
3 | import com.toly1994.composeunit.models.WidgetModel
4 | import com.toly1994.composeunit.repository.WidgetRepository
5 | import com.toly1994.composeunit.repository.memory.MemoryWidgetDataStore
6 | import kotlinx.coroutines.flow.Flow
7 | import kotlinx.coroutines.flow.flow
8 |
9 |
10 | class MemoryWidgetRepository : WidgetRepository {
11 |
12 | override fun queryAllWidget(): Flow> = flow {
13 | emit(MemoryWidgetDataStore.allWidget)
14 | }
15 |
16 | override fun searchWidget(arg: String): Flow> = flow {
17 | emit(MemoryWidgetDataStore.allWidget.filter { model ->
18 | model.name.contains(arg, ignoreCase = true) || model.nameCN.contains(
19 | arg, ignoreCase = true
20 | )
21 | })
22 | }
23 |
24 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/ui/theme/Type.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.ui.theme
2 |
3 | import androidx.compose.material.Typography
4 | import androidx.compose.ui.text.TextStyle
5 | import androidx.compose.ui.text.font.FontFamily
6 | import androidx.compose.ui.text.font.FontWeight
7 | import androidx.compose.ui.unit.sp
8 |
9 | // Set of Material typography styles to start with
10 | val Typography = Typography(
11 | body1 = TextStyle(
12 | fontFamily = FontFamily.Default,
13 | fontWeight = FontWeight.Normal,
14 | fontSize = 16.sp
15 | )
16 | /* Other default text styles to override
17 | button = TextStyle(
18 | fontFamily = FontFamily.Default,
19 | fontWeight = FontWeight.W500,
20 | fontSize = 14.sp
21 | ),
22 | caption = TextStyle(
23 | fontFamily = FontFamily.Default,
24 | fontWeight = FontWeight.Normal,
25 | fontSize = 12.sp
26 | )
27 | */
28 | )
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/models/state/WidgetSearchState.kt:
--------------------------------------------------------------------------------
1 | //package com.toly1994.composeunit.models.state
2 | //
3 | //import androidx.compose.runtime.State
4 | //import androidx.compose.runtime.getValue
5 | //import androidx.compose.runtime.mutableStateOf
6 | //import androidx.compose.runtime.setValue
7 | //import androidx.lifecycle.SavedStateHandle
8 | //import androidx.lifecycle.ViewModel
9 | //import com.toly1994.composeunit.models.WidgetModel
10 | //import com.toly1994.composeunit.repository.WidgetRepository
11 | //import kotlinx.coroutines.flow.Flow
12 | //
13 | //
14 | //class WidgetSearchState {
15 | // var result: List by mutableStateOf(listOf())
16 | //}
17 | //
18 | //class WidgetViewModel(
19 | // private val repository:WidgetRepository,
20 | // private val savedState:SavedStateHandle
21 | //):ViewModel(){
22 | //
23 | //// val uiState :State
24 | // val widgets:Flow> = repository.getAllWidget()
25 | //}
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/layouts/github_search/repository/GithubRepository.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.layouts.github_search.repository
2 |
3 | import com.toly1994.composeunit.layouts.github_search.repository.models.GithubRepo
4 | import kotlinx.coroutines.flow.Flow
5 | import kotlinx.coroutines.flow.flow
6 | import retrofit2.Retrofit
7 | import retrofit2.converter.gson.GsonConverterFactory
8 | import retrofit2.create
9 |
10 | class GithubRepository {
11 |
12 | private val retorfit: Retrofit by lazy {
13 | Retrofit.Builder()
14 | .baseUrl(GitHubApi.baseUrl)
15 | .addConverterFactory(GsonConverterFactory.create())
16 | .build()
17 | }
18 |
19 | private val gitHubClient = retorfit.create()
20 |
21 | suspend fun getRepositoryByUser(username: String = "toly1994328"): Flow> =
22 | flow {
23 | val data = gitHubClient.getRepositoryByUser(username)
24 | emit(data)
25 | }
26 |
27 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/repository/database/dao/WidgetDao.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.repository.database.dao
2 |
3 | import androidx.room.*
4 | import com.toly1994.composeunit.models.WidgetModel
5 | import com.toly1994.composeunit.repository.database.entity.WidgetPo
6 | import com.toly1994.composeunit.repository.database.entity.WidgetPoMap
7 | import kotlinx.coroutines.flow.Flow
8 |
9 | @Dao
10 | interface WidgetDao {
11 | @Query("SELECT * FROM widget")
12 | fun queryAll(): Flow>
13 |
14 | @Query("SELECT * FROM widget WHERE id = :id")
15 | fun queryById(id:Int):Flow>
16 |
17 | @Query("SELECT * FROM widget WHERE name LIKE :arg OR name_cn LIKE :arg")
18 | fun searchByName(arg:String): Flow>
19 |
20 | @Insert(onConflict = OnConflictStrategy.REPLACE)
21 | fun insertAll(vararg widgetPo: WidgetPo)
22 |
23 | @Delete
24 | fun delete(widgetPo: WidgetPo)
25 |
26 | @Query("DELETE from widget")
27 | fun deleteAll()
28 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/app/ComposeUnitApp.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.app
2 |
3 | import androidx.compose.runtime.Composable
4 | import com.toly1994.composeunit.app.data_manager.DataManagePage
5 | import com.toly1994.composeunit.app.navigation.UnitNavigation
6 | import com.toly1994.composeunit.details.WidgetDetail
7 | import com.toly1994.composeunit.layouts.counter.CountViewModel
8 | import com.toly1994.composeunit.layouts.counter.CounterPageV2
9 | import com.toly1994.composeunit.layouts.github_search.views.GithubSearchPage
10 | import com.toly1994.composeunit.widgets.Center
11 | import com.toly1994.composeunit.widgets.WidgetNodeMap
12 |
13 | @Composable
14 | fun ComposeUnitApp(
15 | onShare: (String) -> Unit,
16 | ) {
17 | UnitNavigation(onShare=onShare)
18 | // DataManagePage()
19 | // GithubSearchPage()
20 | // CounterPageV2(title = "计时器 ViewModel + Flow")
21 | // WidgetDetail(onShare = onShare) {
22 | //
23 | // }
24 | // Center {
25 | // WidgetNodeMap(10,0)
26 | // }
27 |
28 | }
29 |
30 |
31 |
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/components/tolyui/Panel.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.components.tolyui
2 |
3 | import androidx.compose.foundation.layout.Box
4 | import androidx.compose.foundation.layout.fillMaxWidth
5 | import androidx.compose.foundation.layout.padding
6 | import androidx.compose.foundation.shape.RoundedCornerShape
7 | import androidx.compose.material.Surface
8 | import androidx.compose.runtime.Composable
9 | import androidx.compose.ui.Modifier
10 | import androidx.compose.ui.draw.clip
11 | import androidx.compose.ui.graphics.Color
12 | import androidx.compose.ui.unit.dp
13 |
14 | @Composable
15 | fun Panel(
16 | radius: Float = 5.0f,
17 | color: Color = Color(0xffF6F8FA),
18 | content: @Composable () -> Unit,
19 | ) {
20 | Surface(
21 | color = color,
22 | modifier = Modifier
23 | .fillMaxWidth()
24 | .padding(10.dp)
25 | .clip(RoundedCornerShape(radius.dp))
26 | ) {
27 | Box(modifier = Modifier.padding(10.dp)
28 | ) { content() }
29 | }
30 | }
--------------------------------------------------------------------------------
/highlight/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.library'
3 | id 'maven-publish'
4 | }
5 |
6 | android {
7 | compileSdk 31
8 |
9 | defaultConfig {
10 | minSdk 21
11 | targetSdk 31
12 | versionCode 3
13 | versionName "1.0.4"
14 |
15 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
16 | consumerProguardFiles "consumer-rules.pro"
17 | }
18 |
19 | buildTypes {
20 | release {
21 | minifyEnabled false
22 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
23 | }
24 | }
25 | compileOptions {
26 | sourceCompatibility JavaVersion.VERSION_1_7
27 | targetCompatibility JavaVersion.VERSION_1_7
28 | }
29 | }
30 |
31 | dependencies {
32 |
33 | implementation 'androidx.appcompat:appcompat:1.4.0'
34 | implementation 'com.google.android.material:material:1.4.0'
35 | testImplementation 'junit:junit:4.+'
36 | androidTestImplementation 'androidx.test.ext:junit:1.1.3'
37 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
38 | }
39 |
--------------------------------------------------------------------------------
/highlight/src/main/java/com/neo/highlight/util/scheme/OnMatchScheme.java:
--------------------------------------------------------------------------------
1 | package com.neo.highlight.util.scheme;
2 |
3 | import androidx.annotation.NonNull;
4 | import androidx.annotation.Nullable;
5 |
6 | import com.neo.highlight.util.scheme.base.BaseScheme;
7 |
8 | import java.util.regex.Pattern;
9 |
10 | /**
11 | * Execute action when match
12 | * @author Irineu A. Silva
13 | */
14 | final public class OnMatchScheme extends BaseScheme {
15 |
16 | @NonNull
17 | private final OnMatchListener onMatchListener;
18 |
19 | public OnMatchScheme(@NonNull Pattern pattern, @NonNull OnMatchListener onMatchListener) {
20 | super(pattern);
21 | this.onMatchListener = onMatchListener;
22 | }
23 |
24 | public OnMatchScheme(@NonNull OnMatchListener onMatchListener) {
25 | super(null);
26 | this.onMatchListener = onMatchListener;
27 | }
28 |
29 | @Nullable
30 | @Override
31 | public Object getSpan(@NonNull CharSequence text, int start, int end) {
32 | onMatchListener.onMatch(text, start, end);
33 | return null;
34 | }
35 |
36 | public interface OnMatchListener {
37 | void onMatch(CharSequence text, int start, int end);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/widgets/Text/node1.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.widgets.Text
2 |
3 | import androidx.compose.material.Text
4 | import androidx.compose.runtime.Composable
5 | import androidx.compose.ui.graphics.Color
6 | import androidx.compose.ui.text.TextStyle
7 | import androidx.compose.ui.text.font.FontStyle
8 | import androidx.compose.ui.text.font.FontWeight
9 | import androidx.compose.ui.tooling.preview.Preview
10 | import androidx.compose.ui.unit.sp
11 |
12 | // "widgetId": 1,
13 | // "name": "文字的基本样式",
14 | // "subtitle":
15 | // 【text】 : 文字 【String】
16 | // 【style】: 文字样式 【TextStyle】
17 | // 【color】: 文字颜色 【Color】
18 | // 【fontSize】: 文字大小 【TextUnit】
19 | // 【fontWeight】: 字重 【FontWeight?】
20 | // 【fontStyle】: 字体样式 【FontStyle?】
21 | // 【letterSpacing】: 字距 【TextUnit】
22 |
23 | @Composable
24 | fun TextNode1() {
25 | val style = TextStyle(
26 | color = Color.Blue,
27 | fontSize = 20.sp,
28 | fontStyle = FontStyle.Italic,
29 | fontWeight = FontWeight.Bold,
30 | letterSpacing = 10.sp
31 | )
32 | Text(
33 | text = "toly-张风捷特烈-1994`",
34 | style = style,
35 | )
36 | }
37 |
38 | @Preview
39 | @Composable
40 | fun TextNode1Preview() {
41 | TextNode1()
42 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/widgets/Text/node4.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.widgets.Text
2 |
3 | import androidx.compose.foundation.background
4 | import androidx.compose.foundation.layout.padding
5 | import androidx.compose.foundation.layout.width
6 | import androidx.compose.material.Text
7 | import androidx.compose.runtime.Composable
8 | import androidx.compose.ui.Modifier
9 | import androidx.compose.ui.graphics.Color
10 | import androidx.compose.ui.text.style.TextOverflow
11 | import androidx.compose.ui.tooling.preview.Preview
12 | import androidx.compose.ui.unit.dp
13 | import androidx.compose.ui.unit.sp
14 |
15 | // "widgetId": 1,
16 | // "name": "多行与包裹溢出",
17 | // "subtitle":
18 | // 【softWrap】 : 是否自动换行 【Boolean】
19 | // 【overflow】: 溢出方式 【TextOverflow】
20 | // 【maxLines】: 最大行数 【Int】
21 |
22 | @Composable
23 | fun TextNode4() {
24 | Text(
25 | modifier = Modifier
26 | .width(200.dp)
27 | .background(Color(0xffEFEFEF))
28 | .padding(10.dp),
29 | text = "ComposeUnit is an application for learn Compose.",
30 | fontSize = 16.sp,
31 | softWrap = true,
32 | overflow = TextOverflow.Ellipsis,
33 | maxLines = 2,
34 | )
35 | }
36 |
37 | @Preview
38 | @Composable
39 | fun TextNode4Preview() {
40 | TextNode4()
41 | }
42 |
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/ui/theme/Theme.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.ui.theme
2 |
3 | import androidx.compose.foundation.isSystemInDarkTheme
4 | import androidx.compose.material.MaterialTheme
5 | import androidx.compose.material.darkColors
6 | import androidx.compose.material.lightColors
7 | import androidx.compose.runtime.Composable
8 |
9 | private val DarkColorPalette = darkColors(
10 | primary = Purple200,
11 | primaryVariant = Purple700,
12 | secondary = Teal200
13 | )
14 |
15 | private val LightColorPalette = lightColors(
16 | primary = Purple500,
17 | primaryVariant = Purple700,
18 | secondary = Teal200
19 |
20 | /* Other default colors to override
21 | background = Color.White,
22 | surface = Color.White,
23 | onPrimary = Color.White,
24 | onSecondary = Color.Black,
25 | onBackground = Color.Black,
26 | onSurface = Color.Black,
27 | */
28 | )
29 |
30 | @Composable
31 | fun ComposeUnitTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit) {
32 | val colors = if (darkTheme) {
33 | DarkColorPalette
34 | } else {
35 | LightColorPalette
36 | }
37 |
38 | MaterialTheme(
39 | colors = colors,
40 | typography = Typography,
41 | shapes = Shapes,
42 | content = content
43 | )
44 | }
--------------------------------------------------------------------------------
/highlight/src/main/java/com/neo/highlight/core/HighlightContract.java:
--------------------------------------------------------------------------------
1 | package com.neo.highlight.core;
2 |
3 | import android.text.Editable;
4 | import android.text.SpannableString;
5 | import android.widget.TextView;
6 |
7 | import androidx.annotation.NonNull;
8 |
9 | import java.util.List;
10 |
11 | /**
12 | * @author Irineu A. Silva
13 | */
14 | public interface HighlightContract {
15 |
16 | //setSpan EditText
17 | void setSpan(Editable editable, int start, int end);
18 | void setSpan(Editable editable);
19 |
20 | //setSpan TextView
21 | void setSpan(TextView textView, int start, int end);
22 | void setSpan(TextView textView);
23 |
24 | //setSpan Spannable
25 | void setSpan(SpannableString spannableString, int start, int end);
26 | void setSpan(SpannableString spannableString);
27 |
28 | //removeSpan EditText
29 | void removeSpan(Editable editable, int start, int end);
30 | void removeSpan(Editable editable);
31 |
32 | //schemes
33 | List getSchemes();
34 | void setSchemes(@NonNull List schemes);
35 | void addScheme(@NonNull Scheme... scheme);
36 | void clearScheme();
37 |
38 | //types
39 | List> getSpanTypes();
40 | void setSpanTypes(@NonNull List> spanTypes);
41 | void addSpanType(Class> span);
42 | void clearSpanTypes();
43 | }
44 |
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit
2 |
3 | import android.content.Intent
4 | import android.net.Uri
5 | import android.os.Bundle
6 | import androidx.activity.ComponentActivity
7 | import androidx.activity.compose.setContent
8 | import androidx.activity.viewModels
9 | import androidx.core.view.WindowCompat
10 | import androidx.room.Room
11 | import com.toly1994.composeunit.app.ComposeUnitApp
12 | import com.toly1994.composeunit.layouts.counter.CountViewModel
13 | import com.toly1994.composeunit.repository.database.ComposeUnitDB
14 | import com.toly1994.composeunit.repository.database.entity.WidgetPo
15 | import com.toly1994.composeunit.repository.memory.MemoryWidgetDataStore
16 |
17 |
18 | class MainActivity : ComponentActivity() {
19 |
20 | override fun onCreate(savedInstanceState: Bundle?) {
21 | super.onCreate(savedInstanceState)
22 | setContent {
23 | ComposeUnitApp(
24 | onShare = {
25 | share(it)
26 | }
27 | )
28 | }
29 | }
30 |
31 | private fun share(content: String) {
32 | val shareIntent = Intent(Intent.ACTION_SEND)
33 | shareIntent.setType("text/plain")
34 | shareIntent.putExtra(Intent.EXTRA_TEXT, content)
35 | startActivity(Intent.createChooser(shareIntent, "代码分享"))
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
16 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/repository/database/entity/WidgetPo.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.repository.database.entity
2 |
3 | import androidx.room.ColumnInfo
4 | import androidx.room.Entity
5 | import androidx.room.PrimaryKey
6 | import com.toly1994.composeunit.models.WidgetModel
7 |
8 | @Entity(tableName = "widget")
9 | data class WidgetPo(
10 | @PrimaryKey
11 | val id: Int,
12 | @ColumnInfo
13 | val name: String,
14 | @ColumnInfo(name = "name_cn")
15 | val nameCN: String,
16 | @ColumnInfo
17 | val info: String,
18 | @ColumnInfo
19 | val lever: Int,
20 | @ColumnInfo
21 | val collectd: Int, // 对应关系见 [PoMap#widgetCollectdMap]
22 | @ColumnInfo
23 | val family: Int, // 对应关系见 [PoMap#widgetFamilyMap]
24 | ){
25 | fun toModel(): WidgetModel {
26 | val collectdValue = WidgetPoMap.widgetCollectdMap.keys.toList()[collectd]
27 | val familyValue = WidgetPoMap.widgetFamilyMap.keys.toList()[family]
28 | return WidgetModel(
29 | id, name, nameCN, info, familyValue,lever, collectdValue,
30 | )
31 | }
32 | }
33 |
34 | object WidgetPoMap {
35 | // // 收藏 0 未收藏 1
36 | val widgetCollectdMap = mapOf(
37 | false to 0,
38 | true to 1,
39 | )
40 | val widgetFamilyMap = mapOf(
41 | "无内容组件" to 0,
42 | "单内容组件" to 1,
43 | "多内容组件" to 2,
44 | "卡槽型组件" to 3,
45 | )
46 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/widgets/Text/node2.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.widgets.Text
2 |
3 | import androidx.compose.material.Text
4 | import androidx.compose.runtime.Composable
5 | import androidx.compose.ui.Modifier
6 | import androidx.compose.ui.draw.clip
7 | import androidx.compose.ui.geometry.Offset
8 | import androidx.compose.ui.graphics.Color
9 | import androidx.compose.ui.graphics.RectangleShape
10 | import androidx.compose.ui.graphics.Shadow
11 | import androidx.compose.ui.text.TextStyle
12 | import androidx.compose.ui.text.font.FontStyle
13 | import androidx.compose.ui.text.font.FontWeight
14 | import androidx.compose.ui.tooling.preview.Preview
15 | import androidx.compose.ui.unit.sp
16 |
17 | // "widgetId": 1,
18 | // "name": "文字背景与阴影",
19 | // "subtitle":
20 | // 【backgroundColor】 : 背景颜色 【Color】
21 | // 【shadow】: 阴影 【Shadow】
22 |
23 | @Composable
24 | fun TextNode2() {
25 | val style = TextStyle(
26 | color = Color.White,
27 | fontSize = 50.sp,
28 | background = Color.Black,
29 | shadow = Shadow(
30 | color = Color.Cyan,
31 | offset = Offset(1f,1f),
32 | blurRadius = 10f
33 | )
34 | )
35 | Text(
36 | text = "张风捷特烈",
37 | style = style,
38 | modifier = Modifier.clip(RectangleShape)
39 | )
40 | }
41 |
42 | @Preview
43 | @Composable
44 | fun TextNode2Preview() {
45 | TextNode2()
46 | }
47 |
--------------------------------------------------------------------------------
/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=-Xmx2048m -Dfile.encoding=UTF-8
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 | # Kotlin code style for this project: "official" or "obsolete":
19 | kotlin.code.style=official
20 | # Enables namespacing of each library's R class so that its R class includes only the
21 | # resources declared in the library itself and none from the library's dependencies,
22 | # thereby reducing the size of the R class for that library
23 | android.nonTransitiveRClass=true
24 | android.injected.testOnly=false
--------------------------------------------------------------------------------
/highlight/src/main/java/com/neo/highlight/util/scheme/StyleScheme.java:
--------------------------------------------------------------------------------
1 | package com.neo.highlight.util.scheme;
2 |
3 | import android.graphics.Typeface;
4 | import android.text.style.StyleSpan;
5 |
6 | import androidx.annotation.NonNull;
7 |
8 | import com.neo.highlight.util.scheme.base.BaseScheme;
9 |
10 | import java.util.regex.Pattern;
11 |
12 | /**
13 | * Pain text style
14 | * @author Irineu A. Silva
15 | */
16 | final public class StyleScheme extends BaseScheme {
17 |
18 | @NonNull
19 | private final STYLE style;
20 |
21 | public StyleScheme(@NonNull Pattern pattern, @NonNull STYLE style) {
22 | super(pattern);
23 | this.style = style;
24 | }
25 |
26 | public StyleScheme(@NonNull STYLE style) {
27 | super(null);
28 | this.style = style;
29 | }
30 |
31 | @NonNull
32 | @Override
33 | public Object getSpan(@NonNull CharSequence text, int start, int end) {
34 | return new StyleSpan(getType());
35 | }
36 |
37 | private int getType() {
38 | switch (style) {
39 |
40 | case NORMAL:
41 | return Typeface.NORMAL;
42 | case ITALIC:
43 | return Typeface.ITALIC;
44 | case BOLD:
45 | return Typeface.BOLD;
46 | case BOLD_ITALIC:
47 | return Typeface.BOLD_ITALIC;
48 | }
49 |
50 | return Typeface.NORMAL;
51 | }
52 |
53 | public enum STYLE {
54 | NORMAL,
55 | ITALIC,
56 | BOLD,
57 | BOLD_ITALIC
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/home/WidgetViewModel.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.home
2 |
3 | import androidx.lifecycle.ViewModel
4 | import androidx.lifecycle.viewModelScope
5 | import com.toly1994.composeunit.models.WidgetModel
6 | import com.toly1994.composeunit.repository.impl.MemoryWidgetRepository
7 | import com.toly1994.composeunit.repository.WidgetRepository
8 | import com.toly1994.composeunit.repository.impl.DbWidgetRepository
9 | import kotlinx.coroutines.flow.MutableStateFlow
10 | import kotlinx.coroutines.flow.StateFlow
11 | import kotlinx.coroutines.flow.catch
12 | import kotlinx.coroutines.launch
13 |
14 | class WidgetViewModel (
15 | private val repository: WidgetRepository = MemoryWidgetRepository()
16 | // private val repository: WidgetRepository = DbWidgetRepository()
17 | ): ViewModel() {
18 | // 状态数据
19 | private val _uiState = MutableStateFlow(WidgetModelState())
20 | val uiState: StateFlow = _uiState
21 |
22 | init {
23 | loadData()
24 | }
25 |
26 | fun loadData(){
27 | viewModelScope.launch {
28 | repository.queryAllWidget()
29 | .catch { ex ->
30 | _uiState.value = WidgetModelState(error = ex.message)
31 | }
32 | .collect { data ->
33 | _uiState.value = WidgetModelState(
34 | models = data
35 | )
36 | }
37 | }
38 | }
39 |
40 | }
41 |
42 | data class WidgetModelState(
43 | val models: List = listOf(),
44 | val error: String? = null
45 | )
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/repository/database/ComposeUnitDB.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.repository.database
2 |
3 | import android.content.Context
4 | import android.util.Log
5 | import androidx.room.Database
6 | import androidx.room.Room
7 | import androidx.room.RoomDatabase
8 | import androidx.sqlite.db.SupportSQLiteDatabase
9 | import com.toly1994.composeunit.models.NodeModel
10 | import com.toly1994.composeunit.repository.database.dao.NodeDao
11 | import com.toly1994.composeunit.repository.database.dao.WidgetDao
12 | import com.toly1994.composeunit.repository.database.entity.WidgetPo
13 | import java.io.File
14 |
15 | object LocalDb{
16 | // 数据库名
17 | private const val dbName: String = "compose_unit.db"
18 |
19 | lateinit var database: ComposeUnitDB
20 | private set
21 |
22 | fun offer(context: Context) {
23 | database = Room.databaseBuilder(context, ComposeUnitDB::class.java, dbName)
24 | .allowMainThreadQueries() //允许在主线程操作
25 | .addCallback(DbCreateCallBack) // 回调监听
26 | // .addMigrations()// 数据库升级
27 | .build()
28 | }
29 |
30 | private object DbCreateCallBack : RoomDatabase.Callback() {
31 | override fun onOpen(db: SupportSQLiteDatabase) {
32 | Log.e("LocalDb", "onOpen: " + db.version)
33 | }
34 |
35 | override fun onCreate(db: SupportSQLiteDatabase) {
36 | super.onCreate(db)
37 | Log.e("LocalDb", "first onCreate db version: " + db.version)
38 | }
39 | }
40 | }
41 |
42 | @Database(entities = [WidgetPo::class,NodeModel::class], version = 1, exportSchema = false)
43 | abstract class ComposeUnitDB : RoomDatabase() {
44 | abstract fun widgetDao(): WidgetDao
45 | abstract fun nodeDao(): NodeDao
46 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/widgets/Column/node3.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.widgets.Column
2 |
3 | import androidx.compose.foundation.Image
4 | import androidx.compose.foundation.background
5 | import androidx.compose.foundation.layout.*
6 | import androidx.compose.material.Text
7 | import androidx.compose.runtime.Composable
8 | import androidx.compose.ui.Alignment
9 | import androidx.compose.ui.Modifier
10 | import androidx.compose.ui.graphics.Color
11 | import androidx.compose.ui.layout.ContentScale
12 | import androidx.compose.ui.res.painterResource
13 | import androidx.compose.ui.text.TextStyle
14 | import androidx.compose.ui.text.font.FontStyle
15 | import androidx.compose.ui.text.font.FontWeight
16 | import androidx.compose.ui.tooling.preview.Preview
17 | import androidx.compose.ui.unit.dp
18 | import androidx.compose.ui.unit.sp
19 | import com.toly1994.composeunit.R
20 | import com.toly1994.composeunit.widgets.Image.ImageContentScaleItem
21 |
22 | // "widgetId": 5,
23 | // "name": "列中的组件高度占比",
24 | // "subtitle":
25 | // Modifier 的 weight 属性只能用于 Row 和 Column 中,该案例里蓝色和绿色区域高度占比 1:2,且无视盒自身高度,使 Column 区域竖向占满。
26 |
27 | @Composable
28 | fun ColumnNode3() {
29 | val colors = arrayOf(Color.Red, Color.Blue, Color.Green,)
30 | Column(
31 | Modifier.width(250.dp).height(100.dp).background(Color(0xffEFEFEF)),
32 | horizontalAlignment = Alignment.CenterHorizontally
33 | ) {
34 | Spacer(Modifier.width(30.dp).height(30.dp).background(colors[0]))
35 | Spacer(Modifier.width(30.dp).height(30.dp).background(colors[1]).weight(1f))
36 | Spacer(Modifier.width(30.dp).height(30.dp).background(colors[2]).weight(2f))
37 | }
38 | }
39 |
40 | @Preview
41 | @Composable
42 | fun ColumnNode3Preview() {
43 | ColumnNode3()
44 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/widgets/Text/node3.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.widgets.Text
2 |
3 | import androidx.compose.foundation.layout.Row
4 | import androidx.compose.foundation.layout.padding
5 | import androidx.compose.material.Text
6 | import androidx.compose.runtime.Composable
7 | import androidx.compose.ui.Modifier
8 | import androidx.compose.ui.draw.clip
9 | import androidx.compose.ui.geometry.Offset
10 | import androidx.compose.ui.graphics.Color
11 | import androidx.compose.ui.graphics.RectangleShape
12 | import androidx.compose.ui.graphics.Shadow
13 | import androidx.compose.ui.text.TextStyle
14 | import androidx.compose.ui.text.font.FontStyle
15 | import androidx.compose.ui.text.font.FontWeight
16 | import androidx.compose.ui.text.style.TextDecoration
17 | import androidx.compose.ui.text.style.TextIndent
18 | import androidx.compose.ui.tooling.preview.Preview
19 | import androidx.compose.ui.unit.dp
20 | import androidx.compose.ui.unit.sp
21 |
22 | // "widgetId": 1,
23 | // "name": "文字装饰线与缩进",
24 | // "subtitle":
25 | // 【textDecoration】 : 文字装饰 【TextDecoration】
26 | // 【textIndent】: 文字缩进 【textIndent】
27 |
28 | @Composable
29 | fun TextNode3() {
30 | val style1 = TextStyle(
31 | fontSize = 25.sp,
32 | textDecoration = TextDecoration.LineThrough
33 | )
34 | val style2 = TextStyle(
35 | fontSize = 25.sp,
36 | textIndent = TextIndent(20.sp),
37 | textDecoration = TextDecoration.Underline
38 | )
39 | Row{
40 | Text(
41 | text = "张风捷特烈",
42 | style = style1,
43 | )
44 | Text(
45 | text = "张风捷特烈",
46 | style = style2,
47 | )
48 | }
49 | }
50 |
51 | @Preview
52 | @Composable
53 | fun TextNode3Preview() {
54 | TextNode3()
55 | }
56 |
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/widgets/Row/node3.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.widgets.Row
2 |
3 | import android.annotation.SuppressLint
4 | import androidx.compose.foundation.Image
5 | import androidx.compose.foundation.background
6 | import androidx.compose.foundation.layout.*
7 | import androidx.compose.material.Text
8 | import androidx.compose.runtime.Composable
9 | import androidx.compose.ui.Alignment
10 | import androidx.compose.ui.Modifier
11 | import androidx.compose.ui.graphics.Color
12 | import androidx.compose.ui.layout.ContentScale
13 | import androidx.compose.ui.res.painterResource
14 | import androidx.compose.ui.text.TextStyle
15 | import androidx.compose.ui.text.font.FontStyle
16 | import androidx.compose.ui.text.font.FontWeight
17 | import androidx.compose.ui.tooling.preview.Preview
18 | import androidx.compose.ui.unit.dp
19 | import androidx.compose.ui.unit.sp
20 | import com.toly1994.composeunit.R
21 | import com.toly1994.composeunit.widgets.Image.ImageContentScaleItem
22 |
23 | // "widgetId": 4,
24 | // "name": "行中的组件宽度占比",
25 | // "subtitle":
26 | // Modifier 的 weight 属性只能用于 Row 和 Column 中,该案例里蓝色和绿色区域宽度占比 1:2,且无视盒自身宽度,使 Row 区域横向占满。
27 | @SuppressLint("SuspiciousIndentation")
28 | @Composable
29 | fun RowNode3() {
30 | val colors = arrayOf(Color.Red, Color.Blue, Color.Green,)
31 | Row(
32 | Modifier.width(250.dp).height(100.dp).background(Color(0xffEFEFEF)),
33 | verticalAlignment = Alignment.CenterVertically
34 | ) {
35 | Spacer(Modifier.width(30.dp).height(30.dp).background(colors[0]))
36 | Spacer(Modifier.width(30.dp).height(30.dp).background(colors[1]).weight(1f))
37 | Spacer(Modifier.width(30.dp).height(30.dp).background(colors[2]).weight(2f))
38 | }
39 | }
40 |
41 | @Preview
42 | @Composable
43 | fun RowNode3Preview() {
44 | RowNode3()
45 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
15 |
18 |
21 |
22 |
23 |
24 |
30 |
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/widgets/Box/node1.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.widgets.Box
2 |
3 | import android.annotation.SuppressLint
4 | import androidx.compose.foundation.Image
5 | import androidx.compose.foundation.background
6 | import androidx.compose.foundation.layout.*
7 | import androidx.compose.material.Text
8 | import androidx.compose.runtime.Composable
9 | import androidx.compose.ui.Alignment
10 | import androidx.compose.ui.Modifier
11 | import androidx.compose.ui.graphics.Color
12 | import androidx.compose.ui.layout.ContentScale
13 | import androidx.compose.ui.res.painterResource
14 | import androidx.compose.ui.text.TextStyle
15 | import androidx.compose.ui.text.font.FontStyle
16 | import androidx.compose.ui.text.font.FontWeight
17 | import androidx.compose.ui.tooling.preview.Preview
18 | import androidx.compose.ui.unit.dp
19 | import androidx.compose.ui.unit.sp
20 | import com.toly1994.composeunit.R
21 | import com.toly1994.composeunit.widgets.Image.ImageContentScaleItem
22 |
23 | // "widgetId": 6,
24 | // "name": "Box 的对齐方式",
25 | // "subtitle":
26 | // 【contentAlignment】 : 内容对齐模式 【Alignment】
27 | // 【content】: 内容组件列表 【@Composable BoxScope.() -> Unit】
28 |
29 | @SuppressLint("SuspiciousIndentation")
30 | @Composable
31 | fun BoxNode1() {
32 | val colors = arrayOf(Color.Red, Color.Yellow , Color.Blue, Color.Green)
33 | Box(
34 | Modifier.width(250.dp).height(100.dp).background(Color(0xffEFEFEF)),
35 | contentAlignment = Alignment.Center
36 | ) {
37 | Spacer(Modifier.width(60.dp).height(60.dp).background(colors[3]))
38 | Spacer(Modifier.width(50.dp).height(50.dp).background(colors[2]))
39 | Spacer(Modifier.width(40.dp).height(40.dp).background(colors[1]))
40 | Spacer(Modifier.width(30.dp).height(30.dp).background(colors[0]))
41 | }
42 | }
43 |
44 | @Preview
45 | @Composable
46 | fun BoxNode1Preview() {
47 | BoxNode1()
48 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/widgets/Box/node2.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.widgets.Box
2 |
3 | import android.annotation.SuppressLint
4 | import androidx.compose.foundation.Image
5 | import androidx.compose.foundation.background
6 | import androidx.compose.foundation.layout.*
7 | import androidx.compose.material.Text
8 | import androidx.compose.runtime.Composable
9 | import androidx.compose.ui.Alignment
10 | import androidx.compose.ui.Modifier
11 | import androidx.compose.ui.graphics.Color
12 | import androidx.compose.ui.layout.ContentScale
13 | import androidx.compose.ui.res.painterResource
14 | import androidx.compose.ui.text.TextStyle
15 | import androidx.compose.ui.text.font.FontStyle
16 | import androidx.compose.ui.text.font.FontWeight
17 | import androidx.compose.ui.tooling.preview.Preview
18 | import androidx.compose.ui.unit.dp
19 | import androidx.compose.ui.unit.sp
20 | import com.toly1994.composeunit.R
21 | import com.toly1994.composeunit.widgets.Image.ImageContentScaleItem
22 |
23 | // "widgetId": 6,
24 | // "name": "修改单个子组件的对齐方式",
25 | // "subtitle":
26 | // BoxScope 中定义了 Modifier.align, 通过它可以修改某一组件的对齐方式。本案例中内容底部居中,红色组件在右上方。
27 |
28 | @SuppressLint("SuspiciousIndentation")
29 | @Composable
30 | fun BoxNode2() {
31 | val colors = arrayOf(Color.Red, Color.Yellow , Color.Blue, Color.Green)
32 | Box(
33 | Modifier.width(250.dp).height(100.dp).background(Color(0xffEFEFEF)),
34 | contentAlignment = Alignment.BottomCenter
35 | ) {
36 | Spacer(Modifier.width(60.dp).height(60.dp).background(colors[3]))
37 | Spacer(Modifier.width(50.dp).height(50.dp).background(colors[2]))
38 | Spacer(Modifier.width(40.dp).height(40.dp).background(colors[1]))
39 | Spacer(Modifier.width(30.dp).height(30.dp).background(colors[0])
40 | .align(Alignment.TopEnd))
41 | }
42 | }
43 |
44 | @Preview
45 | @Composable
46 | fun BoxNode2Preview() {
47 | BoxNode2()
48 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/home/UnitHomePage.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.home
2 |
3 | import android.util.Log
4 | import androidx.compose.foundation.ScrollState
5 | import androidx.compose.foundation.clickable
6 | import androidx.compose.foundation.layout.*
7 | import androidx.compose.foundation.lazy.LazyColumn
8 | import androidx.compose.foundation.lazy.itemsIndexed
9 | import androidx.compose.foundation.verticalScroll
10 | import androidx.compose.runtime.Composable
11 | import androidx.compose.runtime.collectAsState
12 | import androidx.compose.ui.Modifier
13 | import androidx.compose.ui.unit.dp
14 | import androidx.lifecycle.viewmodel.compose.viewModel
15 | import com.toly1994.composeunit.layouts.UnitWidgetItemV1
16 | import com.toly1994.composeunit.models.WidgetModel
17 | import com.toly1994.composeunit.repository.memory.MemoryWidgetDataStore
18 |
19 | @Composable
20 | fun HomeWidgetList() {
21 | Column(
22 | Modifier
23 | .verticalScroll(ScrollState(0))
24 | .padding(bottom = 20.dp)
25 | ) {
26 | MemoryWidgetDataStore.allWidget.forEach { widget ->
27 | Box(modifier = Modifier.padding(top = 10.dp)) {
28 | UnitWidgetItemV1(model = widget)
29 | }
30 | }
31 | }
32 | }
33 |
34 | @Composable
35 | fun HomeLazyWidgetList(
36 | viewModel: WidgetViewModel = viewModel(),
37 | onTapItem: (WidgetModel) -> Unit,
38 | ) {
39 | val data = viewModel.uiState.collectAsState().value.models
40 | LazyColumn(
41 | verticalArrangement = Arrangement.spacedBy(10.dp),
42 | contentPadding = PaddingValues(top = 10.dp, bottom = 10.dp)
43 | ) {
44 | itemsIndexed(data) { index, widget ->
45 | UnitWidgetItemV1(model = widget,
46 | modifier = Modifier.clickable {
47 | onTapItem(widget)
48 | })
49 | Log.d("HomeLazyWidgetList", "$index")
50 | }
51 | }
52 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/details/NodeViewModel.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.details
2 |
3 | import androidx.lifecycle.ViewModel
4 | import androidx.lifecycle.viewModelScope
5 | import androidx.navigation.NavHostController
6 | import com.toly1994.composeunit.app.navigation.UnitRoute
7 | import com.toly1994.composeunit.models.NodeModel
8 | import com.toly1994.composeunit.models.WidgetModel
9 | import com.toly1994.composeunit.repository.NodeRepository
10 | import com.toly1994.composeunit.repository.impl.DbNodeRepository
11 | import com.toly1994.composeunit.repository.impl.MemoryNodeRepository
12 | import kotlinx.coroutines.flow.MutableStateFlow
13 | import kotlinx.coroutines.flow.StateFlow
14 | import kotlinx.coroutines.flow.catch
15 | import kotlinx.coroutines.launch
16 |
17 | class NodeViewModel(
18 | private val repository: NodeRepository = MemoryNodeRepository()
19 | // private val repository: NodeRepository = DbNodeRepository()
20 | ) : ViewModel() {
21 | // 状态数据
22 | private val _uiState = MutableStateFlow(NodeModelState())
23 | val uiState: StateFlow = _uiState
24 |
25 | fun handleEnterWidget(model: WidgetModel, topNavCtrl: NavHostController) {
26 | viewModelScope.launch {
27 | repository.queryNodeByWidgetId(model.id)
28 | .catch { ex ->
29 | _uiState.value = NodeModelState(
30 | error = ex.message,
31 | widget = model
32 | )
33 | }
34 | .collect { data ->
35 | _uiState.value = NodeModelState(
36 | widget = model,
37 | nodes = data
38 | )
39 | topNavCtrl.navigate(UnitRoute.widgetDetail)
40 | }
41 | }
42 | }
43 | }
44 |
45 | data class NodeModelState(
46 | val widget: WidgetModel? = null,
47 | val nodes: List = listOf(),
48 | val error: String? = null
49 | )
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/layouts/github_search/view_model/NodeViewModel.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.layouts.github_search.view_model
2 |
3 | import android.util.Log
4 | import androidx.lifecycle.ViewModel
5 | import androidx.lifecycle.viewModelScope
6 | import com.toly1994.composeunit.layouts.github_search.repository.GithubRepository
7 | import com.toly1994.composeunit.layouts.github_search.repository.models.GithubRepo
8 | import kotlinx.coroutines.flow.MutableStateFlow
9 | import kotlinx.coroutines.flow.StateFlow
10 | import kotlinx.coroutines.flow.catch
11 | import kotlinx.coroutines.launch
12 |
13 | class GithubSearchViewModel(
14 | private val repository: GithubRepository = GithubRepository()
15 | ) : ViewModel() {
16 |
17 | // 状态数据
18 | private val _uiState = MutableStateFlow(GithubRepoUIState.Init)
19 | val uiState: StateFlow = _uiState
20 |
21 | fun searchRepositoryByUserName(arg: String) {
22 | if (arg == "") {
23 | _uiState.value = GithubRepoUIState.Init
24 | return
25 | }
26 | viewModelScope.launch {
27 | _uiState.value = GithubRepoUIState.Loading
28 | repository.getRepositoryByUser(arg)
29 | .catch { ex ->
30 | _uiState.value = GithubRepoUIState.Error(
31 | error = ex.message,
32 | )
33 | }
34 | .collect { data ->
35 | Log.d("RepositoryByUserName", "searchRepositoryByUserName: ${data.size}")
36 | _uiState.value = GithubRepoUIState.Fill(
37 | repos = data
38 | )
39 | }
40 | }
41 | }
42 | }
43 |
44 | sealed class GithubRepoUIState{
45 | data class Fill(
46 | val repos: List = listOf(),
47 | ):GithubRepoUIState()
48 |
49 | object Loading : GithubRepoUIState()
50 |
51 | data class Error(
52 | val error: String? = null
53 | ):GithubRepoUIState()
54 |
55 | object Init:GithubRepoUIState()
56 | }
--------------------------------------------------------------------------------
/highlight/src/main/java/com/neo/highlight/util/scheme/LinkScheme.java:
--------------------------------------------------------------------------------
1 | package com.neo.highlight.util.scheme;
2 |
3 | import android.text.TextPaint;
4 | import android.text.style.URLSpan;
5 |
6 | import androidx.annotation.ColorInt;
7 | import androidx.annotation.NonNull;
8 |
9 | import com.neo.highlight.util.scheme.base.BaseScheme;
10 | import com.neo.highlight.util.scheme.contract.LinkSchemeContract;
11 |
12 | import java.util.regex.Pattern;
13 |
14 | /**
15 | * Pain and makes clickable links
16 | * @author Irineu A. Silva
17 | */
18 | final public class LinkScheme extends BaseScheme implements LinkSchemeContract {
19 |
20 | private boolean painText = true;
21 |
22 | private boolean painTextUnderline = true;
23 |
24 | @ColorInt
25 | private int painTextColor = -1;
26 |
27 | public LinkScheme() {
28 | super(Pattern.compile("\\bhttps?://[^\\s]+\\b/?"));
29 | }
30 |
31 | @Override
32 | public Object getSpan(@NonNull CharSequence text, int start, int end) {
33 | return new URLSpan(text.toString()) {
34 | @Override
35 | public void updateDrawState(@NonNull TextPaint ds) {
36 |
37 | if (painText) {
38 |
39 | if (painTextColor == -1) {
40 | ds.setColor(ds.linkColor);
41 | } else {
42 | ds.setColor(painTextColor);
43 | }
44 |
45 | ds.setUnderlineText(painTextUnderline);
46 | };
47 | }
48 | };
49 | }
50 |
51 | //override LinkSchemeContract
52 | @Override
53 | public LinkScheme setPainText(boolean painText) {
54 | this.painText = painText;
55 | return this;
56 | }
57 |
58 | @Override
59 | public LinkScheme setPainTextColor(@ColorInt int painTextColor) {
60 | this.painTextColor = painTextColor;
61 | return setPainText(true);
62 | }
63 |
64 | @Override
65 | public LinkScheme setPainTextUnderline(boolean painTextUnderline) {
66 | this.painTextUnderline = painTextUnderline;
67 | return this;
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/highlight/src/main/java/com/neo/highlight/util/scheme/base/BaseScheme.java:
--------------------------------------------------------------------------------
1 | package com.neo.highlight.util.scheme.base;
2 |
3 | import androidx.annotation.NonNull;
4 | import androidx.annotation.Nullable;
5 |
6 | import com.neo.highlight.core.Scheme;
7 | import com.neo.highlight.util.scheme.contract.SchemeScope;
8 |
9 | import java.util.ArrayList;
10 | import java.util.Arrays;
11 | import java.util.List;
12 | import java.util.regex.Pattern;
13 |
14 | /**
15 | * Base to schemes
16 | * @author Irineu A. Silva
17 | */
18 | abstract public class BaseScheme implements Scheme, SchemeScope {
19 |
20 | @Nullable
21 | private List scopeSchemes;
22 |
23 | @Nullable
24 | private final Pattern pattern;
25 |
26 | private boolean clearOldSpan = false;
27 |
28 | public BaseScheme(@Nullable Pattern pattern) {
29 | this.pattern = pattern;
30 | }
31 |
32 | //override Scheme
33 |
34 | @Nullable
35 | @Override
36 | public Pattern getRegex() {
37 | return pattern;
38 | }
39 |
40 |
41 | @Override
42 | public boolean getClearOldSpan() {
43 | return clearOldSpan;
44 | }
45 |
46 | @NonNull
47 | @Override
48 | public BaseScheme setClearOldSpan(boolean clearOldSpan) {
49 | this.clearOldSpan = clearOldSpan;
50 | return this;
51 | }
52 |
53 | //override ScopeSchemeContract
54 |
55 | @Nullable
56 | @Override
57 | public List getScopeSchemes() {
58 | return scopeSchemes;
59 | }
60 |
61 | @Override
62 | public void setScopeSchemes(@Nullable List schemes) {
63 | this.scopeSchemes = schemes;
64 | }
65 |
66 | @Override
67 | public BaseScheme addScopeScheme(@NonNull Scheme... schemes) {
68 | if (scopeSchemes == null) {
69 | scopeSchemes = new ArrayList<>();
70 | }
71 |
72 | scopeSchemes.addAll(Arrays.asList(schemes));
73 | return this;
74 | }
75 |
76 | @Override
77 | public BaseScheme clearScopeSchemes() {
78 | if (scopeSchemes != null) {
79 | scopeSchemes.clear();
80 | }
81 | return this;
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/layouts/counter/CounterPageV0.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.layouts.counter
2 |
3 |
4 | import android.annotation.SuppressLint
5 | import androidx.compose.foundation.layout.Arrangement
6 | import androidx.compose.foundation.layout.Column
7 | import androidx.compose.foundation.layout.fillMaxHeight
8 | import androidx.compose.foundation.layout.fillMaxWidth
9 | import androidx.compose.material.*
10 | import androidx.compose.material.icons.Icons
11 | import androidx.compose.material.icons.rounded.Add
12 | import androidx.compose.runtime.Composable
13 | import androidx.compose.runtime.MutableState
14 | import androidx.compose.runtime.mutableStateOf
15 | import androidx.compose.runtime.remember
16 | import androidx.compose.ui.Alignment
17 | import androidx.compose.ui.Modifier
18 | import androidx.compose.ui.graphics.Color
19 | import androidx.compose.ui.text.TextStyle
20 | import androidx.compose.ui.unit.sp
21 |
22 | // V0 计数器
23 |
24 | @SuppressLint("UnusedMaterialScaffoldPaddingParameter")
25 | @Composable
26 | fun CounterPageV0(title: String) {
27 | val count: MutableState = remember { mutableStateOf(0) }
28 | Scaffold(
29 | topBar = {
30 | TopAppBar(
31 | title = { Text(title) },
32 | )
33 | },
34 | floatingActionButton = {
35 | FloatingActionButton(
36 | backgroundColor = MaterialTheme.colors.primary,
37 | content = {
38 | Icon(Icons.Rounded.Add, "")
39 | },
40 | onClick = { count.value++ }
41 | )
42 | })
43 | {
44 | Column(
45 | modifier = Modifier
46 | .fillMaxHeight()
47 | .fillMaxWidth(),
48 | verticalArrangement = Arrangement.Center,
49 | horizontalAlignment = Alignment.CenterHorizontally
50 | ) {
51 | Text(text = "You have pushed the button this many times:")
52 | Text(
53 | text = "$count", style = TextStyle(
54 | fontSize = 36.sp,
55 | color = Color.Gray
56 | )
57 | )
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.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 |
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/doing/Doing.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.doing
2 |
3 | import androidx.compose.foundation.layout.*
4 | import androidx.compose.material.Icon
5 | import androidx.compose.material.MaterialTheme
6 | import androidx.compose.material.Text
7 | import androidx.compose.material.icons.Icons
8 | import androidx.compose.material.icons.filled.Build
9 | import androidx.compose.material.icons.filled.ThumbUp
10 | import androidx.compose.material.icons.filled.Warning
11 | import androidx.compose.material.icons.outlined.Build
12 | import androidx.compose.runtime.Composable
13 | import androidx.compose.ui.Alignment
14 | import androidx.compose.ui.Modifier
15 | import androidx.compose.ui.graphics.Color
16 | import androidx.compose.ui.res.stringResource
17 | import androidx.compose.ui.text.TextStyle
18 | import androidx.compose.ui.text.font.FontWeight
19 | import androidx.compose.ui.text.style.TextAlign
20 | import androidx.compose.ui.tooling.preview.Preview
21 | import androidx.compose.ui.unit.dp
22 | import androidx.compose.ui.unit.sp
23 |
24 | @Composable
25 | fun Doing(
26 | modifier: Modifier = Modifier,
27 | name:String
28 | ) {
29 | Column(
30 | modifier = modifier.fillMaxSize(),
31 | verticalArrangement = Arrangement.Center,
32 | horizontalAlignment = Alignment.CenterHorizontally
33 | ) {
34 |
35 | Icon(
36 | Icons.Outlined.Build, "",
37 | tint = Color(0xffC5C5C5),
38 | modifier = Modifier.size(80.dp,80.dp))
39 | Text(
40 | modifier = Modifier.padding(12.dp),
41 | text = name,
42 | style = TextStyle(
43 | fontWeight = FontWeight.Bold,
44 | fontSize = 20.sp,
45 | color = Color(0xff5A576C),
46 | ),
47 | textAlign = TextAlign.Center,
48 | )
49 | Text(
50 | modifier = Modifier.padding(horizontal = 8.dp),
51 | text = "功能正在开发之中,敬请期待...",
52 | style = MaterialTheme.typography.body1,
53 | textAlign = TextAlign.Center,
54 | color = Color(0xffC5C5C5)
55 | )
56 | }
57 | }
58 |
59 | @Preview
60 | @Composable
61 | fun ComingSoonPreview() {
62 | Doing(name="布局集录")
63 | }
64 |
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/widgets/Text/node5.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.widgets.Text
2 |
3 | import androidx.compose.foundation.background
4 | import androidx.compose.foundation.layout.*
5 | import androidx.compose.material.Text
6 | import androidx.compose.runtime.Composable
7 | import androidx.compose.ui.Alignment
8 | import androidx.compose.ui.Modifier
9 | import androidx.compose.ui.graphics.Color
10 | import androidx.compose.ui.text.style.TextAlign
11 | import androidx.compose.ui.text.style.TextDecoration
12 | import androidx.compose.ui.tooling.preview.Preview
13 | import androidx.compose.ui.unit.dp
14 | import androidx.compose.ui.unit.sp
15 |
16 | // "widgetId": 1,
17 | // "name": "文字对齐与行高",
18 | // "subtitle":
19 | // 【textAlign】: 文字对齐 【TextAlign?】
20 | // 【lineHeight】 : 行高 【TextUnit】
21 |
22 |
23 | @Composable
24 | fun TextNode5() {
25 | val data = arrayOf(
26 | TextAlign.Start,
27 | TextAlign.Center,
28 | TextAlign.End,
29 | TextAlign.Justify,
30 | TextAlign.Right,
31 | TextAlign.Left,
32 | )
33 |
34 | Column {
35 | for (index in data.indices step 2) {
36 | Row(
37 | Modifier.fillMaxWidth(),
38 | horizontalArrangement = Arrangement.SpaceEvenly,
39 | verticalAlignment = Alignment.CenterVertically
40 | ) {
41 | TextAlignItem(data[index])
42 | TextAlignItem(data[index + 1])
43 | }
44 | }
45 | }
46 | }
47 |
48 | @Composable
49 | fun TextAlignItem(align: TextAlign) {
50 | Column(horizontalAlignment = Alignment.CenterHorizontally) {
51 | Box(
52 | modifier = Modifier.width(150.dp).height(90.dp)
53 | .padding(bottom = 3.dp).background(Color(0xffEFEFEF))
54 | ) {
55 | Text(
56 | text = "ComposeUnit is an application for learn Compose.",
57 | textAlign = align,
58 | lineHeight = 20.sp
59 | )
60 | }
61 | Text(text = "TextAlign.$align", color = Color.Gray, fontSize = 12.sp)
62 | Spacer(modifier = Modifier.height(5.dp))
63 | }
64 | }
65 |
66 | @Preview
67 | @Composable
68 | fun TextNode5Preview() {
69 | TextNode5()
70 | }
71 |
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/layouts/counter/CounterPageV1.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.layouts.counter
2 |
3 |
4 | import androidx.compose.foundation.layout.Arrangement
5 | import androidx.compose.foundation.layout.Column
6 | import androidx.compose.foundation.layout.fillMaxHeight
7 | import androidx.compose.foundation.layout.fillMaxWidth
8 | import androidx.compose.material.*
9 | import androidx.compose.material.icons.Icons
10 | import androidx.compose.material.icons.rounded.Add
11 | import androidx.compose.runtime.Composable
12 | import androidx.compose.runtime.MutableState
13 | import androidx.compose.runtime.mutableStateOf
14 | import androidx.compose.runtime.remember
15 | import androidx.compose.ui.Alignment
16 | import androidx.compose.ui.Modifier
17 | import androidx.compose.ui.graphics.Color
18 | import androidx.compose.ui.text.TextStyle
19 | import androidx.compose.ui.unit.sp
20 |
21 | // 计数器: V1 版
22 | // 拆分组件,明确结构
23 |
24 | @Composable
25 | fun CounterPageV1(title: String) {
26 | val count: MutableState = remember { mutableStateOf(0) }
27 | Scaffold(
28 | topBar = { HomeTopBar(title) },
29 | floatingActionButton = {
30 | HomeFab(onClick = { count.value++ })
31 | })
32 | { HomeContent(count.value) }
33 | }
34 |
35 | // 对于比较简单的构建逻辑
36 | // 单独抽离组件就会显得多此一举
37 | @Composable
38 | fun HomeTopBar(title: String) {
39 | TopAppBar(
40 | title = { Text(title) },
41 | )
42 | }
43 |
44 | @Composable
45 | fun HomeFab(onClick: () -> Unit) {
46 | FloatingActionButton(
47 | backgroundColor = MaterialTheme.colors.primary,
48 | content = {
49 | Icon(Icons.Rounded.Add, "")
50 | },
51 | onClick = onClick
52 | )
53 | }
54 |
55 | @Composable
56 | fun HomeContent(count: Int) {
57 | Column(
58 | modifier = Modifier
59 | .fillMaxHeight()
60 | .fillMaxWidth(),
61 | verticalArrangement = Arrangement.Center,
62 | horizontalAlignment = Alignment.CenterHorizontally
63 | ) {
64 | Text(text = "You have pushed the button this many times:")
65 | Text(
66 | text = "$count", style = TextStyle(
67 | fontSize = 36.sp,
68 | color = Color.Gray
69 | )
70 | )
71 | }
72 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/widgets/Icon/node1.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.widgets.Icon
2 |
3 | import androidx.compose.foundation.Image
4 | import androidx.compose.foundation.layout.*
5 | import androidx.compose.material.Icon
6 | import androidx.compose.material.MaterialTheme
7 | import androidx.compose.material.Text
8 | import androidx.compose.material.icons.Icons
9 | import androidx.compose.material.icons.filled.Lock
10 | import androidx.compose.runtime.Composable
11 | import androidx.compose.ui.Modifier
12 | import androidx.compose.ui.graphics.Color
13 | import androidx.compose.ui.graphics.ImageBitmap
14 | import androidx.compose.ui.res.imageResource
15 | import androidx.compose.ui.res.painterResource
16 | import androidx.compose.ui.text.TextStyle
17 | import androidx.compose.ui.text.font.FontStyle
18 | import androidx.compose.ui.text.font.FontWeight
19 | import androidx.compose.ui.tooling.preview.Preview
20 | import androidx.compose.ui.unit.dp
21 | import androidx.compose.ui.unit.sp
22 | import com.toly1994.composeunit.R
23 |
24 | // "widgetId": 3,
25 | // "name": "图标的使用",
26 | // "subtitle":
27 | // 【painter】 : 画板加载 【Painter】
28 | // 【imageVector】: 矢量图片 【ImageVector】
29 | // 【bitmap】: 位图加载 【ImageBitmap】
30 | // 【tint】: 颜色 【Color】
31 | // 【contentDescription】: 无障碍描述 【String?】
32 |
33 | @Composable
34 | fun IconNode1() {
35 | Row(Modifier.fillMaxWidth(),
36 | horizontalArrangement = Arrangement.SpaceEvenly
37 | ) {
38 | Icon(
39 | painter = painterResource(id = R.mipmap.icon_code),
40 | contentDescription = null,
41 | tint = MaterialTheme.colors.primary,
42 | modifier = Modifier.size(40.dp, 40.dp),
43 | )
44 | Icon(
45 | imageVector = Icons.Default.Lock,
46 | modifier = Modifier.width(50.dp).height(50.dp),
47 | tint = Color.Blue,
48 | contentDescription = null,
49 | )
50 | val imageBitmap = ImageBitmap.imageResource(R.mipmap.icon_kafi)
51 | Icon(
52 | bitmap = imageBitmap,
53 | tint = Color.Magenta,
54 | modifier = Modifier.width(60.dp).height(60.dp),
55 | contentDescription = null,
56 | )
57 | }
58 | }
59 |
60 |
61 | @Preview
62 | @Composable
63 | fun TextNode1Preview() {
64 | IconNode1()
65 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/layouts/home/LayoutHomePage.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.home
2 |
3 |
4 | import androidx.compose.foundation.layout.*
5 | import androidx.compose.material.Scaffold
6 | import androidx.compose.material.Text
7 | import androidx.compose.material.TopAppBar
8 | import androidx.compose.runtime.Composable
9 | import androidx.compose.ui.Alignment
10 | import androidx.compose.ui.Modifier
11 | import androidx.compose.ui.graphics.Color
12 | import androidx.compose.ui.unit.dp
13 | import com.toly1994.composeunit.layouts.UnitWidgetItemV1
14 | import com.toly1994.composeunit.models.WidgetModel
15 |
16 | @Composable
17 | fun LayoutHomePage(title: String) {
18 | val text = WidgetModel(
19 | id = 2,
20 | name = "Text",
21 | nameCN = "文字组件",
22 | lever = 5,
23 | family = "无内容组件",
24 | collectd = true,
25 | info = "用于显示文字的组件。拥有的属性非常多,足够满足你的使用需求,核心样式由style属性控制。"
26 | )
27 |
28 | val column = WidgetModel(
29 | id = 2,
30 | name = "Column",
31 | nameCN = "列布局组件",
32 | lever = 4,
33 | family = "多内容组件",
34 | collectd = false,
35 | info = "排布方向为竖向的布局,可容纳多个组件,可以通过属性控制排布的对齐方式。"
36 | )
37 |
38 | val row = WidgetModel(
39 | id = 2,
40 | name = "Row",
41 | nameCN = "行布局组件",
42 | lever = 4,
43 | family = "多内容组件",
44 | collectd = true,
45 | info = "水平方向为竖向的布局,可容纳多个组件,可以通过属性控制排布的对齐方式。"
46 | )
47 |
48 | Scaffold(
49 | backgroundColor = Color(0xffF3F5F4),
50 | topBar = {
51 | TopAppBar(
52 | title = { Text(title) },
53 | )
54 | }) {
55 | Column(
56 | Modifier
57 | .padding(it)
58 | .fillMaxWidth()
59 | .fillMaxHeight(),
60 | verticalArrangement = Arrangement.Center,
61 | horizontalAlignment = Alignment.CenterHorizontally
62 | ) {
63 | UnitWidgetItemV1(model = text)
64 | Spacer(Modifier.height(10.dp))
65 | UnitWidgetItemV1(model =column)
66 | Spacer(Modifier.height(10.dp))
67 | UnitWidgetItemV1(model =row)
68 | // WeChatItem(banned = true)
69 | // JuejinArticleItemV0()
70 |
71 | // Text(text = "content")
72 | }
73 | }
74 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/widgets/Column/node2.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.widgets.Column
2 |
3 | import android.annotation.SuppressLint
4 | import androidx.compose.foundation.background
5 | import androidx.compose.foundation.layout.*
6 | import androidx.compose.material.Text
7 | import androidx.compose.runtime.Composable
8 | import androidx.compose.ui.Alignment
9 | import androidx.compose.ui.Modifier
10 | import androidx.compose.ui.graphics.Color
11 | import androidx.compose.ui.tooling.preview.Preview
12 | import androidx.compose.ui.unit.dp
13 | import androidx.compose.ui.unit.sp
14 |
15 | // "widgetId": 5,
16 | // "name": "列的水平对齐模式",
17 | // "subtitle":
18 | // 【horizontalAlignment】 : 水平对齐 【Alignment.Horizontal】
19 | @SuppressLint("SuspiciousIndentation")
20 | @Composable
21 | fun ColumnNode2() {
22 | val data = mapOf(
23 | Alignment.Start to "Start",
24 | Alignment.CenterHorizontally to "CenterHorizontally",
25 | Alignment.End to "End",
26 | )
27 | val keys = data.keys.toList()
28 | val values = data.values.toList()
29 | Column {
30 | for (index in data.keys.indices step 3) {
31 | Row(
32 | Modifier.fillMaxWidth(),
33 | horizontalArrangement = Arrangement.SpaceEvenly,
34 | verticalAlignment = Alignment.CenterVertically
35 | ) {
36 | ColumnHAItem(keys[index], values[index])
37 | if (index+ 1 < data.size)
38 | ColumnHAItem(keys[index + 1], values[index + 1])
39 | if (index+ 2 < data.size)
40 | ColumnHAItem(keys[index + 2], values[index + 2])
41 | }
42 | }
43 | }
44 | }
45 |
46 | @Composable
47 | fun ColumnHAItem(arrangement: Alignment.Horizontal, info: String) {
48 | val colors = arrayOf(Color.Red, Color.Blue, Color.Green)
49 | Column(horizontalAlignment = Alignment.CenterHorizontally) {
50 | Column(
51 | Modifier.width(80.dp).height(120.dp).background(Color(0xffEFEFEF)),
52 | horizontalAlignment = arrangement,
53 | ) {
54 | colors.forEach {
55 | Spacer(modifier = Modifier.width(30.dp).height(30.dp).background(it))
56 | }
57 | }
58 | Text(text = info, color = Color.Gray, fontSize = 12.sp)
59 | Spacer(modifier = Modifier.height(5.dp))
60 | }
61 | }
62 |
63 | @Preview
64 | @Composable
65 | fun ColumnNode2Preview() {
66 | ColumnNode2()
67 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/widgets/LazyColumn/node1.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.widgets.LazyColumn
2 |
3 | import android.util.Log
4 | import androidx.compose.foundation.background
5 | import androidx.compose.foundation.clickable
6 | import androidx.compose.foundation.layout.*
7 | import androidx.compose.foundation.lazy.LazyColumn
8 | import androidx.compose.foundation.lazy.itemsIndexed
9 | import androidx.compose.material.Divider
10 | import androidx.compose.material.Text
11 | import androidx.compose.runtime.Composable
12 | import androidx.compose.ui.Alignment
13 | import androidx.compose.ui.Modifier
14 | import androidx.compose.ui.graphics.Color
15 | import androidx.compose.ui.text.font.FontWeight
16 | import androidx.compose.ui.tooling.preview.Preview
17 | import androidx.compose.ui.unit.dp
18 | import androidx.compose.ui.unit.sp
19 | import com.toly1994.composeunit.layouts.UnitWidgetItemV1
20 | import okhttp3.internal.toHexString
21 |
22 | // "widgetId": 7,
23 | // "name": "延迟纵向列表基本使用",
24 | // "subtitle":
25 | // 【content】 : 内容 【LazyListScope.() -> Unit】
26 | // 【reverseLayout】: 是否反序 【Boolean】
27 | // 【contentPadding】: 门边距 【PaddingValues】
28 | // 【userScrollEnabled】: 是否允许滑动 【Boolean】
29 | // 【horizontalAlignment】: 水平对齐方式 【Alignment.Horizontal】
30 | // 【verticalArrangement】: 竖直对齐方式 【Arrangement.Vertical】
31 |
32 | @Composable
33 | fun LazyColumnNode1() {
34 | val count = 20
35 | val step = 256 / count
36 | val colors = mutableListOf()
37 | for (index in 0..count) {
38 | colors.add(0xffff00ff - index * step)
39 | }
40 | LazyColumn(
41 | modifier = Modifier.padding(horizontal = 20.dp).height(230.dp),
42 | userScrollEnabled = true,
43 | reverseLayout = false
44 | ) {
45 | itemsIndexed(colors) { _, value ->
46 | Box(modifier = Modifier
47 | .background(Color(value))
48 | .fillMaxWidth(),
49 | contentAlignment = Alignment.Center
50 | ){
51 | Text(
52 | modifier = Modifier.padding(vertical = 15.dp),
53 | text = "0x${value.toHexString()}",
54 | color = Color.White,
55 | fontSize = 18.sp,
56 | fontWeight = FontWeight.Bold
57 | )
58 | }
59 | }
60 | }
61 | }
62 |
63 | @Preview
64 | @Composable
65 | fun LazyColumnNode1Preview() {
66 | LazyColumnNode1()
67 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/widgets/LazyRow/node1.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.widgets.LazyRow
2 |
3 | import android.util.Log
4 | import androidx.compose.foundation.background
5 | import androidx.compose.foundation.clickable
6 | import androidx.compose.foundation.layout.*
7 | import androidx.compose.foundation.lazy.LazyColumn
8 | import androidx.compose.foundation.lazy.LazyRow
9 | import androidx.compose.foundation.lazy.itemsIndexed
10 | import androidx.compose.material.Divider
11 | import androidx.compose.material.Text
12 | import androidx.compose.runtime.Composable
13 | import androidx.compose.ui.Alignment
14 | import androidx.compose.ui.Modifier
15 | import androidx.compose.ui.graphics.Color
16 | import androidx.compose.ui.text.font.FontWeight
17 | import androidx.compose.ui.tooling.preview.Preview
18 | import androidx.compose.ui.unit.dp
19 | import androidx.compose.ui.unit.sp
20 | import com.toly1994.composeunit.layouts.UnitWidgetItemV1
21 | import okhttp3.internal.toHexString
22 |
23 | // "widgetId": 8,
24 | // "name": "延迟横向列表基本使用",
25 | // "subtitle":
26 | // 【content】 : 内容 【LazyListScope.() -> Unit】
27 | // 【reverseLayout】: 是否反序 【Boolean】
28 | // 【contentPadding】: 门边距 【PaddingValues】
29 | // 【userScrollEnabled】: 是否允许滑动 【Boolean】
30 | // 【horizontalAlignment】: 水平对齐方式 【Alignment.Horizontal】
31 | // 【verticalArrangement】: 竖直对齐方式 【Arrangement.Vertical】
32 |
33 | @Composable
34 | fun LazyRowNode1() {
35 | val count = 32
36 | val step = 256 / count
37 | val colors = mutableListOf()
38 | for (index in 0..count) {
39 | colors.add(0xffff00ff - index * step)
40 | }
41 | LazyRow(
42 | modifier = Modifier.padding(horizontal = 20.dp).height(60.dp),
43 | userScrollEnabled = true,
44 | reverseLayout = false
45 | ) {
46 | itemsIndexed(colors) { index, value ->
47 | Box(modifier = Modifier
48 | .background(Color(value))
49 | .fillMaxHeight(),
50 | contentAlignment = Alignment.Center
51 | ){
52 | Text(
53 | modifier = Modifier.padding(horizontal = 15.dp),
54 | text = index.toString(),
55 | color = Color.White,
56 | fontSize = 18.sp,
57 | fontWeight = FontWeight.Bold
58 | )
59 | }
60 | }
61 | }
62 | }
63 |
64 | @Preview
65 | @Composable
66 | fun LazyRowNode1Node1Preview() {
67 | LazyRowNode1()
68 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/widgets/Image/node1.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.widgets.Image
2 |
3 | import androidx.compose.foundation.Image
4 | import androidx.compose.foundation.layout.*
5 | import androidx.compose.material.Text
6 | import androidx.compose.material.icons.Icons
7 | import androidx.compose.material.icons.filled.Lock
8 | import androidx.compose.runtime.Composable
9 | import androidx.compose.ui.Modifier
10 | import androidx.compose.ui.graphics.Color
11 | import androidx.compose.ui.graphics.ImageBitmap
12 | import androidx.compose.ui.graphics.vector.ImageVector
13 | import androidx.compose.ui.layout.ContentScale
14 | import androidx.compose.ui.res.imageResource
15 | import androidx.compose.ui.res.painterResource
16 | import androidx.compose.ui.res.vectorResource
17 | import androidx.compose.ui.text.TextStyle
18 | import androidx.compose.ui.text.font.FontStyle
19 | import androidx.compose.ui.text.font.FontWeight
20 | import androidx.compose.ui.tooling.preview.Preview
21 | import androidx.compose.ui.unit.dp
22 | import androidx.compose.ui.unit.sp
23 | import com.toly1994.composeunit.R
24 |
25 | // "widgetId": 2,
26 | // "name": "图片加载方式",
27 | // "subtitle":
28 | // 【painter】 : 画板加载 【Painter】
29 | // 【imageVector】: 矢量图片 【ImageVector】
30 | // 【bitmap】: 位图加载 【ImageBitmap】
31 | // 【alpha】: 透明度 【Float】
32 | // 【contentDescription】: 无障碍描述 【String?】
33 |
34 | @Composable
35 | fun ImageNode1() {
36 | Row(Modifier.fillMaxWidth(),
37 | horizontalArrangement = Arrangement.SpaceEvenly
38 | ) {
39 | Image(
40 | painter = painterResource(id = R.mipmap.logo),
41 | modifier = Modifier.width(60.dp).height(60.dp),
42 | contentDescription = null,
43 | )
44 | Image(
45 | imageVector = Icons.Default.Lock,
46 | modifier = Modifier.width(60.dp).height(60.dp),
47 | contentDescription = null,
48 | )
49 | val imageBitmap = ImageBitmap.imageResource(R.mipmap.icon_head)
50 | Image(
51 | bitmap = imageBitmap,
52 | modifier = Modifier.width(60.dp).height(60.dp),
53 | contentDescription = null,
54 | )
55 | Image(
56 | painter = painterResource(id = R.mipmap.logo),
57 | modifier = Modifier.width(60.dp).height(60.dp),
58 | alpha = 0.5f,
59 | contentDescription = null,
60 | )
61 | }
62 | }
63 |
64 | @Preview
65 | @Composable
66 | fun ImageNode1Preview() {
67 | ImageNode1()
68 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/layouts/github_search/views/GithubSearchPage.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.layouts.github_search.views
2 |
3 | import android.annotation.SuppressLint
4 | import androidx.compose.foundation.layout.*
5 | import androidx.compose.foundation.lazy.LazyColumn
6 | import androidx.compose.foundation.lazy.itemsIndexed
7 | import androidx.compose.material.*
8 | import androidx.compose.runtime.*
9 | import androidx.compose.ui.Alignment
10 | import androidx.compose.ui.Modifier
11 | import androidx.compose.ui.text.font.FontWeight
12 | import androidx.compose.ui.unit.dp
13 | import androidx.compose.ui.unit.sp
14 | import androidx.lifecycle.viewmodel.compose.viewModel
15 | import com.toly1994.composeunit.layouts.github_search.repository.models.GithubRepo
16 | import com.toly1994.composeunit.layouts.github_search.view_model.GithubRepoUIState
17 | import com.toly1994.composeunit.layouts.github_search.view_model.GithubSearchViewModel
18 |
19 | @SuppressLint("UnusedMaterialScaffoldPaddingParameter")
20 | @Composable
21 | fun GithubSearchPage(
22 | viewModel: GithubSearchViewModel = viewModel()
23 | ) {
24 | val state = viewModel.uiState.collectAsState().value
25 | Scaffold(
26 | topBar = {
27 | GithubSearchBar() {
28 | viewModel.searchRepositoryByUserName(it)
29 | }
30 | }
31 | ) {
32 | if(state is GithubRepoUIState.Loading){
33 | SimpleInfo(text = "Loading...")
34 | }
35 | if(state is GithubRepoUIState.Error){
36 | SimpleInfo(text = "Error")
37 | }
38 | if(state is GithubRepoUIState.Init){
39 | SimpleInfo(text = "请输入查询参数")
40 | }
41 | if(state is GithubRepoUIState.Fill){
42 | HomeLazyGithubRepoList(
43 | state.repos
44 | )
45 | }
46 | }
47 | }
48 |
49 | @Composable
50 | fun SimpleInfo(text:String){
51 | Box(
52 | modifier = Modifier.fillMaxWidth().fillMaxHeight(),
53 | contentAlignment = Alignment.Center
54 | ) {
55 | Text(text = text, fontSize = 18.sp, fontWeight = FontWeight.Bold)
56 | }
57 | }
58 |
59 | @Composable
60 | fun HomeLazyGithubRepoList(
61 | data: List
62 | ) {
63 | LazyColumn(
64 | verticalArrangement = Arrangement.spacedBy(10.dp),
65 | contentPadding = PaddingValues(top = 10.dp, bottom = 10.dp)
66 | ) {
67 | itemsIndexed(data) { _, item ->
68 | GithubRepoItem(item)
69 | }
70 | }
71 | }
72 |
73 |
74 |
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/app/navigation/RouterRes.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.app.navigation
2 |
3 | import androidx.compose.material.icons.Icons
4 | import androidx.compose.material.icons.filled.AccountBox
5 | import androidx.compose.material.icons.filled.Favorite
6 | import androidx.compose.material.icons.filled.Home
7 | import androidx.compose.material.icons.filled.Send
8 | import androidx.compose.ui.graphics.vector.ImageVector
9 | import com.toly1994.composeunit.R
10 |
11 | object UnitRoute {
12 | const val homeNav = "HomeNav"
13 | const val splash = "Splash"
14 | const val widgetDetail = "WidgetDetail"
15 | const val widget = "HomeNav/Widget"
16 | const val layout = "HomeNav/Layout"
17 | const val collect = "HomeNav/Collect"
18 | const val user = "HomeNav/User"
19 | }
20 |
21 | object RouterRes {
22 | val bottomNavData = listOf(
23 | BottomNavData(
24 | route = UnitRoute.widget,
25 | icon = Icons.Default.Home,
26 | text = "组件",
27 | ),
28 | BottomNavData(
29 | route = UnitRoute.layout,
30 | icon = Icons.Default.Send,
31 | text = "布局",
32 | ),
33 | BottomNavData(
34 | route = UnitRoute.collect,
35 | icon = Icons.Default.Favorite,
36 | text = "收藏",
37 | ),
38 | BottomNavData(
39 | route = UnitRoute.user,
40 | icon = Icons.Default.AccountBox,
41 | text = "我的",
42 | ),
43 | )
44 |
45 | val userMenuData = listOf(
46 | MenuItemData(
47 | resImg = R.mipmap.icon_app_setting,
48 | text = "设置中心"
49 | ),
50 | MenuItemData(
51 | resImg = R.mipmap.icon_data,
52 | text = "数据管理"
53 | ),
54 | MenuItemData(
55 | resImg = R.mipmap.icon_colloct,
56 | text = "我的收藏"
57 | ),
58 | MenuItemData(),
59 | MenuItemData(
60 | resImg = R.mipmap.icon_version,
61 | text = "版本信息"
62 | ),
63 | MenuItemData(
64 | resImg = R.mipmap.icon_about,
65 | text = "关于应用"
66 | ),
67 | MenuItemData(),
68 | MenuItemData(
69 | resImg = R.mipmap.icon_kafi,
70 | text = "联系本王"
71 | )
72 | )
73 | }
74 |
75 | data class BottomNavData(
76 | val route: String,
77 | val icon: ImageVector,
78 | val text: String
79 | )
80 |
81 | data class MenuItemData(
82 | val route: String? = null,
83 | val resImg: Int?=null,
84 | val text: String = ""
85 | )
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/widgets/LazyVerticalGrid/node1.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.widgets.LazyVerticalGrid
2 |
3 | import androidx.compose.foundation.background
4 | import androidx.compose.foundation.layout.*
5 | import androidx.compose.foundation.lazy.grid.GridCells
6 | import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
7 |
8 |
9 | import androidx.compose.material.Text
10 | import androidx.compose.runtime.Composable
11 | import androidx.compose.ui.Alignment
12 | import androidx.compose.ui.Modifier
13 | import androidx.compose.ui.graphics.Color
14 | import androidx.compose.ui.text.font.FontWeight
15 | import androidx.compose.ui.tooling.preview.Preview
16 | import androidx.compose.ui.unit.dp
17 | import androidx.compose.ui.unit.sp
18 | import okhttp3.internal.toHexString
19 |
20 | // "widgetId": 7,
21 | // "name": "延迟纵向网格基本使用",
22 | // "subtitle":
23 | // 【content】 : 内容 【LazyListScope.() -> Unit】
24 | // 【reverseLayout】: 是否反序 【Boolean】
25 | // 【columns】: 单元格配置 【GridCells】
26 | // 【contentPadding】: 门边距 【PaddingValues】
27 | // 【userScrollEnabled】: 是否允许滑动 【Boolean】
28 | // 【horizontalArrangement】: 水平间距 【Arrangement.Horizontal】
29 | // 【verticalArrangement】: 竖直间距 【Arrangement.Vertical】
30 |
31 | @Composable
32 | fun LazyVerticalGridNode1() {
33 | val count = 64
34 | val step = 256 / count
35 | val colors = mutableListOf()
36 | for (index in 0..count) {
37 | colors.add(0xffff00ff - index * step)
38 | }
39 | LazyVerticalGrid(
40 | modifier = Modifier
41 | .padding(horizontal = 20.dp)
42 | .height(230.dp),
43 | userScrollEnabled = true,
44 | reverseLayout = false,
45 | columns = GridCells.Fixed(3),
46 | verticalArrangement = Arrangement.spacedBy(4.dp),
47 | horizontalArrangement = Arrangement.spacedBy(4.dp),
48 | ) {
49 | items(colors.size,) {
50 | index ->
51 | Box(
52 | modifier = Modifier
53 | .background(Color(colors[index]))
54 | .fillMaxWidth(),
55 | contentAlignment = Alignment.Center
56 | ) {
57 | Text(
58 | modifier = Modifier.padding(vertical = 15.dp),
59 | text = "0x${colors[index].toHexString()}",
60 | color = Color.White,
61 | fontSize = 16.sp,
62 | fontWeight = FontWeight.Bold
63 | )
64 | }
65 | }
66 | }
67 | }
68 |
69 | @Preview
70 | @Composable
71 | fun LazyVerticalGridPreview() {
72 | LazyVerticalGridNode1()
73 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/app/data_manager/DataManagePage.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.app.data_manager
2 |
3 | import androidx.compose.foundation.layout.*
4 | import androidx.compose.material.*
5 | import androidx.compose.runtime.Composable
6 | import androidx.compose.runtime.rememberCoroutineScope
7 | import androidx.compose.ui.Alignment
8 | import androidx.compose.ui.Modifier
9 | import com.toly1994.composeunit.layouts.counter.CountViewModel
10 | import com.toly1994.composeunit.repository.database.LocalDb
11 | import com.toly1994.composeunit.repository.database.entity.WidgetPo
12 | import com.toly1994.composeunit.repository.memory.MemoryNodeDataStore
13 | import com.toly1994.composeunit.repository.memory.MemoryWidgetDataStore
14 | import kotlinx.coroutines.launch
15 |
16 | @Composable
17 | fun DataManagePage(
18 | ) {
19 | // val db = Room.databaseBuilder(this,ComposeUnitDB::class.java,"compose_unit").allowMainThreadQueries().build()
20 | // db.widgetDao().insertAll(MemoryWidgetDataStore.allWidget.first().toPo())
21 |
22 | val scaffoldState = rememberScaffoldState()
23 | val scope = rememberCoroutineScope()
24 |
25 | Scaffold(
26 | scaffoldState = scaffoldState,
27 | topBar = { TopAppBar(title = { Text("数据库测试") }) }
28 | ) {
29 | Column(Modifier.padding(it).fillMaxWidth().fillMaxHeight(),
30 | horizontalAlignment = Alignment.CenterHorizontally,
31 | verticalArrangement = Arrangement.Center
32 | ) {
33 | Button(onClick = {
34 | addWidget()
35 | scope.launch {
36 | scaffoldState.snackbarHostState.showSnackbar("插入成功!")
37 | }
38 | // scaffoldState.s
39 | }) {
40 | Text(text = "添加组件数据")
41 | }
42 | Button(onClick = { addNode()
43 | scope.launch {
44 | scaffoldState.snackbarHostState.showSnackbar("插入成功!")
45 | }
46 | }) {
47 | Text(text = "添加节点数据")
48 | }
49 | }
50 | }
51 | }
52 |
53 | private fun addWidget(){
54 | val dao = LocalDb.database.widgetDao();
55 | MemoryWidgetDataStore.allWidget.forEach(){
56 | dao.insertAll(it.toPo())
57 | }
58 | }
59 |
60 | //private fun findWidget(): List{
61 | //// val dao = LocalDb.database.widgetDao();
62 | //// return dao.queryAll()
63 | //}
64 |
65 | private fun addNode(){
66 | val dao = LocalDb.database.nodeDao();
67 | MemoryNodeDataStore.allNodes.forEach(){
68 | dao.insertAll(it)
69 | }
70 |
71 | // val dao = LocalDb.database.widgetDao();
72 | // dao.deleteAll()
73 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/widgets/Row/node2.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.widgets.Row
2 |
3 | import android.annotation.SuppressLint
4 | import androidx.compose.foundation.Image
5 | import androidx.compose.foundation.background
6 | import androidx.compose.foundation.layout.*
7 | import androidx.compose.material.Text
8 | import androidx.compose.runtime.Composable
9 | import androidx.compose.ui.Alignment
10 | import androidx.compose.ui.Modifier
11 | import androidx.compose.ui.graphics.Color
12 | import androidx.compose.ui.layout.ContentScale
13 | import androidx.compose.ui.res.painterResource
14 | import androidx.compose.ui.text.TextStyle
15 | import androidx.compose.ui.text.font.FontStyle
16 | import androidx.compose.ui.text.font.FontWeight
17 | import androidx.compose.ui.tooling.preview.Preview
18 | import androidx.compose.ui.unit.dp
19 | import androidx.compose.ui.unit.sp
20 | import com.toly1994.composeunit.R
21 | import com.toly1994.composeunit.widgets.Image.ImageContentScaleItem
22 |
23 | // "widgetId": 4,
24 | // "name": "行的竖直对齐模式",
25 | // "subtitle":
26 | // 【verticalAlignment】 : 竖直对齐 【Arrangement.Vertical】
27 | @SuppressLint("SuspiciousIndentation")
28 | @Composable
29 | fun RowNode2() {
30 | val data = mapOf(
31 | Alignment.Top to "Top",
32 | Alignment.CenterVertically to "Center",
33 | Alignment.Bottom to "Bottom",
34 | )
35 | val keys = data.keys.toList()
36 | val values = data.values.toList()
37 | Column {
38 | for (index in data.keys.indices step 2) {
39 | Row(
40 | Modifier.fillMaxWidth(),
41 | horizontalArrangement = Arrangement.SpaceEvenly,
42 | verticalAlignment = Alignment.CenterVertically
43 | ) {
44 | RowVAItem(keys[index],values[index])
45 | if(index Unit】
25 | // 【reverseLayout】: 是否反序 【Boolean】
26 | // 【rows】: 单元格配置 【GridCells】
27 | // 【contentPadding】: 门边距 【PaddingValues】
28 | // 【userScrollEnabled】: 是否允许滑动 【Boolean】
29 | // 【horizontalArrangement】: 水平间距 【Arrangement.Horizontal】
30 | // 【verticalArrangement】: 竖直间距 【Arrangement.Vertical】
31 |
32 | @Composable
33 | fun LazyHorizontalGridNode1() {
34 | val count = 64
35 | val step = 256 / count
36 | val colors = mutableListOf()
37 | for (index in 0..count) {
38 | colors.add(0xffff00ff - index * step)
39 | }
40 | LazyHorizontalGrid(
41 | modifier = Modifier
42 | .padding(horizontal = 20.dp)
43 | .height(230.dp),
44 | userScrollEnabled = true,
45 | reverseLayout = false,
46 | rows = GridCells.Fixed(3),
47 | verticalArrangement = Arrangement.spacedBy(4.dp),
48 | horizontalArrangement = Arrangement.spacedBy(4.dp),
49 | ) {
50 | items(colors.size) {
51 | index ->
52 | Box(
53 | modifier = Modifier
54 | .background(Color(colors[index]))
55 | .fillMaxWidth(),
56 | contentAlignment = Alignment.Center
57 | ) {
58 | Text(
59 | modifier = Modifier.padding(horizontal = 15.dp),
60 | text = "0x${colors[index].toHexString()}",
61 | color = Color.White,
62 | fontSize = 16.sp,
63 | fontWeight = FontWeight.Bold
64 | )
65 | }
66 | }
67 | }
68 | }
69 |
70 | @Preview
71 | @Composable
72 | fun LazyHorizontalGridPreview() {
73 | LazyHorizontalGridNode1()
74 | }
--------------------------------------------------------------------------------
/highlight/src/main/java/com/neo/highlight/util/scheme/FontScheme.java:
--------------------------------------------------------------------------------
1 | package com.neo.highlight.util.scheme;
2 |
3 | import android.content.Context;
4 | import android.graphics.Paint;
5 | import android.graphics.Typeface;
6 | import android.text.TextPaint;
7 | import android.text.style.TypefaceSpan;
8 |
9 | import androidx.annotation.FontRes;
10 | import androidx.annotation.NonNull;
11 | import androidx.annotation.Nullable;
12 | import androidx.core.content.res.ResourcesCompat;
13 |
14 | import com.neo.highlight.util.scheme.base.BaseScheme;
15 |
16 | import java.util.Objects;
17 | import java.util.regex.Pattern;
18 |
19 | final public class FontScheme extends BaseScheme {
20 |
21 | @NonNull
22 | private final Typeface typeface;
23 |
24 | private boolean keepStyle = true;
25 |
26 | public FontScheme(@Nullable Pattern pattern, @NonNull Typeface typeface) {
27 | super(pattern);
28 | this.typeface = typeface;
29 | }
30 |
31 | public FontScheme(@NonNull Typeface typeface) {
32 | super(null);
33 | this.typeface = typeface;
34 | }
35 |
36 | @NonNull
37 | @Override
38 | public Object getSpan(@NonNull CharSequence text, int start, int end) {
39 | return new TypefaceSpan("") {
40 |
41 | @Override
42 | public void updateDrawState(TextPaint paint) {
43 |
44 | if (keepStyle) {
45 | applyTypeFace(paint);
46 | } else {
47 | paint.setTypeface(typeface);
48 | }
49 | }
50 |
51 | private void applyTypeFace(Paint paint) {
52 | Typeface typefaceAnterior = paint.getTypeface();
53 |
54 | int styleAnterior;
55 |
56 | if (typefaceAnterior == null) {
57 | styleAnterior = 0;
58 | } else {
59 | styleAnterior = typefaceAnterior.getStyle();
60 | }
61 |
62 | int fake = styleAnterior & typeface.getStyle();
63 |
64 | if ((fake & Typeface.BOLD) != 0) {
65 | paint.setFakeBoldText(true);
66 | }
67 |
68 | if ((fake & Typeface.ITALIC) != 0) {
69 | paint.setTextSkewX(-0.25f);
70 | }
71 |
72 | paint.setTypeface(typeface);
73 | }
74 | };
75 | }
76 |
77 | public FontScheme setKeepStyle(boolean keepStyle) {
78 | this.keepStyle = keepStyle;
79 | return this;
80 | }
81 |
82 | @NonNull
83 | public static Typeface getFont(@NonNull Context context, @FontRes int fonResId) {
84 | return Objects.requireNonNull(ResourcesCompat.getFont(context, fonResId));
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/components/CodeHighlighter.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.app.utils
2 |
3 | import android.content.Context
4 | import android.widget.TextView
5 | import androidx.compose.runtime.Composable
6 | import androidx.compose.ui.viewinterop.AndroidView
7 | import androidx.core.content.ContextCompat
8 | import com.neo.highlight.core.Highlight
9 | import com.neo.highlight.core.Scheme
10 | import com.neo.highlight.util.scheme.ColorScheme
11 | import com.neo.highlight.util.scheme.Scope
12 | import com.toly1994.composeunit.R
13 | import java.util.regex.Pattern
14 |
15 | @Composable
16 | fun CodeHighlighter(code :String ) {
17 | AndroidView(factory = {
18 | val tv = TextView(it)
19 | val highlight = Highlight()
20 | highlight.schemes = getKotlinScheme(it)
21 | tv.text = code
22 | highlight.setSpan(tv)
23 | tv
24 | })
25 | }
26 |
27 |
28 | private fun getKotlinScheme(context: Context): List {
29 | val schemes: MutableList = ArrayList()
30 | //keywords
31 |
32 | schemes.add(
33 | ColorScheme(
34 | Pattern.compile("\\b(fun)|(val)|(var)|(sp)|(dp)|(private)\\b"),
35 | ContextCompat.getColor(context, R.color.keyword)
36 | )
37 | )
38 |
39 | // 数字
40 | schemes.add(
41 | Scope(
42 | Pattern.compile("\\w+")
43 | ).addScopeScheme(
44 | ColorScheme(
45 | Pattern.compile("^(\\d+\\.\\d+)|^(\\d+)"),
46 | ContextCompat.getColor(context, R.color.num)
47 | )
48 | )
49 | )
50 | // class
51 | schemes.add(
52 | Scope(
53 | Pattern.compile("\\w+")
54 | ).addScopeScheme(
55 | ColorScheme(
56 | Pattern.compile("^[A-Z](.*?)\\w+"),
57 | ContextCompat.getColor(context, R.color.clazz)
58 | )
59 | )
60 | )
61 |
62 | //function declaration
63 | schemes.add(
64 | Scope(
65 | Pattern.compile("\\b(fun)\\b\\s*\\b\\w+\\b\\([^()]*\\)")
66 | ).addScopeScheme(
67 | ColorScheme(
68 | Pattern.compile("\\w*(?=\\()"),
69 | ContextCompat.getColor(context, R.color.function)
70 | )
71 | )
72 | )
73 |
74 |
75 |
76 | //annotations
77 | schemes.add(
78 | ColorScheme(
79 | Pattern.compile("@.+"),
80 | ContextCompat.getColor(context, R.color.annotation)
81 | )
82 | )
83 |
84 | //strings
85 | schemes.add(
86 | ColorScheme(
87 | Pattern.compile("\"[^\"]*\""),
88 | ContextCompat.getColor(context, R.color.string)
89 | )
90 | )
91 | return schemes
92 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/app/navigation/UnitAppBar.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.app.navigation
2 |
3 | import androidx.compose.foundation.Image
4 | import androidx.compose.foundation.background
5 | import androidx.compose.foundation.border
6 | import androidx.compose.foundation.layout.*
7 | import androidx.compose.foundation.shape.CircleShape
8 | import androidx.compose.foundation.shape.RoundedCornerShape
9 | import androidx.compose.material.MaterialTheme
10 | import androidx.compose.material.Text
11 | import androidx.compose.material.TopAppBar
12 | import androidx.compose.runtime.Composable
13 | import androidx.compose.ui.Alignment
14 | import androidx.compose.ui.Modifier
15 | import androidx.compose.ui.draw.clip
16 | import androidx.compose.ui.draw.shadow
17 | import androidx.compose.ui.graphics.Color
18 | import androidx.compose.ui.layout.ContentScale
19 | import androidx.compose.ui.res.painterResource
20 | import androidx.compose.ui.text.font.FontWeight
21 | import androidx.compose.ui.unit.dp
22 | import androidx.compose.ui.unit.sp
23 | import com.toly1994.composeunit.R
24 |
25 | @Composable
26 | fun UnitAppBar(route:String?){
27 | when(route){
28 | UnitRoute.user -> UserPageAppBar()
29 | else -> TopAppBar(
30 | title = { Text("ComposeUnit") },
31 | )
32 | }
33 |
34 | }
35 |
36 |
37 | @Composable
38 | fun UserPageAppBar(){
39 | Box(contentAlignment = Alignment.BottomStart) {
40 | Column {
41 | Image(
42 | modifier = Modifier.fillMaxWidth().height(180.dp),
43 | contentScale = ContentScale.FillWidth,
44 | painter = painterResource(id = R.mipmap.base_draw),
45 | contentDescription = "",
46 | )
47 | Box(modifier = Modifier
48 | .fillMaxWidth()
49 | .height(50.dp)
50 | .background(Color.White),
51 | contentAlignment = Alignment.CenterEnd
52 |
53 | ){
54 | Text(
55 | modifier = Modifier.offset(x=(-30).dp),
56 | text = "张风捷特烈",
57 | fontSize = 18.sp,
58 | color = MaterialTheme.colors.primary,
59 | fontWeight = FontWeight.Bold)
60 | }
61 | }
62 | Image(
63 | modifier = Modifier
64 | .width(80.dp)
65 | .height(80.dp)
66 | .offset(40.dp, (-10).dp)
67 | .border(3.dp, Color.White, CircleShape)
68 | .shadow(elevation = 1.dp, shape = CircleShape),
69 | contentScale = ContentScale.FillWidth,
70 | painter = painterResource(id = R.mipmap.icon_head),
71 | contentDescription = "",
72 | )
73 | }
74 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/widgets/Image/node3.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.widgets.Image
2 |
3 | import android.annotation.SuppressLint
4 | import androidx.compose.foundation.Image
5 | import androidx.compose.foundation.background
6 | import androidx.compose.foundation.layout.*
7 | import androidx.compose.material.Text
8 | import androidx.compose.runtime.Composable
9 | import androidx.compose.ui.Alignment
10 | import androidx.compose.ui.Modifier
11 | import androidx.compose.ui.graphics.Color
12 | import androidx.compose.ui.layout.ContentScale
13 | import androidx.compose.ui.res.painterResource
14 | import androidx.compose.ui.tooling.preview.Preview
15 | import androidx.compose.ui.unit.dp
16 | import androidx.compose.ui.unit.sp
17 | import com.toly1994.composeunit.R
18 |
19 | // "widgetId": 2,
20 | // "name": "图片缩放模式",
21 | // "subtitle":
22 | // 【contentScale】 : 缩放模式 【ContentScale】
23 |
24 | @SuppressLint("SuspiciousIndentation")
25 | @Composable
26 | fun ImageNode3() {
27 | val data = mapOf(
28 | ContentScale.Fit to "Fit",
29 | ContentScale.Crop to "Crop",
30 | ContentScale.FillHeight to "FillHeight",
31 | ContentScale.FillWidth to "FillWidth",
32 | ContentScale.FillBounds to "FillBounds",
33 | ContentScale.None to "None",
34 | ContentScale.Inside to "Inside",
35 | )
36 | val keys = data.keys.toList();
37 | val values = data.values.toList();
38 | Column {
39 | for (index in data.keys.indices step 2) {
40 | Row(
41 | Modifier.fillMaxWidth(),
42 | horizontalArrangement = Arrangement.SpaceEvenly,
43 | verticalAlignment = Alignment.CenterVertically
44 | ) {
45 | ImageContentScaleItem(keys[index],values[index])
46 | if(index Unit】
28 | @SuppressLint("SuspiciousIndentation")
29 | @Composable
30 | fun RowNode1() {
31 | val data = mapOf(
32 | Arrangement.Center to "Center",
33 | Arrangement.SpaceBetween to "SpaceBetween",
34 | Arrangement.SpaceAround to "SpaceAround",
35 | Arrangement.SpaceEvenly to "SpaceEvenly",
36 | Arrangement.End to "End",
37 | Arrangement.Start to "Start",
38 | )
39 | val keys = data.keys.toList();
40 | val values = data.values.toList();
41 | Column {
42 | for (index in data.keys.indices step 2) {
43 | Row(
44 | Modifier.fillMaxWidth(),
45 | horizontalArrangement = Arrangement.SpaceEvenly,
46 | verticalAlignment = Alignment.CenterVertically
47 | ) {
48 | RowHAItem(keys[index],values[index])
49 | if(indexNUL 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 |
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/widgets/Image/node2.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.widgets.Image
2 |
3 | import android.annotation.SuppressLint
4 | import androidx.compose.foundation.Image
5 | import androidx.compose.foundation.background
6 | import androidx.compose.foundation.layout.*
7 | import androidx.compose.material.Text
8 | import androidx.compose.runtime.Composable
9 | import androidx.compose.ui.Alignment
10 | import androidx.compose.ui.Modifier
11 | import androidx.compose.ui.graphics.Color
12 | import androidx.compose.ui.layout.ContentScale
13 | import androidx.compose.ui.res.painterResource
14 | import androidx.compose.ui.tooling.preview.Preview
15 | import androidx.compose.ui.unit.dp
16 | import androidx.compose.ui.unit.sp
17 | import com.toly1994.composeunit.R
18 |
19 | // "widgetId": 2,
20 | // "name": "图片对齐模式",
21 | // "subtitle":
22 | // 【alignment】 : 对齐模式 【Alignment】
23 |
24 | @SuppressLint("SuspiciousIndentation")
25 | @Composable
26 | fun ImageNode2() {
27 | val data = mapOf(
28 | Alignment.Center to "Center",
29 | Alignment.CenterStart to "CenterStart",
30 | Alignment.CenterEnd to "CenterEnd",
31 | Alignment.TopCenter to "TopCenter",
32 | Alignment.BottomCenter to "BottomCenter",
33 | Alignment.BottomStart to "BottomStart",
34 | Alignment.BottomEnd to "BottomEnd",
35 | Alignment.TopStart to "TopStart",
36 | Alignment.TopEnd to "TopEnd",
37 |
38 | )
39 | val keys = data.keys.toList();
40 | val values = data.values.toList();
41 | Column {
42 | for (index in data.keys.indices step 3) {
43 | Row(
44 | Modifier.fillMaxWidth(),
45 | horizontalArrangement = Arrangement.SpaceEvenly,
46 | verticalAlignment = Alignment.CenterVertically
47 | ) {
48 | ImageAlignmentItem(keys[index],values[index])
49 | if(index+1 Unit】
28 |
29 | @SuppressLint("SuspiciousIndentation")
30 | @Composable
31 | fun ColumnNode1() {
32 | val data = mapOf(
33 | Arrangement.Top to "Center",
34 | Arrangement.SpaceBetween to "SpaceBetween",
35 | Arrangement.SpaceAround to "SpaceAround",
36 | Arrangement.SpaceEvenly to "SpaceEvenly",
37 | Arrangement.Bottom to "End",
38 | Arrangement.Center to "Start",
39 | )
40 | val keys = data.keys.toList();
41 | val values = data.values.toList();
42 | Column {
43 | for (index in data.keys.indices step 3) {
44 | Row(
45 | Modifier.fillMaxWidth(),
46 | horizontalArrangement = Arrangement.SpaceEvenly,
47 | verticalAlignment = Alignment.CenterVertically
48 | ) {
49 | ColumnVAItem(keys[index],values[index])
50 | if(index+1 0) {
90 |
91 | char c = editable.charAt(lineStart - 1);
92 |
93 | if (c == '\n') {
94 | break;
95 | }
96 |
97 | lineStart--;
98 | }
99 |
100 | return lineStart;
101 | }
102 |
103 | public static final String TAG = LinesTextWatcher.class.getSimpleName();
104 | }
105 |
106 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.application'
3 | id 'org.jetbrains.kotlin.android'
4 | id 'kotlin-kapt' // 添加 kapt
5 | }
6 |
7 | android {
8 | namespace 'com.toly1994.composeunit'
9 | compileSdk 33
10 |
11 | defaultConfig {
12 | applicationId "com.toly1994.composeunit"
13 | minSdk 21
14 | targetSdk 32
15 | versionCode 1
16 | versionName "1.0"
17 |
18 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
19 | vectorDrawables {
20 | useSupportLibrary true
21 | }
22 | }
23 |
24 | buildTypes {
25 | release {
26 | minifyEnabled false
27 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
28 | }
29 | }
30 | compileOptions {
31 | sourceCompatibility JavaVersion.VERSION_1_8
32 | targetCompatibility JavaVersion.VERSION_1_8
33 | }
34 | kotlinOptions {
35 | jvmTarget = '1.8'
36 | }
37 | buildFeatures {
38 | compose true
39 | }
40 | composeOptions {
41 | kotlinCompilerExtensionVersion '1.1.1'
42 | }
43 | packagingOptions {
44 | resources {
45 | excludes += '/META-INF/{AL2.0,LGPL2.1}'
46 | }
47 | }
48 | }
49 |
50 | dependencies {
51 | // room 数据库
52 | def room_version = "2.4.3"
53 | implementation "androidx.room:room-runtime:$room_version"
54 | kapt "androidx.room:room-compiler:$room_version"
55 | implementation "androidx.room:room-ktx:$room_version"
56 |
57 | // retrofit 网络请求
58 | implementation "com.squareup.retrofit2:retrofit:2.9.0"
59 | implementation "com.squareup.retrofit2:converter-gson:2.9.0"
60 |
61 | // 网络图片
62 | implementation "io.coil-kt:coil-compose:2.2.2"
63 |
64 | implementation project(":highlight")
65 | implementation 'androidx.core:core-ktx:1.7.0'
66 | implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1'
67 | implementation 'androidx.activity:activity-compose:1.6.0'
68 | implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.5.1'
69 |
70 |
71 | implementation "androidx.compose.ui:ui:$compose_ui_version"
72 | implementation "androidx.compose.ui:ui-tooling-preview:$compose_ui_version"
73 | implementation 'androidx.compose.material:material:1.3.0'
74 | implementation "androidx.navigation:navigation-compose:2.5.2"
75 |
76 | // 协程核心库
77 | implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4"
78 | // 协程Android支持库
79 | implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4"
80 | // 协程Java8支持库
81 | implementation "org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.6.4"
82 |
83 | testImplementation 'junit:junit:4.13.2'
84 | androidTestImplementation 'androidx.test.ext:junit:1.1.3'
85 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
86 | androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_ui_version"
87 | debugImplementation "androidx.compose.ui:ui-tooling:$compose_ui_version"
88 | debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_ui_version"
89 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/widgets/Image/node4.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.widgets.Image
2 |
3 | import android.annotation.SuppressLint
4 | import androidx.compose.foundation.Image
5 | import androidx.compose.foundation.background
6 | import androidx.compose.foundation.layout.*
7 | import androidx.compose.material.Text
8 | import androidx.compose.runtime.Composable
9 | import androidx.compose.ui.Alignment
10 | import androidx.compose.ui.Modifier
11 | import androidx.compose.ui.graphics.BlendMode
12 | import androidx.compose.ui.graphics.Color
13 | import androidx.compose.ui.graphics.ColorFilter
14 | import androidx.compose.ui.layout.ContentScale
15 | import androidx.compose.ui.res.painterResource
16 | import androidx.compose.ui.tooling.preview.Preview
17 | import androidx.compose.ui.unit.dp
18 | import androidx.compose.ui.unit.sp
19 | import com.toly1994.composeunit.R
20 |
21 | // "widgetId": 2,
22 | // "name": "颜色叠合模式",
23 | // "subtitle":
24 | // 【colorFilter】 : 缩放模式 【ColorFilter】
25 |
26 | @SuppressLint("SuspiciousIndentation")
27 | @Composable
28 | fun ImageNode4() {
29 | val data = arrayOf(
30 | BlendMode.Clear,BlendMode.Src,BlendMode.Dst,
31 | BlendMode.SrcOver,BlendMode.DstOver,BlendMode.SrcIn,
32 | BlendMode.DstIn,BlendMode.SrcOut,BlendMode.DstOut,
33 | BlendMode.SrcAtop,BlendMode.DstAtop,BlendMode.Xor,
34 | BlendMode.Plus,BlendMode.Modulate,BlendMode.Screen,
35 | BlendMode.Overlay,BlendMode.Darken,BlendMode.Lighten,
36 | BlendMode.ColorDodge,BlendMode.ColorBurn,BlendMode.Hardlight,
37 | BlendMode.Softlight,BlendMode.Difference,BlendMode.Exclusion,
38 | BlendMode.Multiply,BlendMode.Hue,BlendMode.Saturation,
39 | BlendMode.Color,BlendMode.Luminosity,)
40 | Column {
41 | for (index in data.indices step 5) {
42 | Row(
43 | Modifier.fillMaxWidth(),
44 | horizontalArrangement = Arrangement.SpaceEvenly,
45 | verticalAlignment = Alignment.CenterVertically
46 | ) {
47 | ImageBlendModeItem(data[index])
48 | if(index+1 Unit) {
58 | Box(
59 | modifier = Modifier.fillMaxWidth(),
60 | contentAlignment = Alignment.Center
61 | ) {
62 | Surface(
63 | Modifier
64 | .width(200.dp)
65 | .height((0.618 * 0.618 * 200).dp),
66 | color = Color(0xffEFEFEF)
67 | ) { content() }
68 | }
69 | }
70 |
71 | @Composable
72 | fun Center(content: @Composable () -> Unit) {
73 | Box(
74 | modifier = Modifier.fillMaxWidth().fillMaxHeight(),
75 | contentAlignment = Alignment.Center
76 | ) {
77 | content()
78 | }
79 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/layouts/unit_widget_item/UnitWidgetItemV1.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.layouts
2 |
3 | import androidx.compose.foundation.background
4 | import androidx.compose.foundation.layout.*
5 |
6 | import androidx.compose.foundation.shape.CircleShape
7 | import androidx.compose.foundation.shape.RoundedCornerShape
8 | import androidx.compose.material.MaterialTheme
9 | import androidx.compose.material.Text
10 | import androidx.compose.runtime.Composable
11 | import androidx.compose.ui.Alignment
12 | import androidx.compose.ui.Modifier
13 | import androidx.compose.ui.draw.clip
14 | import androidx.compose.ui.geometry.Offset
15 | import androidx.compose.ui.graphics.Color
16 | import androidx.compose.ui.graphics.Shadow
17 | import androidx.compose.ui.text.TextStyle
18 | import androidx.compose.ui.text.font.FontWeight
19 | import androidx.compose.ui.unit.dp
20 | import androidx.compose.ui.unit.sp
21 | import com.toly1994.composeunit.models.WidgetModel
22 |
23 |
24 |
25 | @Composable
26 | fun UnitWidgetItemV1(
27 | modifier: Modifier = Modifier,
28 | model: WidgetModel) {
29 | val titleTextStyle = TextStyle(
30 | fontWeight = FontWeight.Bold,
31 | fontSize = 16.sp,
32 | color = Color(0xff2F3032),
33 | )
34 |
35 | val contentTextStyle = TextStyle(
36 | fontSize = 14.sp,
37 | color = Color(0xff2F3032),
38 | )
39 |
40 | val infoTextStyle = TextStyle(
41 | fontSize = 12.sp,
42 | color = Color(0xff86909c),
43 | )
44 |
45 | val starTextStyle = TextStyle(
46 | color = MaterialTheme.colors.primary,
47 | )
48 |
49 | val typeTextStyle = TextStyle(
50 | fontSize = 10.sp,
51 | shadow = Shadow(
52 | color = Color.White,
53 | blurRadius = 2.0f,
54 | offset = Offset(1f, 1f)
55 | )
56 | )
57 | val collectTextStyle = TextStyle(
58 | fontSize = 10.sp,
59 | color = MaterialTheme.colors.primary,
60 | shadow = Shadow(
61 | color = Color.White,
62 | blurRadius = 2.0f,
63 | offset = Offset(1f, 1f)
64 | )
65 | )
66 | var starText = "";
67 | for (i in 0 until model.lever) {
68 | starText+="★"
69 | }
70 |
71 | Column(
72 | modifier
73 | .fillMaxWidth()
74 | .background(Color.White)
75 | .padding(20.dp, 10.dp)
76 | ) {
77 | Row(verticalAlignment = Alignment.CenterVertically) {
78 | Text(text = model.name, style = titleTextStyle)
79 | Spacer(modifier = Modifier.width(6.dp))
80 | if(model.collectd){
81 | Wrapper(wrapperColor = Color(0xffF3F3F5)) {
82 | Text(text = "已收藏", style = collectTextStyle)
83 | }
84 | }
85 | Spacer(modifier = Modifier.weight(1f))
86 | Text(text = starText, style = starTextStyle)
87 | }
88 | Spacer(modifier = Modifier.height(8.dp))
89 | Text(text = model.info, style = contentTextStyle)
90 | Spacer(modifier = Modifier.height(8.dp))
91 | Row(verticalAlignment = Alignment.CenterVertically) {
92 | Spacer(
93 | Modifier
94 | .width(4.dp)
95 | .height(4.dp)
96 | .clip(CircleShape)
97 | .background(infoTextStyle.color)
98 | )
99 |
100 | Spacer(modifier = Modifier.width(8.dp))
101 | Text(text = model.nameCN, style = infoTextStyle)
102 | Box(
103 | Modifier.fillMaxWidth(),
104 | contentAlignment = Alignment.CenterEnd
105 | ) {
106 | Wrapper(
107 | wrapperColor = Color(0xffF3F3F5),
108 | shape = RoundedCornerShape(10)
109 | ) {
110 | Text(text = model.family, style = typeTextStyle)
111 | }
112 | }
113 |
114 | }
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/layouts/github_search/views/GithubRepoItem.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.layouts.github_search.views
2 |
3 | import androidx.compose.foundation.Image
4 | import androidx.compose.foundation.background
5 | import androidx.compose.foundation.layout.*
6 | import androidx.compose.foundation.shape.CircleShape
7 | import androidx.compose.foundation.shape.RoundedCornerShape
8 | import androidx.compose.material.Divider
9 | import androidx.compose.material.Icon
10 | import androidx.compose.material.MaterialTheme
11 | import androidx.compose.material.Text
12 | import androidx.compose.material.icons.Icons
13 | import androidx.compose.material.icons.filled.Warning
14 | import androidx.compose.runtime.Composable
15 | import androidx.compose.ui.Alignment
16 | import androidx.compose.ui.BiasAlignment
17 | import androidx.compose.ui.Modifier
18 | import androidx.compose.ui.draw.clip
19 | import androidx.compose.ui.geometry.Offset
20 | import androidx.compose.ui.graphics.Color
21 | import androidx.compose.ui.graphics.Shadow
22 | import androidx.compose.ui.res.painterResource
23 | import androidx.compose.ui.text.TextStyle
24 | import androidx.compose.ui.text.font.FontWeight
25 | import androidx.compose.ui.tooling.preview.Preview
26 | import androidx.compose.ui.unit.dp
27 | import androidx.compose.ui.unit.sp
28 | import coil.compose.AsyncImage
29 | import com.toly1994.composeunit.R
30 | import com.toly1994.composeunit.components.style.Gap
31 | import com.toly1994.composeunit.layouts.Wrapper
32 | import com.toly1994.composeunit.layouts.github_search.repository.models.GithubRepo
33 | import com.toly1994.composeunit.layouts.wechat_item.CircleNumTip
34 | import com.toly1994.composeunit.widgets.Box.BoxNode2
35 |
36 | @Composable
37 | fun GithubRepoItem(githubRepo: GithubRepo) {
38 | val titleTextStyle = TextStyle(
39 | fontWeight = FontWeight.Bold,
40 | fontSize = 16.sp,
41 | color = Color(0xff2F3032),
42 | )
43 | val collectTextStyle = TextStyle(
44 | fontSize = 10.sp,
45 | color = MaterialTheme.colors.primary,
46 | shadow = Shadow(
47 | color = Color.White,
48 | blurRadius = 2.0f,
49 | offset = Offset(1f, 1f)
50 | )
51 | )
52 | val subTextStyle = TextStyle(
53 | fontSize = 12.sp,
54 | color = Color(0xffC5C5C5),
55 | )
56 |
57 | Column(
58 | Modifier
59 | .fillMaxWidth()
60 | .background(Color.White)
61 | ) {
62 | Box(
63 | modifier = Modifier.padding(10.dp, 10.dp)
64 | ) {
65 | Row(
66 | verticalAlignment = Alignment.Top
67 | ) {
68 | Box(
69 | contentAlignment = BiasAlignment(1.2f, -1.2f)
70 | ) {
71 | AsyncImage(
72 | modifier = Modifier
73 | .width(45.dp)
74 | .clip(RoundedCornerShape(10)),
75 | model = githubRepo.owner.avatar_url,
76 | contentDescription = null
77 | )
78 | }
79 |
80 | Spacer(modifier = Modifier.width(10.dp))
81 | Column(
82 | Modifier.weight(1f)
83 | ) {
84 | Text(text = githubRepo.name, style = titleTextStyle)
85 | Spacer(modifier = Modifier.height(4.dp))
86 | Text(text = githubRepo.description, style = subTextStyle)
87 | }
88 | Row {
89 | Wrapper(wrapperColor = Color(0xffF3F3F5)) {
90 | Text(text = "star : ${githubRepo.stargazers_count}", style = collectTextStyle)
91 | }
92 | Gap(width = 6f)
93 | Wrapper(wrapperColor = Color(0xffF3F3F5)) {
94 | Text(text = "forks : ${githubRepo.forks_count}", style = collectTextStyle)
95 | }
96 | }
97 | }
98 | }
99 | Divider(
100 | startIndent = 70.dp,
101 | thickness = 0.5.dp
102 | )
103 | }
104 |
105 | }
106 |
107 |
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/layouts/unit_widget_item/UnitWidgetItemV0.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.layouts
2 |
3 | import androidx.compose.foundation.background
4 | import androidx.compose.foundation.layout.*
5 |
6 | import androidx.compose.foundation.shape.CircleShape
7 | import androidx.compose.foundation.shape.RoundedCornerShape
8 | import androidx.compose.material.MaterialTheme
9 | import androidx.compose.material.Text
10 | import androidx.compose.runtime.Composable
11 | import androidx.compose.ui.Alignment
12 | import androidx.compose.ui.Modifier
13 | import androidx.compose.ui.draw.clip
14 | import androidx.compose.ui.geometry.Offset
15 | import androidx.compose.ui.graphics.Color
16 | import androidx.compose.ui.graphics.Shadow
17 | import androidx.compose.ui.text.TextStyle
18 | import androidx.compose.ui.text.font.FontWeight
19 | import androidx.compose.ui.unit.dp
20 | import androidx.compose.ui.unit.sp
21 |
22 |
23 |
24 | @Composable
25 | fun UnitWidgetItem() {
26 | val titleTextStyle = TextStyle(
27 | fontWeight = FontWeight.Bold,
28 | fontSize = 16.sp,
29 | color = Color(0xff2F3032),
30 | )
31 |
32 | val contentTextStyle = TextStyle(
33 | fontSize = 14.sp,
34 | color = Color(0xff2F3032),
35 | )
36 |
37 | val infoTextStyle = TextStyle(
38 | fontSize = 12.sp,
39 | color = Color(0xff86909c),
40 | )
41 |
42 | val starTextStyle = TextStyle(
43 | color = MaterialTheme.colors.primary,
44 | )
45 |
46 | val typeTextStyle = TextStyle(
47 | fontSize = 10.sp,
48 | shadow = Shadow(
49 | color = Color.White,
50 | blurRadius = 2.0f,
51 | offset = Offset(1f, 1f)
52 | )
53 | )
54 |
55 | val collectTextStyle = TextStyle(
56 | fontSize = 10.sp,
57 | color = MaterialTheme.colors.primary,
58 | shadow = Shadow(
59 | color = Color.White,
60 | blurRadius = 2.0f,
61 | offset = Offset(1f, 1f)
62 | )
63 | )
64 |
65 | Column(
66 | Modifier
67 | .fillMaxWidth()
68 | .background(Color.White)
69 | .padding(20.dp, 10.dp)
70 | ) {
71 | Row(verticalAlignment = Alignment.CenterVertically) {
72 | Text(text = "Text", style = titleTextStyle)
73 | Spacer(modifier = Modifier.width(6.dp))
74 | Wrapper(wrapperColor = Color(0xffF3F3F5)) {
75 | Text(text = "已收藏", style = collectTextStyle)
76 | }
77 |
78 | // Box(
79 | // Modifier.fillMaxWidth(),
80 | // contentAlignment = Alignment.CenterEnd
81 | // ) {
82 | // Text(text = "★★★★★★", style = starTextStyle)
83 | // }
84 | Spacer(modifier = Modifier.weight(1f))
85 | Text(text = "★★★★★★", style = starTextStyle)
86 |
87 | }
88 | Spacer(modifier = Modifier.height(8.dp))
89 | Text(text = "用于显示文字的组件。拥有的属性非常多,足够满足你的使用需求,核心样式由style属性控制。", style = contentTextStyle)
90 | Spacer(modifier = Modifier.height(8.dp))
91 | Row(verticalAlignment = Alignment.CenterVertically) {
92 | Spacer(
93 | Modifier
94 | .width(4.dp)
95 | .height(4.dp)
96 | .clip(CircleShape)
97 | .background(infoTextStyle.color)
98 | )
99 |
100 | Spacer(modifier = Modifier.width(8.dp))
101 | Text(text = "文字组件", style = infoTextStyle)
102 | Box(
103 | Modifier.fillMaxWidth(),
104 | contentAlignment = Alignment.CenterEnd
105 | ) {
106 | Wrapper(
107 | wrapperColor = Color(0xffF3F3F5),
108 | shape = RoundedCornerShape(10)
109 | ) {
110 | Text(text = "展示型", style = typeTextStyle)
111 | }
112 | }
113 |
114 | }
115 | }
116 | }
117 |
118 | @Composable
119 | fun Wrapper(
120 | wrapperColor: Color,
121 | shape: RoundedCornerShape = CircleShape,
122 | content: @Composable () -> Unit
123 | ) {
124 | Box(
125 | Modifier
126 | .clip(shape)
127 | .background(wrapperColor)) {
128 | Box(Modifier.padding(8.dp, 4.dp))
129 | { content() }
130 | }
131 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/app/navigation/UnitNavigation.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.app.navigation
2 |
3 | import android.os.Handler
4 | import android.os.Looper
5 | import androidx.compose.foundation.layout.padding
6 | import androidx.compose.material.*
7 | import androidx.compose.runtime.Composable
8 | import androidx.compose.runtime.collectAsState
9 | import androidx.compose.ui.Modifier
10 | import androidx.compose.ui.graphics.Color
11 | import androidx.navigation.NavGraph.Companion.findStartDestination
12 | import androidx.navigation.NavHostController
13 | import androidx.navigation.NavType
14 | import androidx.navigation.compose.NavHost
15 | import androidx.navigation.compose.composable
16 | import androidx.lifecycle.viewmodel.compose.viewModel
17 | import androidx.navigation.compose.currentBackStackEntryAsState
18 | import androidx.navigation.compose.rememberNavController
19 | import androidx.navigation.navArgument
20 | import com.toly1994.composeunit.app.splash.UnitSplash
21 | import com.toly1994.composeunit.details.NodeModelState
22 | import com.toly1994.composeunit.details.NodeViewModel
23 | import com.toly1994.composeunit.details.WidgetDetail
24 | import com.toly1994.composeunit.doing.Doing
25 | import com.toly1994.composeunit.home.HomeLazyWidgetList
26 | import com.toly1994.composeunit.models.WidgetModel
27 | import com.toly1994.composeunit.user.UnitUserPage
28 |
29 | @Composable
30 | fun UnitNavigation(
31 | viewModel : NodeViewModel = viewModel(),
32 | onShare: (String) -> Unit) {
33 | val topNavCtrl = rememberNavController()
34 | NavHost(
35 | navController = topNavCtrl,
36 | startDestination = UnitRoute.splash
37 | ) {
38 | composable(UnitRoute.splash) { UnitSplash() }
39 | composable(UnitRoute.homeNav) {
40 | UnitHomeNavigation{
41 | viewModel.handleEnterWidget(it,topNavCtrl)
42 | }
43 | }
44 | composable(UnitRoute.widgetDetail,) {
45 | val nodeState = viewModel.uiState.collectAsState().value
46 | WidgetDetail(nodeState, onShare) {
47 | topNavCtrl.popBackStack()
48 | }
49 | }
50 | }
51 | delayToHome(topNavCtrl)
52 | }
53 |
54 | private fun delayToHome(topNavCtrl: NavHostController, duration: Long = 1000) {
55 | Handler(Looper.getMainLooper()).postDelayed({
56 | topNavCtrl.navigate(UnitRoute.homeNav) {
57 | popUpTo(UnitRoute.splash) {
58 | inclusive = true
59 | }
60 | }
61 | }, duration)
62 | }
63 |
64 | @Composable
65 | fun UnitHomeNavigation(
66 | toDetail: (WidgetModel) -> Unit,
67 | ) {
68 | val navCtrl = rememberNavController()
69 | val navEntry = navCtrl.currentBackStackEntryAsState()
70 | val currentRout: String? = navEntry.value?.destination?.route
71 | Scaffold(backgroundColor = Color(0xffF3F5F4), bottomBar = {
72 | UnitBottomNavBar(currentRoute = currentRout, onTapItem = { navigatorTo(navCtrl, it) })
73 | }, topBar = {
74 | UnitAppBar(currentRout)
75 | }) {
76 | NavHost(navCtrl, startDestination = UnitRoute.widget, Modifier.padding(it)) {
77 | composable(UnitRoute.widget) {
78 | HomeLazyWidgetList(onTapItem = toDetail)
79 | }
80 | composable(UnitRoute.layout) { Doing(name = "布局集录") }
81 | composable(UnitRoute.collect) { Doing(name = "收藏集录") }
82 | composable(UnitRoute.user) { UnitUserPage() }
83 | }
84 | }
85 | }
86 |
87 |
88 |
89 | @Composable
90 | fun UnitBottomNavBar(
91 | currentRoute: String?,
92 | onTapItem: (String) -> Unit,
93 | ) {
94 | BottomNavigation() {
95 | RouterRes.bottomNavData.forEach { data ->
96 | BottomNavigationItem(selected = currentRoute == data.route,
97 | onClick = { onTapItem(data.route) },
98 | label = { Text(text = data.text) },
99 | icon = {
100 | Icon(
101 | imageVector = data.icon, contentDescription = ""
102 | )
103 | })
104 | }
105 | }
106 | }
107 |
108 | // 路由跳转
109 | private fun navigatorTo(
110 | navCtrl: NavHostController, route: String
111 | ) {
112 | navCtrl.navigate(route) {
113 | popUpTo(navCtrl.graph.findStartDestination().id) {
114 | saveState = true
115 | }
116 | restoreState = true
117 | }
118 | }
119 |
120 |
121 |
--------------------------------------------------------------------------------
/highlight/src/main/java/com/neo/highlight/util/listener/HighlightTextWatcher.java:
--------------------------------------------------------------------------------
1 | package com.neo.highlight.util.listener;
2 |
3 | import android.os.Handler;
4 | import android.os.Looper;
5 | import android.text.Editable;
6 | import android.text.SpannableString;
7 | import android.widget.TextView;
8 |
9 | import androidx.annotation.NonNull;
10 |
11 | import com.neo.highlight.core.Highlight;
12 | import com.neo.highlight.core.HighlightContract;
13 | import com.neo.highlight.core.LinesTextWatcher;
14 | import com.neo.highlight.core.Scheme;
15 |
16 | import java.util.List;
17 |
18 | /**
19 | * Apply schemes to EditText
20 | * @author Irineu A. Silva
21 | */
22 | final public class HighlightTextWatcher extends LinesTextWatcher implements HighlightContract {
23 |
24 | @NonNull
25 | private RANGE range = RANGE.MODIFIED;
26 |
27 | @NonNull
28 | private Highlight highlight;
29 |
30 | public HighlightTextWatcher() {
31 | highlight = new Highlight();
32 | }
33 |
34 | public HighlightTextWatcher(@NonNull Highlight highlight) {
35 | this.highlight = highlight;
36 | }
37 |
38 | @Override
39 | protected void onLinesChange(
40 | @NonNull Editable editable,
41 | int start, int end,
42 | int firstLineStart, int lastLineEnd
43 | ) {
44 |
45 | if (range == RANGE.MODIFIED) {
46 | removeSpan(editable, firstLineStart, lastLineEnd);
47 | setSpan(editable, firstLineStart, lastLineEnd);
48 | } else {
49 | final Editable _editable = editable;
50 | new Handler(Looper.getMainLooper()).post(new Runnable() {
51 |
52 | @Override
53 | public void run() {
54 | removeSpan(_editable);
55 | setSpan(_editable);
56 | }
57 | });
58 | }
59 | }
60 |
61 | public void setRange(@NonNull RANGE range) {
62 | this.range = range;
63 | }
64 |
65 | @NonNull
66 | public RANGE getRange() {
67 | return range;
68 | }
69 |
70 | @NonNull
71 | public Highlight getHighlight() {
72 | return highlight;
73 | }
74 |
75 | public void setHighlight(@NonNull Highlight highlight) {
76 | this.highlight = highlight;
77 | }
78 |
79 | //override HighlightContract
80 |
81 | @Override
82 | public void setSpan(Editable editable, int start, int end) {
83 | this.highlight.setSpan(editable, start, end);
84 | }
85 |
86 | @Override
87 | public void setSpan(Editable editable) {
88 | this.highlight.setSpan(editable);
89 | }
90 |
91 | @Override
92 | public void setSpan(TextView textView, int start, int end) {
93 | this.highlight.setSpan(textView, start, end);
94 | }
95 |
96 | @Override
97 | public void setSpan(TextView textView) {
98 | this.highlight.setSpan(textView);
99 | }
100 |
101 | @Override
102 | public void setSpan(SpannableString spannableString, int start, int end) {
103 | this.highlight.setSpan(spannableString, start, end);
104 | }
105 |
106 | @Override
107 | public void setSpan(SpannableString spannableString) {
108 | this.setSpan(spannableString);
109 | }
110 |
111 | @Override
112 | public void removeSpan(Editable editable) {
113 | this.highlight.removeSpan(editable);
114 | }
115 |
116 | @Override
117 | public void removeSpan(Editable editable, int start, int end) {
118 | this.highlight.removeSpan(editable, start, end);
119 | }
120 |
121 | @Override
122 | public List getSchemes() {
123 | return highlight.getSchemes();
124 | }
125 |
126 | @Override
127 | public void setSchemes(@NonNull List schemes) {
128 | highlight.setSchemes(schemes);
129 | }
130 |
131 | @Override
132 | public void addScheme(@NonNull Scheme... schemes) {
133 | highlight.addScheme(schemes);
134 | }
135 |
136 | @Override
137 | public void clearScheme() {
138 | highlight.clearScheme();
139 | }
140 |
141 | @Override
142 | public List> getSpanTypes() {
143 | return highlight.getSpanTypes();
144 | }
145 |
146 | @Override
147 | public void setSpanTypes(@NonNull List> spanTypes) {
148 | highlight.setSpanTypes(spanTypes);
149 | }
150 |
151 | @Override
152 | public void addSpanType(Class> span) {
153 | highlight.addSpanType(span);
154 | }
155 |
156 | @Override
157 | public void clearSpanTypes() {
158 | highlight.clearSpanTypes();
159 | }
160 |
161 | public enum RANGE {
162 | MODIFIED,
163 | ALL
164 | }
165 | }
166 |
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/repository/memory/MemoryWidgetDataStore.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.repository.memory
2 |
3 | import com.toly1994.composeunit.models.WidgetModel
4 |
5 | object MemoryWidgetDataStore {
6 | val allWidget = listOf(
7 | WidgetModel(
8 | id = 1,
9 | name = "Text",
10 | nameCN = "文字组件",
11 | lever = 5,
12 | family = "无内容组件",
13 | collectd = true,
14 | info = "用于显示文字的组件。拥有的属性非常多,足够满足你的使用需求,核心样式由style属性控制。"
15 | ),
16 | WidgetModel(
17 | id = 2,
18 | name = "Image",
19 | nameCN = "图片组件",
20 | lever = 5,
21 | family = "无内容组件",
22 | collectd = true,
23 | info = "用于显示一张图片,可以从资源文件中加载。可以指定适应方式、对齐模式、颜色混合模式、透明度等属性。"
24 | ),
25 | WidgetModel(
26 | id = 3,
27 | name = "Icon",
28 | nameCN = "图标组件",
29 | lever = 3,
30 | family = "无内容组件",
31 | collectd = false,
32 | info = "用于图标显示的组件。可指定图标资源、颜色。非常简单,但是非常用。"
33 | ),
34 | WidgetModel(
35 | id = 4,
36 | name = "Row",
37 | nameCN = "行布局组件",
38 | lever = 5,
39 | family = "多内容组件",
40 | collectd = true,
41 | info = "水平方向为竖向的布局,可容纳多个组件,可以通过属性控制排布的对齐方式。"
42 | ),
43 | WidgetModel(
44 | id = 5,
45 | name = "Column",
46 | nameCN = "列布局组件",
47 | lever = 5,
48 | family = "多内容组件",
49 | collectd = false,
50 | info = "排布方向为竖向的布局,可容纳多个组件,可以通过属性控制排布的对齐方式。"
51 | ),
52 | WidgetModel(
53 | id = 6,
54 | name = "Box",
55 | nameCN = "叠放盒组件",
56 | lever = 5,
57 | family = "多内容组件",
58 | collectd = true,
59 | info = "可容纳多个组件,堆叠排放,可以通过属性控制排布的对齐方式等属性。"
60 | ),
61 | WidgetModel(
62 | id = 7,
63 | name = "LazyColumn",
64 | nameCN = "延迟纵向列表",
65 | lever = 5,
66 | family = "多内容组件",
67 | collectd = true,
68 | info = "具有懒加载条目功能的纵向列表,支持纵向滑动处理,是非常常用的列表组件。"
69 | ),
70 | WidgetModel(
71 | id = 8,
72 | name = "LazyRow",
73 | nameCN = "延迟横向列表",
74 | lever = 4,
75 | family = "多内容组件",
76 | collectd = true,
77 | info = "与 LazyColumn 相对应,具有懒加载条目功能的横向列表,支持横向滑动处理。"
78 | ),
79 | WidgetModel(
80 | id = 9,
81 | name = "LazyVerticalGrid",
82 | nameCN = "延迟纵向网格",
83 | lever = 5,
84 | family = "多内容组件",
85 | collectd = true,
86 | info = "具有懒加载条目功能的纵向网格布局,支持纵向滑动处理,是非常常用的网格组件。"
87 | ),
88 | WidgetModel(
89 | id = 10,
90 | name = "LazyHorizontalGrid",
91 | nameCN = "延迟横向网格",
92 | lever = 5,
93 | family = "多内容组件",
94 | collectd = true,
95 | info = "与 LazyHorizontalGrid 相对应,具有懒加载条目功能的横向网格布局,支持横向滑动处理。"
96 | ),
97 | WidgetModel(
98 | id = 11,
99 | name = "Scaffold",
100 | nameCN = "脚手架组件",
101 | lever = 4,
102 | family = "卡槽型组件",
103 | collectd = true,
104 | info = "一个通用 app 结构,包括上、下、左、右、中、浮动按钮部位,对应位置可盛放组件。"
105 | ),
106 | WidgetModel(
107 | id = 12,
108 | name = "AppTopBar",
109 | nameCN = "应用头部栏",
110 | lever = 4,
111 | family = "卡槽型组件",
112 | collectd = true,
113 | info = "一个应用顶部栏的通用结构,可在指定的部位放置相应的组件,常用于Scaffold组件中。"
114 | ),
115 | WidgetModel(
116 | id = 13,
117 | name = "FloatingActionButton",
118 | nameCN = "浮动按钮",
119 | lever = 3,
120 | family = "单内容组件",
121 | collectd = true,
122 | info = "Material 风格,一般用于Scaffold中,可摆放在特定位置。可盛放一个子组件,接收点击、可定义颜色、形状等。"
123 | ),
124 | WidgetModel(
125 | id = 14,
126 | name = "Spacer",
127 | nameCN = "占位组件",
128 | lever = 4,
129 | family = "无内容组件",
130 | collectd = false,
131 | info = "只有 modifier 参数的组件,一般用于占位场景。"
132 | ),
133 | WidgetModel(
134 | id = 15,
135 | name = "Divider",
136 | nameCN = "分割线组件",
137 | lever = 2,
138 | family = "无内容组件",
139 | collectd = false,
140 | info = "横向分割线,默认 1dp,可指定头部空缺长度。"
141 | )
142 | )
143 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/repository/memory/MemoryNodeDataStore.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.repository.memory
2 |
3 | import com.toly1994.composeunit.models.NodeModel
4 | import com.toly1994.composeunit.repository.memory.node_res.*
5 |
6 | object MemoryNodeDataStore {
7 | val allNodes = listOf(
8 | //==== Text ==========
9 | NodeModel(
10 | widgetId = 1,
11 | name = "文字的基本样式",
12 | code = TextNode1Code,
13 | info = TextNode1Info
14 | ),
15 | NodeModel(
16 | widgetId = 1,
17 | name = "文字背景与阴影",
18 | code = TextNode2Code,
19 | info = TextNode2Info
20 | ),
21 | NodeModel(
22 | widgetId = 1,
23 | name = "文字装饰线与缩进",
24 | code = TextNode3Code,
25 | info = TextNode3Info
26 | ),
27 | NodeModel(
28 | widgetId = 1,
29 | name = "多行与包裹溢出",
30 | code = TextNode4Code,
31 | info = TextNode4Info
32 | ),
33 | NodeModel(
34 | widgetId = 1,
35 | name = "文字对齐与行高",
36 | code = TextNode5Code,
37 | info = TextNode5Info
38 | ),
39 | //==== Image ==========
40 | NodeModel(
41 | widgetId = 2,
42 | name = "图片加载方式",
43 | code = ImageNode1Code,
44 | info = ImageNode1Info
45 | ),
46 | NodeModel(
47 | widgetId = 2,
48 | name = "图片对齐模式",
49 | code = ImageNode2Code,
50 | info = ImageNode2Info
51 | ),
52 | NodeModel(
53 | widgetId = 2,
54 | name = "图片缩放模式",
55 | code = ImageNode3Code,
56 | info = ImageNode3Info
57 | ),
58 | NodeModel(
59 | widgetId = 2,
60 | name = "颜色叠合模式",
61 | code = ImageNode4Code,
62 | info = ImageNode4Info
63 | ),
64 | //==== Icon ==========
65 | NodeModel(
66 | widgetId = 3,
67 | name = "图标的使用",
68 | code = IconNode1Code,
69 | info = IconNode1Info
70 | ),
71 | //==== Row ==========
72 | NodeModel(
73 | widgetId = 4,
74 | name = "行的水平对齐模式",
75 | code = RowNode1Code,
76 | info = RowNode1Info
77 | ),
78 | NodeModel(
79 | widgetId = 4,
80 | name = "行的竖直对齐模式",
81 | code = RowNode2Code,
82 | info = RowNode2Info
83 | ),
84 | NodeModel(
85 | widgetId = 4,
86 | name = "行中的组件宽度占比",
87 | code = RowNode3Code,
88 | info = RowNode3Info
89 | ),
90 | //==== Column ==========
91 | NodeModel(
92 | widgetId = 5,
93 | name = "列的竖直对齐模式",
94 | code = ColumnNode1Code,
95 | info = ColumnNode1Info
96 | ),
97 | NodeModel(
98 | widgetId = 5,
99 | name = "列的水平对齐模式",
100 | code = ColumnNode2Code,
101 | info = ColumnNode2Info
102 | ),
103 | NodeModel(
104 | widgetId = 5,
105 | name = "列中的组件高度占比",
106 | code = ColumnNode3Code,
107 | info = ColumnNode3Info
108 | ),
109 | //==== Box ==========
110 | NodeModel(
111 | widgetId = 6,
112 | name = "Box 的对齐方式",
113 | code = BoxNode1Code,
114 | info = BoxNode1Info
115 | ),
116 | NodeModel(
117 | widgetId = 6,
118 | name = "修改单个子组件的对齐方式",
119 | code = BoxNode2Code,
120 | info = BoxNode2Info
121 | ),
122 | //==== LazyColumn ==========
123 | NodeModel(
124 | widgetId = 7,
125 | name = "延迟纵向列表基本使用",
126 | code = LazyColumnNode1Code,
127 | info = LazyColumnNode1Info
128 | ),
129 | //==== LazyColumn ==========
130 | NodeModel(
131 | widgetId = 8,
132 | name = "延迟横向列表基本使用",
133 | code = LazyRowNode1Code,
134 | info = LazyRowNode1Info
135 | ),
136 | //==== LazyVerticalGrid ==========
137 | NodeModel(
138 | widgetId = 9,
139 | name = "延迟纵向网格基本使用",
140 | code = LazyVerticalGridNode1Code,
141 | info = LazyVerticalGridNode1Info
142 | ),
143 | //==== LazyHorizontalGrid ==========
144 | NodeModel(
145 | widgetId = 10,
146 | name = "延迟横向网格基本使用",
147 | code = LazyHorizontalGridNode1Code,
148 | info = LazyHorizontalGridNode1Info
149 | ),
150 | )
151 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/layouts/juejin_article_item/JuejinArticleItemV1.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.layouts
2 |
3 | import androidx.compose.foundation.Image
4 | import androidx.compose.foundation.background
5 | import androidx.compose.foundation.layout.*
6 | import androidx.compose.foundation.shape.RoundedCornerShape
7 | import androidx.compose.material.Icon
8 | import androidx.compose.material.Text
9 | import androidx.compose.runtime.Composable
10 | import androidx.compose.ui.Alignment
11 | import androidx.compose.ui.Modifier
12 | import androidx.compose.ui.draw.clip
13 | import androidx.compose.ui.geometry.Offset
14 | import androidx.compose.ui.graphics.Color
15 | import androidx.compose.ui.graphics.Shadow
16 | import androidx.compose.ui.layout.ContentScale
17 | import androidx.compose.ui.res.painterResource
18 | import androidx.compose.ui.text.TextStyle
19 | import androidx.compose.ui.text.font.FontWeight
20 | import androidx.compose.ui.text.style.TextOverflow
21 | import androidx.compose.ui.unit.dp
22 | import androidx.compose.ui.unit.sp
23 | import com.toly1994.composeunit.R
24 |
25 |
26 | @Composable
27 | fun JuejinArticleItemV1() {
28 | val titleTextStyle = TextStyle(
29 | fontWeight = FontWeight.Bold,
30 | fontSize = 16.sp,
31 | color = Color(0xff2F3032),
32 | )
33 | Column(
34 | Modifier.fillMaxWidth().background(Color.White).padding(20.dp, 10.dp)
35 | ) {
36 | Text(text = "【Flutter 异步编程 - 柒】 | 深入剖析 Stream 机制源码实现", style = titleTextStyle)
37 | JuejinArticleItemCenter()
38 | Spacer(modifier = Modifier.height(8.dp))
39 | JuejinArticleItemFooter()
40 | }
41 | }
42 |
43 | @Composable
44 | fun JuejinArticleItemCenter() {
45 | val contentTextStyle = TextStyle(
46 | fontSize = 14.sp,
47 | color = Color(0xff5A576C),
48 | )
49 | val userTextStyle = TextStyle(
50 | fontSize = 14.sp,
51 | color = Color(0xff58575F),
52 | )
53 | val timeTextStyle = TextStyle(
54 | fontSize = 14.sp,
55 | color = Color(0xff8C929E),
56 | )
57 | Row(
58 | verticalAlignment = Alignment.CenterVertically,
59 | ) {
60 | Column(
61 | Modifier
62 | .weight(1f)
63 | .padding(end = 5.dp)
64 | ) {
65 | Row(
66 | Modifier.padding(0.dp, 4.dp)
67 | ) {
68 | Text(text = "张风捷特烈", style = userTextStyle)
69 | Text(text = " | ", style = timeTextStyle)
70 | Text(text = "14小时前", style = timeTextStyle)
71 | }
72 | Text(
73 | maxLines = 2,
74 | overflow = TextOverflow.Ellipsis,
75 | text = "一、从 Stream 的回调监听开始说起 在第三篇中,我们已经对 Stream 有了基本的概念认知,以及使用方式。 Stream 的特点是可以通过 listen 方法的第一入参 onData,不断监听",
76 | style = contentTextStyle
77 | )
78 | }
79 | Image(
80 | modifier = Modifier
81 | .width(90.dp)
82 | .height(60.dp)
83 | .clip(RoundedCornerShape(10)),
84 | painter = painterResource(id = R.mipmap.caver),
85 | contentDescription = "",
86 | contentScale = ContentScale.FillBounds
87 | )
88 | }
89 | }
90 |
91 | @Composable
92 | fun JuejinArticleItemFooter() {
93 | val typeTextStyle = TextStyle(
94 | fontSize = 12.sp,
95 | color = Color(0xff90959A),
96 | shadow = Shadow(
97 | color = Color.White,
98 | blurRadius = 2.0f,
99 | offset = Offset(1f, 1f)
100 | )
101 | )
102 | val infoTextStyle = TextStyle(
103 | fontSize = 12.sp,
104 | color = Color(0xff86909c),
105 | )
106 | Row(verticalAlignment = Alignment.CenterVertically) {
107 | Icon(
108 | modifier = Modifier.size(18.dp, 18.dp),
109 | tint = Color(0xff1F80FD),
110 | painter = painterResource(id = R.mipmap.zan), contentDescription = ""
111 | )
112 | Spacer(modifier = Modifier.width(2.dp))
113 | Text(text = "100", style = infoTextStyle)
114 | Spacer(modifier = Modifier.width(10.dp))
115 | Icon(
116 | modifier = Modifier.size(18.dp, 18.dp),
117 | tint = infoTextStyle.color,
118 | painter = painterResource(id = R.mipmap.pinglun), contentDescription = ""
119 | )
120 | Spacer(modifier = Modifier.width(2.dp))
121 | Text(text = "99", style = infoTextStyle)
122 | Spacer(
123 | Modifier.weight(1f)
124 | )
125 | Wrapper(
126 | wrapperColor = Color(0xffF3F3F5),
127 | shape = RoundedCornerShape(10)
128 | ) {
129 | Text(text = "Android", style = typeTextStyle)
130 | }
131 | Spacer(modifier = Modifier.width(8.dp))
132 | Wrapper(
133 | wrapperColor = Color(0xffF3F3F5),
134 | shape = RoundedCornerShape(10)
135 | ) {
136 | Text(text = "Flutter", style = typeTextStyle)
137 | }
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/layouts/wechat_item/WeChatItem.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.layouts.wechat_item
2 |
3 | import android.annotation.SuppressLint
4 | import androidx.compose.foundation.Image
5 | import androidx.compose.foundation.background
6 | import androidx.compose.foundation.layout.*
7 | import androidx.compose.foundation.shape.CircleShape
8 | import androidx.compose.foundation.shape.RoundedCornerShape
9 | import androidx.compose.material.*
10 | import androidx.compose.material.icons.Icons
11 | import androidx.compose.material.icons.filled.Warning
12 | import androidx.compose.material.icons.rounded.Add
13 | import androidx.compose.material.icons.rounded.ShoppingCart
14 | import androidx.compose.runtime.Composable
15 | import androidx.compose.ui.Alignment
16 | import androidx.compose.ui.BiasAlignment
17 | import androidx.compose.ui.Modifier
18 | import androidx.compose.ui.draw.clip
19 | import androidx.compose.ui.geometry.Offset
20 | import androidx.compose.ui.graphics.Color
21 | import androidx.compose.ui.graphics.Shadow
22 | import androidx.compose.ui.res.painterResource
23 | import androidx.compose.ui.text.TextStyle
24 | import androidx.compose.ui.text.font.FontWeight
25 | import androidx.compose.ui.unit.dp
26 | import androidx.compose.ui.unit.sp
27 | import com.toly1994.composeunit.R
28 |
29 | @Composable
30 | fun WeChatItem(banned:Boolean = false) {
31 | val titleTextStyle = TextStyle(
32 | fontWeight = FontWeight.Bold,
33 | fontSize = 16.sp,
34 | color = Color(0xff2F3032),
35 | )
36 |
37 | val subTextStyle = TextStyle(
38 | fontSize = 12.sp,
39 | color = Color(0xffC5C5C5),
40 | )
41 |
42 | Column(
43 | Modifier
44 | .fillMaxWidth()
45 | .background(Color.White)
46 | ) {
47 | Box(
48 | modifier = Modifier.padding(10.dp, 10.dp)
49 | ) {
50 | Row(
51 | verticalAlignment = Alignment.Top
52 | ) {
53 | Box(
54 | contentAlignment = BiasAlignment(1.2f, -1.2f)
55 | ) {
56 | Image(
57 | modifier = Modifier
58 | .width(45.dp)
59 | .clip(RoundedCornerShape(10)),
60 | painter = painterResource(id = R.mipmap.head_icon),
61 | contentDescription = "",
62 | )
63 | if(banned) {
64 | Spacer(
65 | Modifier
66 | .width(10.dp)
67 | .height(10.dp)
68 | .clip(CircleShape)
69 | .background(Color.Red)
70 | )
71 | } else {
72 | CircleNumTip(
73 | color = Color.Red, radius = 8f, count = 1
74 | )
75 | }
76 | }
77 |
78 | Spacer(modifier = Modifier.width(10.dp))
79 | Column(
80 | Modifier.weight(1f)
81 | ) {
82 | Text(text = "堕天使者", style = titleTextStyle)
83 | Spacer(modifier = Modifier.height(4.dp))
84 | Text(text = "你好,Compose 学的怎么样了?", style = subTextStyle)
85 | }
86 | Column() {
87 | Text(text = "22:25", style = subTextStyle)
88 | if(banned) {
89 | Spacer(modifier = Modifier.height(6.dp))
90 | }
91 | if(banned) {
92 | Icon(
93 | Icons.Default.Warning, "",
94 | tint = subTextStyle.color,
95 | modifier = Modifier.size(18.dp,18.dp))
96 | }
97 | }
98 | }
99 | }
100 | Divider(
101 | startIndent = 70.dp,
102 | thickness = 0.5.dp
103 | )
104 | }
105 |
106 |
107 | }
108 |
109 | @Composable
110 | fun Wrapper(
111 | wrapperColor: Color,
112 | shape: RoundedCornerShape = CircleShape,
113 | content: @Composable () -> Unit
114 | ) {
115 | Box(
116 | Modifier
117 | .clip(shape)
118 | .background(wrapperColor)
119 | ) {
120 | Box(Modifier.padding(8.dp, 4.dp))
121 | { content() }
122 | }
123 | }
124 |
125 | @Composable
126 | fun CircleNumTip(
127 | color: Color,
128 | count: Int,
129 | radius: Float,
130 | ) {
131 | Box(
132 | Modifier
133 | .width(radius.dp * 2)
134 | .height(radius.dp * 2)
135 | .clip(CircleShape)
136 | .background(color),
137 | contentAlignment = Alignment.Center
138 | ) {
139 | Text(
140 | text = "$count", style = TextStyle(
141 | fontSize = (radius / 0.8).sp,
142 | color = Color.White,
143 | )
144 | )
145 | }
146 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/toly1994/composeunit/layouts/juejin_article_item/JuejinArticleItemV0.kt:
--------------------------------------------------------------------------------
1 | package com.toly1994.composeunit.layouts
2 |
3 | import androidx.compose.foundation.Image
4 | import androidx.compose.foundation.background
5 | import androidx.compose.foundation.layout.*
6 | import androidx.compose.foundation.shape.RoundedCornerShape
7 | import androidx.compose.material.Icon
8 | import androidx.compose.material.Text
9 | import androidx.compose.runtime.Composable
10 | import androidx.compose.ui.Alignment
11 | import androidx.compose.ui.Modifier
12 | import androidx.compose.ui.draw.clip
13 | import androidx.compose.ui.geometry.Offset
14 | import androidx.compose.ui.graphics.Color
15 | import androidx.compose.ui.graphics.Shadow
16 | import androidx.compose.ui.layout.ContentScale
17 | import androidx.compose.ui.res.painterResource
18 | import androidx.compose.ui.text.TextStyle
19 | import androidx.compose.ui.text.font.FontWeight
20 | import androidx.compose.ui.text.style.TextOverflow
21 | import androidx.compose.ui.unit.dp
22 | import androidx.compose.ui.unit.sp
23 | import com.toly1994.composeunit.R
24 |
25 |
26 | @Composable
27 | fun JuejinArticleItemV0() {
28 | val titleTextStyle = TextStyle(
29 | fontWeight = FontWeight.Bold,
30 | fontSize = 16.sp,
31 | color = Color(0xff2F3032),
32 | )
33 | val contentTextStyle = TextStyle(
34 | fontSize = 14.sp,
35 | color = Color(0xff5A576C),
36 | )
37 | val infoTextStyle = TextStyle(
38 | fontSize = 12.sp,
39 | color = Color(0xff86909c),
40 | )
41 | val typeTextStyle = TextStyle(
42 | fontSize = 12.sp,
43 | color = Color(0xff90959A),
44 | shadow = Shadow(
45 | color = Color.White,
46 | blurRadius = 2.0f,
47 | offset = Offset(1f, 1f)
48 | )
49 | )
50 | val userTextStyle = TextStyle(
51 | fontSize = 14.sp,
52 | color = Color(0xff58575F),
53 | )
54 | val timeTextStyle = TextStyle(
55 | fontSize = 14.sp,
56 | color = Color(0xff8C929E),
57 | )
58 | Column(
59 | Modifier
60 | .fillMaxWidth()
61 | .background(Color.White)
62 | .padding(20.dp, 10.dp)
63 | ) {
64 | Text(text = "【Flutter 异步编程 - 柒】 | 深入剖析 Stream 机制源码实现", style = titleTextStyle)
65 | Row(
66 | verticalAlignment = Alignment.CenterVertically,
67 | ) {
68 | Column(
69 | Modifier
70 | .weight(1f)
71 | .padding(end = 5.dp)
72 | ) {
73 | Row(
74 | Modifier.padding(0.dp, 4.dp)
75 | ) {
76 | Text(text = "张风捷特烈", style = userTextStyle)
77 | Text(text = " | ", style = timeTextStyle)
78 | Text(text = "14小时前", style = timeTextStyle)
79 | }
80 | Text(
81 | maxLines = 2,
82 | overflow = TextOverflow.Ellipsis,
83 | text = "一、从 Stream 的回调监听开始说起 在第三篇中,我们已经对 Stream 有了基本的概念认知,以及使用方式。 Stream 的特点是可以通过 listen 方法的第一入参 onData,不断监听",
84 | style = contentTextStyle
85 | )
86 | }
87 | Image(
88 | modifier = Modifier
89 | .width(90.dp)
90 | .height(60.dp)
91 | .clip(RoundedCornerShape(10)),
92 | painter = painterResource(id = R.mipmap.caver),
93 | contentDescription = "",
94 | contentScale = ContentScale.FillBounds
95 | )
96 | }
97 |
98 | Spacer(modifier = Modifier.height(8.dp))
99 | Row(verticalAlignment = Alignment.CenterVertically) {
100 | Icon(
101 | modifier = Modifier.size(18.dp, 18.dp),
102 | tint = Color(0xff1F80FD),
103 | painter = painterResource(id = R.mipmap.zan), contentDescription = ""
104 | )
105 | Spacer(modifier = Modifier.width(2.dp))
106 | Text(text = "100", style = infoTextStyle)
107 | Spacer(modifier = Modifier.width(10.dp))
108 | Icon(
109 | modifier = Modifier.size(18.dp, 18.dp),
110 | tint = infoTextStyle.color,
111 | painter = painterResource(id = R.mipmap.pinglun), contentDescription = ""
112 | )
113 | Spacer(modifier = Modifier.width(2.dp))
114 | Text(text = "99", style = infoTextStyle)
115 | Spacer(
116 | Modifier.weight(1f)
117 | )
118 | Wrapper(
119 | wrapperColor = Color(0xffF3F3F5),
120 | shape = RoundedCornerShape(10)
121 | ) {
122 | Text(text = "Android", style = typeTextStyle)
123 | }
124 | Spacer(modifier = Modifier.width(8.dp))
125 | Wrapper(
126 | wrapperColor = Color(0xffF3F3F5),
127 | shape = RoundedCornerShape(10)
128 | ) {
129 | Text(text = "Flutter", style = typeTextStyle)
130 | }
131 | }
132 | }
133 | }
134 |
--------------------------------------------------------------------------------