diff --git a/build.gradle.kts b/build.gradle.kts index 24af2b4e..7fc38f5d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,8 +7,8 @@ buildscript { mavenLocal() } dependencies { - classpath("com.android.tools.build:gradle:7.0.3") - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.31") + classpath("com.android.tools.build:gradle:7.0.4") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.0") } } diff --git a/compose/.gitignore b/compose/.gitignore new file mode 100644 index 00000000..42afabfd --- /dev/null +++ b/compose/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/compose/build.gradle.kts b/compose/build.gradle.kts new file mode 100644 index 00000000..7481e75d --- /dev/null +++ b/compose/build.gradle.kts @@ -0,0 +1,79 @@ +import com.qmuiteam.plugin.Dep +import java.io.FileInputStream +import java.util.* + +plugins { + id("com.android.library") + kotlin("android") + `maven-publish` +} + + +android { + compileSdk = Dep.compileSdk + + buildFeatures { + compose = true + } + + defaultConfig { + minSdk = Dep.minSdk + targetSdk = Dep.targetSdk + } + + buildTypes { + getByName("release"){ + isMinifyEnabled = false + proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") + } + } + + compileOptions { + sourceCompatibility = Dep.javaVersion + targetCompatibility = Dep.javaVersion + } + kotlinOptions { + jvmTarget = Dep.kotlinJvmTarget + } + + composeOptions { + kotlinCompilerExtensionVersion = Dep.Compose.version + } +} + +dependencies { + api(Dep.AndroidX.annotation) + api(Dep.AndroidX.appcompat) + api(Dep.AndroidX.coreKtx) + api(Dep.Compose.ui) + api(Dep.Compose.animation) + api(Dep.Compose.material) + api(Dep.Compose.compiler) +} + +afterEvaluate { + val file = rootProject.file("gradle/deploy.properties") + if(file.exists()) { + val properties = Properties() + properties.load(FileInputStream(file)) + publishing { + publications { + create("release") { + from(components.getByName("release")) + groupId = Dep.QMUI.group + artifactId = project.name + version = Dep.QMUI.composeVer + } + } + repositories { + maven { + setUrl(properties.getProperty("maven.url")) + credentials { + username = properties.getProperty("maven.username") + password = properties.getProperty("maven.password") + } + } + } + } + } +} \ No newline at end of file diff --git a/compose/proguard-rules.pro b/compose/proguard-rules.pro new file mode 100644 index 00000000..481bb434 --- /dev/null +++ b/compose/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/compose/src/androidTest/java/com/qmuiteam/compose/ExampleInstrumentedTest.kt b/compose/src/androidTest/java/com/qmuiteam/compose/ExampleInstrumentedTest.kt new file mode 100644 index 00000000..b0a4768b --- /dev/null +++ b/compose/src/androidTest/java/com/qmuiteam/compose/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package com.qmuiteam.compose + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("com.qmuiteam.compose", appContext.packageName) + } +} \ No newline at end of file diff --git a/compose/src/main/AndroidManifest.xml b/compose/src/main/AndroidManifest.xml new file mode 100644 index 00000000..c2d442cf --- /dev/null +++ b/compose/src/main/AndroidManifest.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/compose/src/main/java/com/qmuiteam/compose/modal/ModalImpl.kt b/compose/src/main/java/com/qmuiteam/compose/modal/ModalImpl.kt new file mode 100644 index 00000000..5491438b --- /dev/null +++ b/compose/src/main/java/com/qmuiteam/compose/modal/ModalImpl.kt @@ -0,0 +1,188 @@ +package com.qmuiteam.compose.modal + +import android.view.View +import android.view.ViewGroup +import android.widget.FrameLayout +import androidx.activity.OnBackPressedCallback +import androidx.activity.OnBackPressedDispatcher +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.AnimatedVisibilityScope +import androidx.compose.animation.core.tween +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.ComposeView +import androidx.core.view.isVisible +import kotlinx.coroutines.flow.MutableStateFlow + +internal abstract class QMUIModalPresent( + private val rootLayout: FrameLayout, + private val onBackPressedDispatcher: OnBackPressedDispatcher, + val mask: Color = DefaultMaskColor, + val systemCancellable: Boolean = true, + val maskCancellable: Boolean = true +) : QMUIModal { + + private val onShowListeners = arrayListOf() + private val onDismissListeners = arrayListOf() + private val visibleFlow = MutableStateFlow(false) + private var isShown = false + private var isDismissing = false + + private val composeLayout = ComposeView(rootLayout.context).apply { + visibility = View.GONE + } + + private val onBackPressedCallback = object : OnBackPressedCallback(systemCancellable) { + override fun handleOnBackPressed() { + dismiss() + } + } + + init { + composeLayout.setContent { + Box(modifier = Modifier.fillMaxSize()) { + val visible by visibleFlow.collectAsState(initial = false) + ModalContent(visible = visible) { + if (isDismissing) { + doAfterDismiss() + } + } + } + } + } + + private fun doAfterDismiss() { + isDismissing = false + composeLayout.isVisible = false + composeLayout.disposeComposition() + rootLayout.removeView(composeLayout) + onBackPressedCallback.remove() + } + + @Composable + abstract fun ModalContent(visible: Boolean, dismissFinishAction: () -> Unit) + + override fun isShowing(): Boolean { + return isShown + } + + override fun show() { + if (isShown || isDismissing) { + return + } + isShown = true + rootLayout.addView(composeLayout, generateLayoutParams()) + composeLayout.visibility = View.VISIBLE + visibleFlow.value = true + onBackPressedDispatcher.addCallback(onBackPressedCallback) + } + + open fun generateLayoutParams(): FrameLayout.LayoutParams { + return FrameLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ) + } + + override fun dismiss() { + if (!isShown) { + return + } + isShown = false + isDismissing = true + visibleFlow.value = false + } + + override fun doOnShow(listener: QMUIModal.Action) { + onShowListeners.add(listener) + } + + override fun doOnDismiss(listener: QMUIModal.Action) { + onDismissListeners.add(listener) + } + + override fun removeOnShowAction(listener: QMUIModal.Action) { + onShowListeners.remove(listener) + } + + override fun removeOnDismissAction(listener: QMUIModal.Action) { + onDismissListeners.remove(listener) + } +} + +internal class StillModalImpl( + rootLayout: FrameLayout, + onBackPressedDispatcher: OnBackPressedDispatcher, + mask: Color = DefaultMaskColor, + systemCancellable: Boolean = true, + maskCancellable: Boolean = true, + val content: @Composable (modal: QMUIModal) -> Unit +) : QMUIModalPresent(rootLayout, onBackPressedDispatcher, mask, systemCancellable, maskCancellable) { + + @Composable + override fun ModalContent(visible: Boolean, dismissFinishAction: () -> Unit) { + if (visible) { + var modifier = Modifier + .fillMaxSize() + .background(mask) + if (maskCancellable) { + modifier = modifier.clickable( + interactionSource = remember { MutableInteractionSource() }, + indication = null + ) { + dismiss() + } + } + Box(modifier = modifier) + } else { + dismissFinishAction() + } + } +} + +internal class AnimateModalImpl( + rootLayout: FrameLayout, + onBackPressedDispatcher: OnBackPressedDispatcher, + mask: Color = DefaultMaskColor, + systemCancellable: Boolean = true, + maskCancellable: Boolean = true, + val content: @Composable AnimatedVisibilityScope.(modal: QMUIModal) -> Unit +) : QMUIModalPresent(rootLayout, onBackPressedDispatcher, mask, systemCancellable, maskCancellable) { + + @Composable + override fun ModalContent(visible: Boolean, dismissFinishAction: () -> Unit) { + AnimatedVisibility( + visible = visible, + enter = fadeIn(tween(300), 0f), + exit = fadeOut(tween(300), 0f) + ) { + var modifier = Modifier + .fillMaxSize() + .background(mask) + if (maskCancellable) { + modifier = modifier.clickable( + interactionSource = remember { MutableInteractionSource() }, + indication = null + ) { + dismiss() + } + } + Box(modifier = modifier) + content(this@AnimateModalImpl) + DisposableEffect("") { + onDispose { + dismissFinishAction() + } + } + } + } +} + diff --git a/compose/src/main/java/com/qmuiteam/compose/modal/QMUIDialog.kt b/compose/src/main/java/com/qmuiteam/compose/modal/QMUIDialog.kt new file mode 100644 index 00000000..31cc9cc8 --- /dev/null +++ b/compose/src/main/java/com/qmuiteam/compose/modal/QMUIDialog.kt @@ -0,0 +1,156 @@ +package com.qmuiteam.compose.modal + +import android.view.View +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.TextUnit +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp + +val DefaultDialogPaddingHor = 20.dp + +@Composable +fun QMUIDialog( + modal: QMUIModal, + horEdge: Dp = 20.dp, + verEdge: Dp = 20.dp, + widthLimit: Dp = 360.dp, + radius: Dp = 12.dp, + background: Color = Color.White, + content: @Composable (QMUIModal) -> Unit +) { + BoxWithConstraints( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = horEdge, vertical = verEdge), + contentAlignment = Alignment.Center + ) { + var modifier = if (widthLimit < maxWidth) { + Modifier.width(widthLimit) + } else { + Modifier.fillMaxWidth() + } + if (radius > 0.dp) { + modifier = modifier.clip(RoundedCornerShape(radius)) + } + modifier = modifier + .background(background) + .clickable( + interactionSource = remember { MutableInteractionSource() }, + indication = null + ) { } + Box(modifier = modifier) { + content(modal) + } + } +} + +@Composable +fun QMUIDialogTitle( + text: String, + fontSize: TextUnit = 15.sp, + textAlign: TextAlign? = null, + color: Color = Color.Black, + fontWeight: FontWeight? = FontWeight.Bold, + fontFamily: FontFamily? = null, + maxLines: Int = Int.MAX_VALUE, + lineHeight: TextUnit = 20.sp, +) { + Text( + text = text, + modifier = Modifier + .fillMaxWidth() + .padding( + top = 24.dp, + start = DefaultDialogPaddingHor, + end = DefaultDialogPaddingHor, + ), + textAlign = textAlign, + color = color, + fontSize = fontSize, + fontWeight = fontWeight, + fontFamily = fontFamily, + maxLines = maxLines, + lineHeight = lineHeight + ) +} + +@Composable +fun QMUIDialogMessageContent( + text: String, + fontSize: TextUnit = 14.sp, + textAlign: TextAlign? = null, + color: Color = Color.Black, + fontWeight: FontWeight? = FontWeight.Bold, + fontFamily: FontFamily? = null, + maxLines: Int = Int.MAX_VALUE, + lineHeight: TextUnit = 16.sp, +) { + Text( + text = text, + modifier = Modifier + .fillMaxWidth() + .padding( + start = DefaultDialogPaddingHor, + end = DefaultDialogPaddingHor, + top = 16.dp, + bottom = 24.dp + ), + textAlign = textAlign, + color = color, + fontSize = fontSize, + fontWeight = fontWeight, + fontFamily = fontFamily, + maxLines = maxLines, + lineHeight = lineHeight + ) +} + + +fun View.qmuiDialog( + mask: Color = DefaultMaskColor, + systemCancellable: Boolean = true, + maskCancellable: Boolean = true, + modalHostProvider: ModalHostProvider = DefaultModalHostProvider, + horEdge: Dp = 20.dp, + verEdge: Dp = 20.dp, + widthLimit: Dp = 360.dp, + radius: Dp = 12.dp, + background: Color = Color.White, + content: @Composable (QMUIModal) -> Unit +): QMUIModal { + return qmuiModal(mask, systemCancellable, maskCancellable, modalHostProvider) { modal -> + QMUIDialog(modal, horEdge, verEdge, widthLimit, radius, background, content) + } +} + +fun View.qmuiStillDialog( + mask: Color = DefaultMaskColor, + systemCancellable: Boolean = true, + maskCancellable: Boolean = true, + modalHostProvider: ModalHostProvider = DefaultModalHostProvider, + horEdge: Dp = 20.dp, + verEdge: Dp = 20.dp, + widthLimit: Dp = 360.dp, + radius: Dp = 12.dp, + background: Color = Color.White, + content: @Composable (QMUIModal) -> Unit +): QMUIModal { + return qmuiStillModal(mask, systemCancellable, maskCancellable, modalHostProvider) { modal -> + QMUIDialog(modal, horEdge, verEdge, widthLimit, radius, background, content) + } +} \ No newline at end of file diff --git a/compose/src/main/java/com/qmuiteam/compose/modal/QMUIModal.kt b/compose/src/main/java/com/qmuiteam/compose/modal/QMUIModal.kt new file mode 100644 index 00000000..b0b91fa3 --- /dev/null +++ b/compose/src/main/java/com/qmuiteam/compose/modal/QMUIModal.kt @@ -0,0 +1,109 @@ +package com.qmuiteam.compose.modal + +import android.view.View +import android.view.Window +import android.widget.FrameLayout +import androidx.activity.OnBackPressedDispatcher +import androidx.appcompat.app.AppCompatActivity +import androidx.compose.animation.AnimatedVisibilityScope +import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect +import androidx.compose.runtime.DisposableEffectResult +import androidx.compose.runtime.remember +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalView + +val DefaultMaskColor = Color.Black.copy(alpha = 0.5f) + +private class ModalHolder(var current: QMUIModal? = null) + +@Composable +fun QMUIModal( + isVisible: Boolean, + mask: Color = DefaultMaskColor, + systemCancellable: Boolean = true, + maskCancellable: Boolean = true, + doOnShow: QMUIModal.Action? = null, + doOnDismiss: QMUIModal.Action? = null, + modalHostProvider: ModalHostProvider = DefaultModalHostProvider, + content: @Composable AnimatedVisibilityScope.(QMUIModal) -> Unit +) { + val modalHolder = remember { + ModalHolder(null) + } + if (isVisible) { + if (modalHolder.current == null) { + val modal = LocalView.current.qmuiModal(mask, systemCancellable, maskCancellable, modalHostProvider, content) + doOnShow?.let { modal.doOnShow(it) } + doOnDismiss?.let { modal.doOnDismiss(it) } + modalHolder.current = modal + } + } else { + modalHolder.current?.dismiss() + } + DisposableEffect("") { + object : DisposableEffectResult { + override fun dispose() { + modalHolder.current?.dismiss() + } + } + } +} + +interface QMUIModal { + fun show() + fun dismiss() + fun isShowing(): Boolean + + fun doOnShow(listener: Action) + fun doOnDismiss(listener: Action) + fun removeOnShowAction(listener: Action) + fun removeOnDismissAction(listener: Action) + + fun interface Action { + fun invoke(modal: QMUIModal) + } +} + +fun interface ModalHostProvider { + fun provide(view: View): Pair +} + +class ActivityHostModalProvider : ModalHostProvider { + override fun provide(view: View): Pair { + val contentLayout = + view.rootView.findViewById(Window.ID_ANDROID_CONTENT) ?: throw RuntimeException("View is not attached to Activity") + val activity = contentLayout.context as? AppCompatActivity ?: throw RuntimeException("view's rootView's context is not AppCompatActivity") + return contentLayout to activity.onBackPressedDispatcher + } +} + +val DefaultModalHostProvider = ActivityHostModalProvider() + +fun View.qmuiModal( + mask: Color = DefaultMaskColor, + systemCancellable: Boolean = true, + maskCancellable: Boolean = true, + modalHostProvider: ModalHostProvider = DefaultModalHostProvider, + content: @Composable AnimatedVisibilityScope.(QMUIModal) -> Unit +): QMUIModal { + if (!isAttachedToWindow) { + throw RuntimeException("View is not attached to window") + } + val modalHost = modalHostProvider.provide(this) + return AnimateModalImpl(modalHost.first, modalHost.second, mask, systemCancellable, maskCancellable, content) +} + +fun View.qmuiStillModal( + mask: Color = DefaultMaskColor, + systemCancellable: Boolean = true, + maskCancellable: Boolean = true, + modalHostProvider: ModalHostProvider = DefaultModalHostProvider, + content: @Composable (QMUIModal) -> Unit +): QMUIModal { + if (!isAttachedToWindow) { + throw RuntimeException("View is not attached to window") + } + val modalHost = modalHostProvider.provide(this) + return StillModalImpl(modalHost.first, modalHost.second, mask, systemCancellable, maskCancellable, content) +} \ No newline at end of file diff --git a/compose/src/test/java/com/qmuiteam/compose/ExampleUnitTest.kt b/compose/src/test/java/com/qmuiteam/compose/ExampleUnitTest.kt new file mode 100644 index 00000000..5afcec46 --- /dev/null +++ b/compose/src/test/java/com/qmuiteam/compose/ExampleUnitTest.kt @@ -0,0 +1,17 @@ +package com.qmuiteam.compose + +import org.junit.Test + +import org.junit.Assert.* + +/** + * Example local unit test, which will execute on the development machine (host). + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +class ExampleUnitTest { + @Test + fun addition_isCorrect() { + assertEquals(4, 2 + 2) + } +} \ No newline at end of file diff --git a/plugin/build.gradle.kts b/plugin/build.gradle.kts index 250fe576..313ad4e1 100644 --- a/plugin/build.gradle.kts +++ b/plugin/build.gradle.kts @@ -1,7 +1,7 @@ plugins { `java-gradle-plugin` idea - kotlin("jvm") version "1.5.31" + kotlin("jvm") version "1.6.0" } diff --git a/plugin/settings.gradle.kts b/plugin/settings.gradle.kts new file mode 100644 index 00000000..e69de29b diff --git a/plugin/src/main/java/com/qmuiteam/plugin/Dep.kt b/plugin/src/main/java/com/qmuiteam/plugin/Dep.kt index 06fc2948..d59ae3f8 100644 --- a/plugin/src/main/java/com/qmuiteam/plugin/Dep.kt +++ b/plugin/src/main/java/com/qmuiteam/plugin/Dep.kt @@ -6,7 +6,6 @@ object Dep { val javaVersion = JavaVersion.VERSION_11 const val kotlinJvmTarget = "11" - const val kotlinVer = "1.5.31" const val compileSdk = 31 const val minSdk = 21 const val targetSdk = 31 @@ -17,6 +16,7 @@ object Dep { const val qmuiVer = "2.0.1" const val archVer = "2.0.1" const val typeVer = "0.0.14" + const val composeVer = "0.0.1" } object AndroidX { @@ -28,6 +28,20 @@ object Dep { val fragment = "androidx.fragment:fragment:1.4.0" } + object Compose { + val version = "1.1.0-rc01" + val animation = "androidx.compose.animation:animation:$version" + val ui = "androidx.compose.ui:ui:$version" + val material = "androidx.compose.material:material:$version" + val compiler = "androidx.compose.compiler:compiler:$version" + } + + object Flipper { + private const val version = "0.96.1" + const val soLoader = "com.facebook.soloader:soloader:0.10.1" + const val flipper = "com.facebook.flipper:flipper:$version" + } + object MaterialDesign { const val material = "com.google.android.material:material:1.4.0" } diff --git a/qmuidemo/build.gradle.kts b/qmuidemo/build.gradle.kts index 1d9ee002..edf5b8c9 100644 --- a/qmuidemo/build.gradle.kts +++ b/qmuidemo/build.gradle.kts @@ -43,6 +43,14 @@ android { targetCompatibility = Dep.javaVersion } + buildFeatures { + compose = true + } + + composeOptions { + kotlinCompilerExtensionVersion = Dep.Compose.version + } + defaultConfig { applicationId = "com.qmuiteam.qmuidemo" minSdk = Dep.minSdk @@ -70,6 +78,9 @@ dependencies { implementation(project(":qmui")) implementation(project(":arch")) implementation(project(":type")) + implementation(project(":compose")) + implementation(Dep.Flipper.soLoader) + implementation(Dep.Flipper.flipper) kapt(project(":compiler")) kapt(project(":arch-compiler")) } diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/QDApplication.java b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/QDApplication.java index c661cb00..b7647818 100644 --- a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/QDApplication.java +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/QDApplication.java @@ -24,6 +24,11 @@ import android.util.Log; import androidx.annotation.NonNull; +import com.facebook.flipper.android.AndroidFlipperClient; +import com.facebook.flipper.core.FlipperClient; +import com.facebook.flipper.plugins.inspector.DescriptorMapping; +import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin; +import com.facebook.soloader.SoLoader; import com.qmuiteam.qmui.QMUILog; import com.qmuiteam.qmui.arch.QMUISwipeBackActivityManager; import com.qmuiteam.qmui.qqface.QMUIQQFaceCompiler; @@ -78,6 +83,11 @@ public class QDApplication extends Application { QMUISwipeBackActivityManager.init(this); QMUIQQFaceCompiler.setDefaultQQFaceManager(QDQQFaceManager.getInstance()); QDSkinManager.install(this); + + SoLoader.init(this, false); + FlipperClient client = AndroidFlipperClient.getInstance(this); + client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults())); + client.start(); } @Override diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDButtonFragment.kt b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDButtonFragment.kt index c217d184..1349ec50 100644 --- a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDButtonFragment.kt +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDButtonFragment.kt @@ -17,8 +17,15 @@ package com.qmuiteam.qmuidemo.fragment.components import android.view.LayoutInflater import android.view.View +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.ui.Modifier import butterknife.BindView import butterknife.ButterKnife +import com.qmuiteam.compose.modal.QMUIDialogMessageContent +import com.qmuiteam.compose.modal.QMUIDialogTitle +import com.qmuiteam.compose.modal.qmuiDialog +import com.qmuiteam.qmui.arch.annotation.LatestVisitRecord import com.qmuiteam.qmui.arch.effect.MapEffect import com.qmuiteam.qmui.kotlin.onClick import com.qmuiteam.qmui.kotlin.skin @@ -30,6 +37,7 @@ import com.qmuiteam.qmuidemo.lib.annotation.Widget import com.qmuiteam.qmuidemo.manager.QDDataManager import com.qmuiteam.qmuidemo.model.QDItemDescription +@LatestVisitRecord @Widget(name = "QMUIRoundButton", iconRes = R.mipmap.icon_grid_button) class QDButtonFragment : BaseFragment() { @BindView(R.id.topbar) @@ -56,6 +64,15 @@ class QDButtonFragment : BaseFragment() { private fun initTopBar() { mTopBar.addLeftBackImageButton().onClick { popBackStack() } + mTopBar.addRightTextButton("test", View.generateViewId()).onClick { + it.qmuiDialog { + Column(modifier = Modifier.fillMaxWidth()) { + QMUIDialogTitle(text = "这是标题") + QMUIDialogMessageContent(text = "这是一点点有意思的内容") + } + + }.show() + } mTopBar.setTitle(mQDItemDescription.name) diff --git a/settings.gradle.kts b/settings.gradle.kts index 5f942fd4..3a2a1454 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -6,6 +6,7 @@ include(":arch") include(":arch-compiler") include(":arch-annotation") include(":type") +include(":compose") includeBuild("./plugin")