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.

499 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.LocalContext
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.BodyS
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 {
BodyS {
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 context = LocalContext.current as ApplyActActivity
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(context.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
)
}
}
}
}