From ff59eb9415d3df520df98e14ef66d9a3d9804c5b Mon Sep 17 00:00:00 2001 From: Runt <qingingrunt2010@qq.com> Date: Sun, 18 May 2025 17:50:11 +0000 Subject: [PATCH] 封装dialog,popup,loading弹框, 优化权限申请 优化文件选择 --- libmvi/src/main/java/com/runt/open/mvi/base/model/BaseViewModel.kt | 48 +++++ libmvi/src/main/java/com/runt/open/mvi/retrofit/utils/RetrofitUtils.java | 13 + libmvi/src/main/java/com/runt/open/mvi/views/PublicViews.kt | 149 ++++++++++++++++++ /dev/null | 8 - libmvi/src/main/java/com/runt/open/mvi/CrashHandler.java | 2 libmvi/src/main/java/com/runt/open/mvi/data/MessageState.kt | 21 ++ libmvi/src/main/java/com/runt/open/mvi/OpenApplication.kt | 2 libmvi/build.gradle.kts | 2 libmvi/src/main/java/com/runt/open/mvi/base/LayoutView.kt | 19 ++ libmvi/src/main/java/com/runt/open/mvi/data/PopupMessage.kt | 8 + libmvi/src/main/java/com/runt/open/mvi/data/LoadingState.kt | 11 + libmvi/src/main/java/com/runt/open/mvi/base/BaseActivity.kt | 156 +++++++++++++++++++ 12 files changed, 423 insertions(+), 16 deletions(-) diff --git a/libmvi/build.gradle.kts b/libmvi/build.gradle.kts index 7c42701..a50342d 100644 --- a/libmvi/build.gradle.kts +++ b/libmvi/build.gradle.kts @@ -44,6 +44,8 @@ dependencies { + api(libs.androidx.material3) + api(platform(libs.androidx.compose.bom)) api(libs.androidx.activity.compose) api(libs.androidx.core.ktx) api(libs.androidx.lifecycle.runtime.ktx) diff --git a/libmvi/src/main/java/com/runt/open/mvi/CrashHandler.java b/libmvi/src/main/java/com/runt/open/mvi/CrashHandler.java index fee8251..4152db7 100644 --- a/libmvi/src/main/java/com/runt/open/mvi/CrashHandler.java +++ b/libmvi/src/main/java/com/runt/open/mvi/CrashHandler.java @@ -153,7 +153,7 @@ * @return 返回文件名称,便于将文件传送到服务器 */ private String saveCatchInfoFile(Throwable ex) { - //ex.printStackTrace(); + ex.printStackTrace(); //Log.i(TAG, "saveCatchInfo2File Throwable:"+ex); StringBuffer sb = new StringBuffer(); diff --git a/libmvi/src/main/java/com/runt/open/mvi/OpenApplication.kt b/libmvi/src/main/java/com/runt/open/mvi/OpenApplication.kt index 4bc247a..596fdcb 100644 --- a/libmvi/src/main/java/com/runt/open/mvi/OpenApplication.kt +++ b/libmvi/src/main/java/com/runt/open/mvi/OpenApplication.kt @@ -11,7 +11,7 @@ * @purpose * @date 6/2/24 */ -class OpenApplication :Application(){ +open class OpenApplication :Application(){ val TAG = "MyApplication" var activities : MutableList<Activity> = ArrayList() diff --git a/libmvi/src/main/java/com/runt/open/mvi/base/BaseActivity.kt b/libmvi/src/main/java/com/runt/open/mvi/base/BaseActivity.kt index 20db9c3..91dae29 100644 --- a/libmvi/src/main/java/com/runt/open/mvi/base/BaseActivity.kt +++ b/libmvi/src/main/java/com/runt/open/mvi/base/BaseActivity.kt @@ -1,17 +1,24 @@ package com.runt.open.mvi.base +import android.Manifest import android.app.ActivityManager +import android.content.ContentResolver import android.content.Context import android.content.Intent import android.content.pm.PackageManager +import android.net.Uri import android.os.Build import android.os.Bundle import android.os.Environment +import android.provider.MediaStore +import android.provider.Settings +import android.text.TextUtils import android.util.Log import android.view.MotionEvent import android.view.View import android.view.WindowManager import android.view.inputmethod.InputMethodManager +import android.webkit.MimeTypeMap import android.widget.EditText import android.widget.Toast import androidx.activity.ComponentActivity @@ -53,6 +60,11 @@ val PARAMS_TITLE = "title" + private var requestFileResult:Observer<List<String>>? = null; + + private var fileLauncher : ActivityResultLauncher<Intent>? = null //选择文件 + private var filePermissionLauncher : ActivityResultLauncher<Intent>? = null //文件权限 + private val fileUriList = mutableListOf<Uri>() override fun onCreate(savedInstanceState : Bundle?) { super.onCreate(savedInstanceState) // get genericity "B" @@ -77,7 +89,7 @@ init(); //setContentView(mLayout) setContent { - mLayout!!.layout() + mLayout!!.layoutFrame() } mContext = this TAG = this.javaClass.simpleName @@ -85,18 +97,20 @@ mViewModel!!.onCreate(this as BaseActivity<LayoutView<BaseViewModel> , BaseViewModel>) loadData() //加载数据 } + abstract fun init() abstract fun initViews() abstract fun loadData() - fun registerPermissionResult(){ + protected fun registerPermissionResult(){ permissionsLauncher = this.registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { result -> if (result == null || result.size === 0) { permissionObserver !!.onChanged("") return@registerForActivityResult } + mViewModel!!.hidePopupWindow() Log.d(TAG , "result:" + result + " size:" + result.size) var allGranted = true for (key in result.keys) { @@ -112,6 +126,115 @@ permissionObserver !!.onChanged(com.google.gson.Gson().toJson(result.keys).replace("[" , "").replace("]" , "").replace("\"" , "")) } } + } + + protected fun registerFileResult(){ + + filePermissionLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> + Log.i(TAG,"filePermission ${result}") + onRequestFileResult(); + } + //选择文件 + fileLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult() , object : ActivityResultCallback<ActivityResult?> { + override fun onActivityResult(result : ActivityResult?) { + Log.i(TAG,"fileLauncher ${result!!.data?.data}") + Log.i(TAG,"fileLauncher clipData= ${result!!.data?.clipData}") + fileUriList.clear(); + result!!.data?.data?.let{ + fileUriList.add(it); + } + result!!.data?.clipData?.let{ + val count = it.itemCount + for (i in 0 until count) { + fileUriList.add(it.getItemAt(i).uri) + } + } + if(fileUriList.size == 0){ + requestFileResult?.onChanged(ArrayList()) + }else{ + onRequestFileResult(); + } + } + }) + } + + private fun onRequestFileResult(){ + + val cR : ContentResolver = getContentResolver() + val mime = MimeTypeMap.getSingleton() + var filePath = mViewModel!!.getFilePathFromUri(fileUriList.get(0)!!); + //文件不存在或读写权限受限 + if(filePath == null){ + //android 11需要申请权限 //是否有所有问读写权限 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && ! Environment.isExternalStorageManager()) { + //跳转到打开权限页面 + var intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION); + + intent.setData(Uri.parse("package:" + mContext!!.getPackageName())); + filePermissionLauncher!!.launch(intent) + return; + } + requestFileResult?.onChanged(ArrayList()) + }else{ + var filePathes = ArrayList<String>() + for (i in 0 until fileUriList.size) { + var filePath = mViewModel!!.getFilePathFromUri(fileUriList.get(i)!!); + filePathes.add(filePath!!) + } + requestFileResult?.onChanged(filePathes) + } + } + + fun requestFile(fileType :String,maxCount:Int = 1,fileResult:Observer<List<String>>){ + requestFileResult = fileResult; + var permissions = ""; + //android 13 权限申请细化类型 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + permissions = fileType ; + //android 14 选择文件授权 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + permissions+=","+ Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED; + } + }else{ + //读取权限 + permissions = Manifest.permission.READ_EXTERNAL_STORAGE ; + } + //申请权限 + requestPermissions(permissions , object :Observer<String>{ + override fun onChanged(value : String) { + if(!value.isEmpty()){ + var intent = Intent() + // intent.action = Intent.ACTION_PICK + // intent.action = Intent.ACTION_GET_CONTENT + + //intent.setType("image/*") + when(fileType){ + Manifest.permission.READ_MEDIA_VIDEO ->{ + intent.action = MediaStore.ACTION_PICK_IMAGES + intent.setType("video/*") // 设置文件类型,可以更具体如"application/pdf" + } + Manifest.permission.READ_MEDIA_AUDIO ->{ + intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI) + intent.setType("audio/*") // 设置文件类型,可以更具体如"application/pdf" + } + Manifest.permission.READ_MEDIA_IMAGES ->{ + intent.action = MediaStore.ACTION_PICK_IMAGES + intent.setType("image/*") // 设置文件类型,可以更具体如"application/pdf" + } + else -> {} + } + // 设置可多选 + intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, maxCount > 1); + if(maxCount > 1){ + //设置最大数量 + intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, maxCount); + } + fileLauncher!!.launch(intent) + }else{ + requestFileResult?.onChanged(ArrayList()) + } + } + }) } fun registerForActivityResult(callback : ActivityResultCallback<ActivityResult>):ActivityResultLauncher<Intent>{ @@ -271,7 +394,33 @@ allGranted = false if (showPop) { // TODO: - //showPermissionPopu(permission) + var title = "" + var message = ""; + if(permissions.contains(Manifest.permission.READ_EXTERNAL_STORAGE)){ + title = "申请文件读取权限"; + message = "通过文件读取权限后,可无障碍使用图片、音乐、视频并添加到直播的音视频流中" + }else if(permissions.contains(Manifest.permission.CAMERA)){ + title = "申请相机权限"; + message = "通过相机权限后,可将相机画面添加到直播画面流中" + }else if(permissions.contains(Manifest.permission.RECORD_AUDIO)){ + title = "申请话筒权限"; + message = "通过话筒权限后,可将话筒声音添加到直播声音流中" + }else if(permissions.contains(Manifest.permission.READ_MEDIA_IMAGES)){ + title = "申请图片和视频文件权限"; + message = "通过图片和视频文件权限后,可将图片和视频画面添加到直播画面流中" + }else if(permissions.contains(Manifest.permission.READ_MEDIA_VIDEO)){ + title = "申请图片和视频文件权限"; + message = "通过图片和视频文件权限后,可将图片和视频画面添加到直播画面流中" + }else if(permissions.contains(Manifest.permission.READ_MEDIA_AUDIO)){ + title = "申请音频文件权限"; + message = "通过音频文件权限后,可将音频文件的声音添加到直播声音流中" + }/*else if(permissions.contains(Manifest.permission.POST_NOTIFICATIONS)){ + title = "申请通知栏权限"; + message = "通过通知栏权限后,可开启后台服务,保证相机、话筒、截屏、扬声器等功能不被系统终止" + }*/ + if(!TextUtils.isEmpty(title)){ + mViewModel!!.showPopupWindow(title = title, message = message) + } } break } @@ -281,6 +430,7 @@ var permissionsLauncher : ActivityResultLauncher<Array<String>>? = null //权限 var permissionObserver : Observer<String>? = null //权限和文件请求回调 + /** * 统一权限申请 */ diff --git a/libmvi/src/main/java/com/runt/open/mvi/base/LayoutView.kt b/libmvi/src/main/java/com/runt/open/mvi/base/LayoutView.kt index 38aa0d7..5a863fc 100644 --- a/libmvi/src/main/java/com/runt/open/mvi/base/LayoutView.kt +++ b/libmvi/src/main/java/com/runt/open/mvi/base/LayoutView.kt @@ -1,7 +1,12 @@ package com.runt.open.mvi.base import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue import com.runt.open.mvi.base.model.BaseViewModel +import com.runt.open.mvi.views.LoadingDialog +import com.runt.open.mvi.views.MessageDialog +import com.runt.open.mvi.views.PopupWindow /** * @author Runt(qingingrunt2010@qq.com) @@ -13,5 +18,17 @@ val TAG : String = javaClass.simpleName @Composable - abstract fun layout(); + fun layoutFrame(){ + val isLoading by mViewModel.isLoading.collectAsState() + val messageState by mViewModel.messageState.collectAsState() + val popupState by mViewModel.popupState.collectAsState() + layout() + // 显示 loading 弹窗 + LoadingDialog(isLoading) + MessageDialog(messageState) + PopupWindow(popupState) + } + + @Composable + protected abstract fun layout(); } \ No newline at end of file diff --git a/libmvi/src/main/java/com/runt/open/mvi/base/model/BaseViewModel.kt b/libmvi/src/main/java/com/runt/open/mvi/base/model/BaseViewModel.kt index 8ecb0d2..12fedd1 100644 --- a/libmvi/src/main/java/com/runt/open/mvi/base/model/BaseViewModel.kt +++ b/libmvi/src/main/java/com/runt/open/mvi/base/model/BaseViewModel.kt @@ -7,14 +7,18 @@ import android.util.Log import androidx.activity.ComponentActivity import androidx.core.content.FileProvider -import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import com.runt.open.mvi.base.BaseActivity import com.runt.open.mvi.base.LayoutView +import com.runt.open.mvi.data.LoadingState +import com.runt.open.mvi.data.MessageState +import com.runt.open.mvi.data.PopupMessage import com.runt.open.mvi.retrofit.AndroidScheduler import io.reactivex.Observable import io.reactivex.Observer import io.reactivex.schedulers.Schedulers +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow import okhttp3.Callback import okhttp3.OkHttpClient import okhttp3.Request @@ -35,7 +39,18 @@ var TAG = ""; protected var mActivity : BaseActivity<LayoutView<BaseViewModel> , BaseViewModel>? = null - var verifyResult = MutableLiveData<Int>() + + private val _isLoading = MutableStateFlow(LoadingState()) + val isLoading = _isLoading.asStateFlow() + + val messageSetDismiss = { + _messageState.value = _messageState.value.copy(isVisible = false); + } + private val _messageState = MutableStateFlow(MessageState(isVisible = false, setDismiss = { })) + val messageState = _messageState.asStateFlow() + + private val _popupState = MutableStateFlow(PopupMessage(isVisible = false,"","")) + val popupState = _popupState.asStateFlow() open fun onCreate(activity : BaseActivity<LayoutView<BaseViewModel> , BaseViewModel>) { mActivity = activity @@ -46,6 +61,35 @@ return mActivity!!; } + fun showLoading(message : String = "加载中...") { + _isLoading.value = LoadingState(isVisible = true,message = message); + } + + fun hideLoading() { + _isLoading.value = _isLoading.value.copy(isVisible = false); + } + + fun showDialog( title:String = "", message: String = "", confirmText:String = "确定", cancelText:String = "", + touchOutside:Boolean = true,//空白和系统返回 是否关闭 + showClose:Boolean = false,//显示关闭图标(默认不显示) + confirmDissmiss:Boolean = true,//点击确定是否关闭 + cancelDissmiss:Boolean = true,//点击取消是否关闭 + onDismissRequest : () -> Unit = {}, + onConfirmRequest : () -> Unit = {}, ){ + + _messageState.value = MessageState(title = title, message = message, touchOutside = touchOutside, showClose = showClose, confirmText = confirmText, + cancelText = cancelText, confirmDissmiss = confirmDissmiss, cancelDissmiss = cancelDissmiss, onDismissRequest = onDismissRequest, + onConfirmRequest = onConfirmRequest, setDismiss = messageSetDismiss); + } + + fun showPopupWindow(title : String,message : String){ + _popupState.value = PopupMessage(isVisible = true,title,message) + } + + fun hidePopupWindow(){ + _popupState.value = _popupState.value.copy(isVisible = false); + } + /** * 获取用户信息 */ diff --git a/libmvi/src/main/java/com/runt/open/mvi/data/LoadingState.kt b/libmvi/src/main/java/com/runt/open/mvi/data/LoadingState.kt new file mode 100644 index 0000000..0e022d2 --- /dev/null +++ b/libmvi/src/main/java/com/runt/open/mvi/data/LoadingState.kt @@ -0,0 +1,11 @@ +package com.runt.open.mvi.data + +/** + * @author Runt(qingingrunt2010@qq.com) + * @purpose + * @date 5/18/25 + */ +data class LoadingState( + val isVisible: Boolean = false, + val message: String = "加载中...", +) diff --git a/libmvi/src/main/java/com/runt/open/mvi/data/MessageState.kt b/libmvi/src/main/java/com/runt/open/mvi/data/MessageState.kt new file mode 100644 index 0000000..3ff6b7e --- /dev/null +++ b/libmvi/src/main/java/com/runt/open/mvi/data/MessageState.kt @@ -0,0 +1,21 @@ +package com.runt.open.mvi.data + +/** + * @author Runt(qingingrunt2010@qq.com) + * @purpose + * @date 5/18/25 + */ +data class MessageState( + val isVisible: Boolean = true, + val title:String = "", + val message: String = "加载中...", + val confirmText:String = "确定", + val cancelText:String = "", + val touchOutside:Boolean = true,//空白和系统返回 是否关闭 + val showClose:Boolean = false,//显示关闭图标(默认不显示) + val confirmDissmiss:Boolean = true,//点击确定是否关闭 + val cancelDissmiss:Boolean = true,//点击取消是否关闭 + val onDismissRequest : () -> Unit = {}, + val onConfirmRequest : () -> Unit = {}, + var setDismiss:() -> Unit +) \ No newline at end of file diff --git a/libmvi/src/main/java/com/runt/open/mvi/data/PopupMessage.kt b/libmvi/src/main/java/com/runt/open/mvi/data/PopupMessage.kt new file mode 100644 index 0000000..58767b5 --- /dev/null +++ b/libmvi/src/main/java/com/runt/open/mvi/data/PopupMessage.kt @@ -0,0 +1,8 @@ +package com.runt.open.mvi.data + +/** + * @author Runt(qingingrunt2010@qq.com) + * @purpose + * @date 5/19/25 + */ +data class PopupMessage(var isVisible:Boolean,val title:String,val message:String) \ No newline at end of file diff --git a/libmvi/src/main/java/com/runt/open/mvi/interfaces/UIIntent.kt b/libmvi/src/main/java/com/runt/open/mvi/interfaces/UIIntent.kt deleted file mode 100644 index d6dc2b0..0000000 --- a/libmvi/src/main/java/com/runt/open/mvi/interfaces/UIIntent.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.runt.open.mvi.interfaces - -/** - * @author Runt(qingingrunt2010@qq.com) - * @purpose - * @date 6/2/24 - */ -interface UIIntent {} \ No newline at end of file diff --git a/libmvi/src/main/java/com/runt/open/mvi/interfaces/UIState.kt b/libmvi/src/main/java/com/runt/open/mvi/interfaces/UIState.kt deleted file mode 100644 index 99dd6bf..0000000 --- a/libmvi/src/main/java/com/runt/open/mvi/interfaces/UIState.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.runt.open.mvi.interfaces - -/** - * @author Runt(qingingrunt2010@qq.com) - * @purpose - * @date 6/2/24 - */ -interface UIState {} \ No newline at end of file diff --git a/libmvi/src/main/java/com/runt/open/mvi/retrofit/utils/RetrofitUtils.java b/libmvi/src/main/java/com/runt/open/mvi/retrofit/utils/RetrofitUtils.java index 39695c3..b5b0988 100644 --- a/libmvi/src/main/java/com/runt/open/mvi/retrofit/utils/RetrofitUtils.java +++ b/libmvi/src/main/java/com/runt/open/mvi/retrofit/utils/RetrofitUtils.java @@ -38,6 +38,15 @@ return instance; } + private Retrofit getRetrofit(OkHttpClient client,Retrofit.Builder builder,String url){ + return builder + //设置OKHttpClient + .client(client) + //设置baseUrl,注意,baseUrl必须后缀"/" + .baseUrl(url) + .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) + .build(); + } /** * log输出,gson驼峰转换 * @return @@ -53,6 +62,10 @@ return retrofit.create(clas); } + public <T> T getTempRetrofit(Class<T> clas,String url) { + return getRetrofit(getOkHttpClient(new OkHttpClient.Builder().addInterceptor(new HttpLoggingInterceptor(BuildConfig.DEBUG))), + new Retrofit.Builder().addConverterFactory(GsonConverterFactory.create(true)),url).create(clas); + } /** * log输出,gson不转换驼峰 * @return diff --git a/libmvi/src/main/java/com/runt/open/mvi/views/PublicViews.kt b/libmvi/src/main/java/com/runt/open/mvi/views/PublicViews.kt new file mode 100644 index 0000000..3dd7708 --- /dev/null +++ b/libmvi/src/main/java/com/runt/open/mvi/views/PublicViews.kt @@ -0,0 +1,149 @@ +package com.runt.open.mvi.views + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Button +import androidx.compose.material3.Card +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +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.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.compose.ui.window.Dialog +import androidx.compose.ui.window.Popup +import com.runt.open.mvi.data.LoadingState +import com.runt.open.mvi.data.MessageState +import com.runt.open.mvi.data.PopupMessage + +/** + * @author Runt(qingingrunt2010@qq.com) + * @purpose + * @date 5/18/25 + */ + +@Composable +fun LoadingDialog( loadingState : LoadingState) { + if (loadingState.isVisible) { + Dialog(onDismissRequest = {}) { + Column( + modifier = Modifier + .size(140.dp) + .clip(RoundedCornerShape(16.dp)) + .background(Color.White), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + CircularProgressIndicator() + Spacer(modifier = Modifier.height(12.dp)) + Text( + text = loadingState.message, + fontSize = 14.sp, + color = Color.Black + ) + } + } + } +} + +@Composable +fun MessageDialog(message : MessageState){ + if(message.isVisible){ + Dialog(onDismissRequest = { + if(message.cancelDissmiss){ + message.setDismiss.invoke() + } + message.onDismissRequest + }) { + Card( + modifier = Modifier + .fillMaxWidth() + .wrapContentHeight() + .padding(16.dp), + shape = RoundedCornerShape(16.dp), + ) { + Column(modifier = Modifier.wrapContentHeight()){ + Text(text = message.title, fontSize = 16.sp, + modifier = Modifier.fillMaxWidth() + .padding(top = 20.dp , start = 20.dp) + .wrapContentSize(Alignment.Center), + textAlign = TextAlign.Center) + Text( + text = message.message, + modifier = Modifier + .fillMaxWidth() + .wrapContentSize() + .padding(top = 30.dp , bottom = 20.dp, start = 14.dp, end = 15.dp) + .wrapContentSize(Alignment.Center), + textAlign = TextAlign.Center, + ) + Row (modifier = Modifier.padding(start = 15.dp, end = 15.dp, bottom = 20.dp)){ + if(!message.cancelText.equals("")){ + Spacer(modifier = Modifier.weight(1f)) + Button(onClick = { + if(message.cancelDissmiss){ + message.setDismiss.invoke() + } + message.onDismissRequest + }) { + Text(text = message.cancelText) + } + } + Spacer(modifier = Modifier.weight(1f)) + Button(onClick = { + if(message.confirmDissmiss){ + message.setDismiss.invoke() + } + message.onConfirmRequest + }) { + Text(text = message.confirmText) + } + } + } + } + } + } +} + +@Composable +fun PopupWindow(popupMessage : PopupMessage){ + if(popupMessage.isVisible){ + Popup( + alignment = Alignment.TopCenter, + ) { + Surface( + modifier = Modifier.fillMaxWidth() + .wrapContentHeight().padding(10.dp), + shadowElevation = 2.dp, + border = BorderStroke(1.dp, Color.Gray) , + shape = RoundedCornerShape(8.dp) + ) { + Column( + modifier = Modifier.padding(16.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text(popupMessage.title) + Spacer(modifier = Modifier.height(16.dp)) + Text(popupMessage.message) + Spacer(modifier = Modifier.height(15.dp)) + } + } + } + } +} \ No newline at end of file -- Gitblit v1.9.1