You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
497 lines
19 KiB
497 lines
19 KiB
package com.gyf.csams.activity.ui
|
|
|
|
import android.Manifest
|
|
import android.content.pm.PackageManager
|
|
import android.os.Bundle
|
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
|
import androidx.activity.compose.setContent
|
|
import androidx.activity.result.contract.ActivityResultContracts
|
|
import androidx.appcompat.app.AppCompatActivity
|
|
import androidx.compose.foundation.clickable
|
|
import androidx.compose.foundation.layout.*
|
|
import androidx.compose.foundation.lazy.LazyColumn
|
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
|
import androidx.compose.foundation.text.KeyboardOptions
|
|
import androidx.compose.material.*
|
|
import androidx.compose.runtime.Composable
|
|
import androidx.compose.runtime.LaunchedEffect
|
|
import androidx.compose.runtime.getValue
|
|
import androidx.compose.runtime.livedata.observeAsState
|
|
import androidx.compose.runtime.rememberCoroutineScope
|
|
import androidx.compose.ui.Alignment
|
|
import androidx.compose.ui.Modifier
|
|
import androidx.compose.ui.platform.LocalFocusManager
|
|
import androidx.compose.ui.res.painterResource
|
|
import androidx.compose.ui.res.stringResource
|
|
import androidx.compose.ui.text.input.KeyboardType
|
|
import androidx.compose.ui.unit.dp
|
|
import androidx.compose.ui.viewinterop.AndroidView
|
|
import androidx.core.content.ContextCompat
|
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
|
import com.baidu.location.LocationClient
|
|
import com.baidu.location.LocationClientOption
|
|
import com.baidu.mapapi.map.MapStatusUpdateFactory
|
|
import com.baidu.mapapi.search.sug.SuggestionResult
|
|
import com.google.android.material.datepicker.MaterialDatePicker
|
|
import com.gyf.csams.MainApplication
|
|
import com.gyf.csams.MyLocationListener
|
|
import com.gyf.csams.R
|
|
import com.gyf.csams.activity.model.ApplyActViewModel
|
|
import com.gyf.csams.uikit.Background
|
|
import com.gyf.csams.uikit.BackgroundImage
|
|
import com.gyf.csams.uikit.DescCard
|
|
import com.gyf.lib.uikit.BaseTextField
|
|
import com.gyf.lib.uikit.Body
|
|
import com.gyf.lib.uikit.MainColumnFrame
|
|
import com.gyf.lib.uikit.ScaffoldModel
|
|
import com.gyf.lib.util.BottomButton
|
|
import com.gyf.lib.util.format
|
|
import com.orhanobut.logger.Logger
|
|
import kotlinx.coroutines.launch
|
|
import java.util.*
|
|
|
|
|
|
val location_permissions = arrayOf(
|
|
Manifest.permission.ACCESS_COARSE_LOCATION,
|
|
Manifest.permission.ACCESS_FINE_LOCATION,
|
|
Manifest.permission.ACCESS_WIFI_STATE,
|
|
Manifest.permission.ACCESS_NETWORK_STATE,
|
|
Manifest.permission.CHANGE_WIFI_STATE
|
|
)
|
|
|
|
|
|
/**
|
|
* 申请活动
|
|
*
|
|
*/
|
|
class ApplyActActivity : AppCompatActivity() {
|
|
|
|
private lateinit var mLocationClient: LocationClient
|
|
|
|
override fun onStop() {
|
|
super.onStop()
|
|
mLocationClient.stop()
|
|
}
|
|
|
|
|
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
super.onCreate(savedInstanceState)
|
|
|
|
mLocationClient = (application as MainApplication).mLocationClient
|
|
|
|
setContent {
|
|
Body {
|
|
MainColumnFrame(background = { Background(image = BackgroundImage.ApplyActivity) }) {
|
|
val model: ApplyActViewModel = viewModel()
|
|
val scaffoldModel: ScaffoldModel = viewModel()
|
|
model.scaffoldModel = scaffoldModel
|
|
val showMap by model.showMap.observeAsState(false)
|
|
val location by MyLocationListener.location.observeAsState()
|
|
|
|
when {
|
|
showMap && location != null -> {
|
|
Box {
|
|
val sugResult by model.sugResult.observeAsState()
|
|
|
|
Column(modifier = Modifier.fillMaxSize()) {
|
|
AndroidView(modifier = Modifier
|
|
.weight(0.6F)
|
|
.fillMaxWidth(),
|
|
factory = { context -> model.createMapView(context) })
|
|
|
|
if (sugResult == null || sugResult?.size == 0) {
|
|
PoiItem(
|
|
modifier = Modifier
|
|
.weight(0.4F)
|
|
.fillMaxWidth()
|
|
)
|
|
}
|
|
|
|
}
|
|
|
|
Column(modifier = Modifier.fillMaxSize()) {
|
|
|
|
Search(
|
|
modifier = Modifier
|
|
.weight(0.2F)
|
|
.fillMaxWidth()
|
|
)
|
|
|
|
sugResult.let {
|
|
if (it.isNullOrEmpty()) {
|
|
Spacer(
|
|
modifier = Modifier
|
|
.weight(0.8F)
|
|
.fillMaxWidth()
|
|
)
|
|
} else {
|
|
SuggestItem(
|
|
modifier = Modifier
|
|
.weight(0.8F)
|
|
.fillMaxWidth(),
|
|
sugResult = it
|
|
)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
else -> {
|
|
Title(modifier = Modifier.weight(0.2F))
|
|
Row(
|
|
Modifier
|
|
.weight(0.1F)
|
|
.fillMaxWidth(), horizontalArrangement = Arrangement.Center
|
|
) {
|
|
BaseTextField(form = model.activityName)
|
|
}
|
|
Row(
|
|
Modifier
|
|
.weight(0.1F)
|
|
.fillMaxWidth(),
|
|
horizontalArrangement = Arrangement.Center
|
|
) {
|
|
ActivityTime()
|
|
}
|
|
ActivityLocation(
|
|
modifier = Modifier
|
|
.weight(0.15F)
|
|
.fillMaxWidth()
|
|
)
|
|
DescCard(
|
|
modifier = Modifier.weight(0.3F),
|
|
stringForm = model.activityDesc
|
|
)
|
|
//TODO 活动人数不合法警告
|
|
// val error by model.activitySize.formError.observeAsState()
|
|
// if (error?.isNotEmpty() == true) {
|
|
// scaffoldModel.update(message = error)
|
|
// }
|
|
Row(
|
|
Modifier
|
|
.weight(0.1F)
|
|
.fillMaxWidth(), horizontalArrangement = Arrangement.Center
|
|
) {
|
|
BaseTextField(
|
|
form = model.activitySize,
|
|
keyboardOptions =
|
|
KeyboardOptions.Default.copy(keyboardType = KeyboardType.Number)
|
|
)
|
|
}
|
|
Spacer(modifier = Modifier.weight(0.05F))
|
|
BottomButton(modifier = Modifier.fillMaxWidth()) {
|
|
model.apply { scaffoldModel.update(message = it) }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Composable
|
|
private fun SelectIcon(modifier: Modifier = Modifier) {
|
|
IconButton(modifier = modifier, onClick = {
|
|
|
|
}) {
|
|
Icon(
|
|
painter = painterResource(id = R.drawable.ic_seleted),
|
|
contentDescription = null
|
|
)
|
|
}
|
|
}
|
|
|
|
@Composable
|
|
private fun Search(
|
|
modifier: Modifier = Modifier,
|
|
model: ApplyActViewModel = viewModel()
|
|
) {
|
|
Column(
|
|
modifier = modifier
|
|
.fillMaxWidth()
|
|
// .border(width = 1.dp, color = MaterialTheme.colors.onBackground)
|
|
,
|
|
verticalArrangement = Arrangement.SpaceAround
|
|
) {
|
|
Card(backgroundColor = MaterialTheme.colors.background) {
|
|
Row(modifier = Modifier.fillMaxWidth()) {
|
|
BaseTextField(modifier = Modifier.weight(0.5F),
|
|
form = model.city, leadingIcon = {
|
|
Text(
|
|
text = stringResource(id = R.string.at),
|
|
style = MaterialTheme.typography.subtitle2
|
|
)
|
|
}, trailingIcon = {
|
|
Text(
|
|
text = stringResource(id = R.string.incity),
|
|
style = MaterialTheme.typography.subtitle2
|
|
)
|
|
}, textStyle = MaterialTheme.typography.subtitle2
|
|
)
|
|
BaseTextField(modifier = Modifier.weight(0.5F), form = model.address)
|
|
}
|
|
}
|
|
// Row(
|
|
// modifier = Modifier.fillMaxWidth(),
|
|
// horizontalArrangement = Arrangement.Center
|
|
// ) {
|
|
// OutlinedButton(onClick = {
|
|
// model.searchPoiInCity()
|
|
// }) {
|
|
// Text(text = stringResource(id = R.string.search_btn))
|
|
// }
|
|
// }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@Composable
|
|
private fun SuggestItem(
|
|
modifier: Modifier = Modifier,
|
|
model: ApplyActViewModel = viewModel(),
|
|
sugResult: List<SuggestionResult.SuggestionInfo>
|
|
) {
|
|
val state = rememberLazyListState()
|
|
val focusManager = LocalFocusManager.current
|
|
LazyColumn(modifier = modifier, state = state) {
|
|
sugResult.forEach {
|
|
item {
|
|
Card(backgroundColor = MaterialTheme.colors.background) {
|
|
Column(
|
|
modifier = Modifier
|
|
.fillMaxWidth()
|
|
.clickable(onClick = {
|
|
focusManager.clearFocus()
|
|
model.locateSuggestPoi(suggestInfo = it)
|
|
})
|
|
) {
|
|
Text(text = it.key)
|
|
it.address?.let {
|
|
Text(text = it)
|
|
}
|
|
}
|
|
}
|
|
Divider(color = MaterialTheme.colors.onBackground)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@Composable
|
|
private fun PoiItem(
|
|
modifier: Modifier = Modifier,
|
|
model: ApplyActViewModel = viewModel()
|
|
) {
|
|
val state = rememberLazyListState()
|
|
val poiInfo by model.poiInfo.observeAsState()
|
|
val selectPoi by model.selectPoi.observeAsState()
|
|
val mapView by model.mapView.observeAsState()
|
|
LazyColumn(modifier = modifier, state = state) {
|
|
poiInfo?.withIndex()?.forEach { it ->
|
|
if (it.value.name?.isNotEmpty() == true || it.value.address?.isNotEmpty() == true) {
|
|
item {
|
|
Card(modifier = Modifier.clickable(onClick = {
|
|
model.updateStatusChangeByItemClick(true)
|
|
val mapStatusUpdate =
|
|
MapStatusUpdateFactory.newLatLng(it.value.getLocation())
|
|
mapView?.map?.setMapStatus(mapStatusUpdate)
|
|
model.updateSelectPoi(it.value)
|
|
}), backgroundColor = MaterialTheme.colors.background) {
|
|
Row(
|
|
modifier = Modifier
|
|
.fillMaxWidth(),
|
|
horizontalArrangement = Arrangement.SpaceBetween,
|
|
verticalAlignment = Alignment.CenterVertically
|
|
) {
|
|
if (it.index == 0) {
|
|
Text(
|
|
text = "【${it.value.address}】",
|
|
color = MaterialTheme.colors.primary,
|
|
modifier = Modifier.weight(0.8F)
|
|
)
|
|
if (selectPoi == null || selectPoi == it.value) {
|
|
SelectIcon(modifier = Modifier.weight(0.2F))
|
|
} else {
|
|
Spacer(modifier = Modifier.weight(0.2F))
|
|
}
|
|
} else {
|
|
Column(
|
|
modifier = Modifier.weight(0.8F)
|
|
) {
|
|
Text(
|
|
text = it.value.name,
|
|
color = MaterialTheme.colors.primary
|
|
)
|
|
it.value.address?.let {
|
|
Text(text = it, color = MaterialTheme.colors.secondary)
|
|
}
|
|
}
|
|
if (selectPoi == it.value) {
|
|
SelectIcon(modifier = Modifier.weight(0.2F))
|
|
} else {
|
|
Spacer(modifier = Modifier.weight(0.2F))
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
Spacer(modifier = Modifier.height(10.dp))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
poiInfo?.apply {
|
|
LaunchedEffect(poiInfo) {
|
|
launch {
|
|
if (size > 0) {
|
|
state.animateScrollToItem(0)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
@Composable
|
|
private fun Title(modifier: Modifier = Modifier) {
|
|
Box(modifier = modifier.fillMaxWidth(), contentAlignment = Alignment.Center) {
|
|
Text(
|
|
text = stringResource(id = R.string.activity_application),
|
|
style = MaterialTheme.typography.h4
|
|
)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 活动时间
|
|
*
|
|
* @param modifier
|
|
* @param model
|
|
*/
|
|
@Composable
|
|
private fun ActivityTime(
|
|
modifier: Modifier = Modifier,
|
|
model: ApplyActViewModel = viewModel()
|
|
) {
|
|
val scope = rememberCoroutineScope()
|
|
BaseTextField(
|
|
modifier = modifier,
|
|
form = model.activityTime, readOnly = true
|
|
) {
|
|
IconButton(onClick = {
|
|
scope.launch {
|
|
val picker = MaterialDatePicker
|
|
.Builder
|
|
.datePicker()
|
|
.setSelection(Date().time)
|
|
.build()
|
|
picker.show(supportFragmentManager, picker.toString())
|
|
picker.addOnPositiveButtonClickListener {
|
|
model.activityTime.onChange(Date(it).format())
|
|
}
|
|
}
|
|
|
|
}) {
|
|
Icon(
|
|
painter = painterResource(id = R.drawable.ic_date),
|
|
contentDescription = null
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
private fun requestLocation() {
|
|
//如果想获取地址信息,需在配置LocationClientOption类时做相应的设置
|
|
val option = LocationClientOption()
|
|
option.locationMode = LocationClientOption.LocationMode.Hight_Accuracy
|
|
//可选,是否需要地址信息,默认为不需要,即参数为false
|
|
//如果开发者需要获得当前点的地址信息,此处必须为true
|
|
option.setIsNeedAddress(true)
|
|
//可选,设置是否需要最新版本的地址信息。默认需要,即参数为true
|
|
option.setNeedNewVersionRgc(true)
|
|
|
|
|
|
mLocationClient.locOption = option
|
|
Logger.i("开始定位")
|
|
mLocationClient.start()
|
|
}
|
|
|
|
|
|
private fun checkSelfPermissions(): Int {
|
|
location_permissions.forEach {
|
|
when (val v = ContextCompat.checkSelfPermission(this, it)) {
|
|
PackageManager.PERMISSION_GRANTED -> Logger.i("权限${it}已放通")
|
|
else -> {
|
|
Logger.i("权限${it}检查状态:$v")
|
|
return v
|
|
}
|
|
}
|
|
|
|
}
|
|
Logger.i("已授权")
|
|
return PackageManager.PERMISSION_GRANTED
|
|
}
|
|
|
|
/**
|
|
* 活动地点
|
|
*
|
|
* @param modifier
|
|
* @param model
|
|
*/
|
|
@Composable
|
|
private fun ActivityLocation(
|
|
modifier: Modifier = Modifier,
|
|
model: ApplyActViewModel = viewModel(),
|
|
scaffoldModel: ScaffoldModel = viewModel()
|
|
) {
|
|
val launcher = rememberLauncherForActivityResult(
|
|
ActivityResultContracts.RequestMultiplePermissions()
|
|
) { it ->
|
|
var isGranted = true
|
|
it.entries.forEach {
|
|
isGranted = isGranted && it.value
|
|
Logger.i("权限:${it.key}授权结果:${it.value}")
|
|
}
|
|
|
|
if (isGranted) {
|
|
// Permission Accepted: Do something
|
|
requestLocation()
|
|
model.openMap()
|
|
Logger.i("准备打开地图")
|
|
} else {
|
|
// Permission Denied: Do something
|
|
scaffoldModel.update(message = getString(R.string.denined_location_permission))
|
|
}
|
|
}
|
|
|
|
BaseTextField(modifier = modifier, form = model.activityAddress, readOnly = true) {
|
|
IconButton(onClick = {
|
|
when (PackageManager.PERMISSION_GRANTED) {
|
|
checkSelfPermissions() -> {
|
|
// Some works that require permission
|
|
requestLocation()
|
|
model.openMap()
|
|
Logger.i("准备打开地图")
|
|
}
|
|
else -> {
|
|
// Asking for permission
|
|
Logger.i("询问权限")
|
|
launcher.launch(location_permissions)
|
|
}
|
|
}
|
|
}) {
|
|
Icon(
|
|
painter = painterResource(id = R.drawable.ic_icon_location),
|
|
contentDescription = null
|
|
)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|