Merge branch 'refs/heads/dev_robotaxi-d_240729_6.6.0' into dev_robotaxi-d_240807_6.6.0
@@ -11,4 +11,14 @@ public class WriteOffPassenger implements Serializable {
|
||||
public String orderNo;
|
||||
public int passengerSize;
|
||||
public long writeOffTime;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WriteOffPassenger{" +
|
||||
"phone='" + phone + '\'' +
|
||||
", orderNo='" + orderNo + '\'' +
|
||||
", passengerSize=" + passengerSize +
|
||||
", writeOffTime=" + writeOffTime +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ import com.mogo.och.bus.util.BusTrajectoryManager;
|
||||
import com.mogo.och.bus.util.BusVoiceManager;
|
||||
import com.mogo.och.common.module.manager.autopilot.autopilot.OchAutoPilotManager;
|
||||
import com.mogo.och.common.module.manager.autopilot.line.LineManager;
|
||||
import com.mogo.och.common.module.manager.socket.cloud.IOchOnMessageListener;
|
||||
import com.mogo.och.common.module.manager.socket.lan.ILanMessageListener;
|
||||
import com.mogo.och.common.module.manager.socket.lan.LanSocketManager;
|
||||
import com.mogo.och.common.module.manager.socket.lan.bean.AppConnectMsg;
|
||||
@@ -278,8 +279,8 @@ public class OrderModel {
|
||||
GsonUtils.toJson(data));
|
||||
}
|
||||
|
||||
private final IMogoOnMessageListener<OCHOperationalMessage> mMogoOnMessageListener =
|
||||
new IMogoOnMessageListener<OCHOperationalMessage>() {
|
||||
private final IOchOnMessageListener<OCHOperationalMessage> mMogoOnMessageListener =
|
||||
new IOchOnMessageListener<OCHOperationalMessage>() {
|
||||
@Override
|
||||
public Class<OCHOperationalMessage> target() {
|
||||
return OCHOperationalMessage.class;
|
||||
@@ -297,8 +298,8 @@ public class OrderModel {
|
||||
}
|
||||
};
|
||||
|
||||
private final IMogoOnMessageListener<WriteOffPassenger> mWriteOffPassengerOnMessageListener =
|
||||
new IMogoOnMessageListener<WriteOffPassenger>() {
|
||||
private final IOchOnMessageListener<WriteOffPassenger> mWriteOffPassengerOnMessageListener =
|
||||
new IOchOnMessageListener<WriteOffPassenger>() {
|
||||
@Override
|
||||
public Class<WriteOffPassenger> target() {
|
||||
return WriteOffPassenger.class;
|
||||
|
||||
@@ -52,6 +52,7 @@ import com.mogo.och.common.module.manager.device.LightAirconditionDoorStatusMana
|
||||
import com.mogo.och.common.module.manager.logchainanalytic.OchChainLogManager
|
||||
import com.mogo.och.common.module.manager.socket.cloud.AbnormalFactorsLoopManager.startLoopAbnormalFactors
|
||||
import com.mogo.och.common.module.manager.socket.cloud.AbnormalFactorsLoopManager.stopLoopAbnormalFactors
|
||||
import com.mogo.och.common.module.manager.socket.cloud.IOchOnMessageListener
|
||||
import com.mogo.och.common.module.manager.socket.cloud.OCHSocketMessageManager
|
||||
import com.mogo.och.common.module.manager.socket.cloud.OCHSocketMessageManager.pushAppOperationalMsgBox
|
||||
import com.mogo.och.common.module.manager.socket.cloud.OCHSocketMessageManager.registerSocketMessageListener
|
||||
@@ -251,7 +252,7 @@ class DriverM1Model {
|
||||
}
|
||||
|
||||
private val mOnSystemMessageListener =
|
||||
object : IMogoOnMessageListener<SystemMsg> {
|
||||
object : IOchOnMessageListener<SystemMsg> {
|
||||
override fun onMsgReceived(obj: SystemMsg) {
|
||||
|
||||
d(SceneConstant.M_CHARTER_D + TAG, "onMsgReceived = " + obj.context)
|
||||
@@ -273,7 +274,7 @@ class DriverM1Model {
|
||||
}
|
||||
|
||||
private val mOnDoorMessageListener =
|
||||
object : IMogoOnMessageListener<OperateDoorMsg> {
|
||||
object : IOchOnMessageListener<OperateDoorMsg> {
|
||||
override fun onMsgReceived(obj: OperateDoorMsg) {
|
||||
d(SceneConstant.M_CHARTER_D + TAG, "onMsgReceived = " + obj.message)
|
||||
val doorStatus = LightAirconditionDoorStatusManager.doorStatus
|
||||
@@ -290,7 +291,7 @@ class DriverM1Model {
|
||||
}
|
||||
|
||||
private val mOnOrderClosedMessageListener =
|
||||
object : IMogoOnMessageListener<OrderCloseMsg> {
|
||||
object : IOchOnMessageListener<OrderCloseMsg> {
|
||||
override fun onMsgReceived(obj: OrderCloseMsg) {
|
||||
//订单结束
|
||||
pushOperationalToMsgBox(DateTimeUtil.getCurrentTimeStamp(), obj.message
|
||||
@@ -304,8 +305,8 @@ class DriverM1Model {
|
||||
}
|
||||
}
|
||||
|
||||
private val mWriteOffPassengerOnMessageListener: IMogoOnMessageListener<WriteOffPassenger> =
|
||||
object : IMogoOnMessageListener<WriteOffPassenger> {
|
||||
private val mWriteOffPassengerOnMessageListener =
|
||||
object : IOchOnMessageListener<WriteOffPassenger> {
|
||||
override fun target(): Class<WriteOffPassenger> {
|
||||
return WriteOffPassenger::class.java
|
||||
}
|
||||
|
||||
@@ -8,6 +8,9 @@ import com.mogo.commons.module.intent.IMogoIntentListener
|
||||
import com.mogo.commons.module.intent.IntentManager
|
||||
import com.mogo.commons.storage.SharedPrefsMgr
|
||||
import com.mogo.eagle.core.data.BaseData
|
||||
import com.mogo.eagle.core.data.config.FunctionBuildConfig
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationGCJ02ListenerManager
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationGCJ02ListenerManager.getChassisLocationGCJ02
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant
|
||||
@@ -174,15 +177,17 @@ object LoginModel {
|
||||
LoginStatusManager.setBusinessType(data.data.businessType)
|
||||
iTaxiLoginCallback?.searchStatusSuccess()
|
||||
// 后台已登录
|
||||
if (valueOf(data.data.driverStatus) == LoginStatusEnum.Login) {
|
||||
// 业务不支持 去退出登录
|
||||
if (!LoginStatusManager.checkBusiness(data.data.businessType)) {
|
||||
LoginStatusManager.loginOut()
|
||||
return
|
||||
if(!FunctionBuildConfig.isOffLine){
|
||||
if (valueOf(data.data.driverStatus) == LoginStatusEnum.Login) {
|
||||
// 业务不支持 去退出登录
|
||||
if (!LoginStatusManager.checkBusiness(data.data.businessType)) {
|
||||
LoginStatusManager.loginOut()
|
||||
return
|
||||
}
|
||||
}
|
||||
LoginStatusManager.setLoginStatus(data.data.driverStatus)
|
||||
}
|
||||
LoginStatusManager.setOpenOrderType(data.data.servingStatus)
|
||||
LoginStatusManager.setLoginStatus(data.data.driverStatus)
|
||||
LoginStatusManager.setLoginInfo(data.data)
|
||||
d(SceneConstant.M_TAXI + TAG, "登录信息:$data")
|
||||
loginSuccess(data)
|
||||
@@ -218,6 +223,11 @@ object LoginModel {
|
||||
// 登出
|
||||
fun logout() {
|
||||
val location4Login = TaxiLogoutReqBean.Location4Login()
|
||||
if (FunctionBuildConfig.isOffLine) {
|
||||
LoginStatusManager.setLoginStatus(LoginStatusEnum.Logout)
|
||||
FunctionBuildConfig.isOffLine = false
|
||||
return
|
||||
}
|
||||
OchCommonServiceManager.logout(
|
||||
mContext!!, location4Login,
|
||||
object : OchCommonServiceCallback<BaseData> {
|
||||
@@ -271,4 +281,9 @@ object LoginModel {
|
||||
updateLoginLocalStatus(0)
|
||||
}
|
||||
|
||||
fun gotoOfflineMode() {
|
||||
FunctionBuildConfig.isOffLine = true
|
||||
LoginStatusManager.setLoginStatus(LoginStatusEnum.Login)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -127,4 +127,8 @@ class LoginPresenter(view: LoginFragment?) : Presenter<LoginFragment?>(view), IT
|
||||
this.code = null
|
||||
}
|
||||
|
||||
fun gotoOfflineMode() {
|
||||
LoginModel.gotoOfflineMode()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -35,6 +35,7 @@ import kotlinx.android.synthetic.main.biz_login_view.biz_actv_welcome_login_titl
|
||||
import kotlinx.android.synthetic.main.biz_login_view.biz_cl_driver_main
|
||||
import kotlinx.android.synthetic.main.biz_login_view.bv_switch_business
|
||||
import kotlinx.android.synthetic.main.biz_login_view.eiv_Info
|
||||
import kotlinx.android.synthetic.main.biz_login_view.iv_login_offline
|
||||
|
||||
|
||||
/**
|
||||
@@ -109,6 +110,9 @@ class LoginFragment : MvpFragment<LoginFragment?, LoginPresenter?>(), ILoginView
|
||||
biz_actv_login_get_code.onClick {
|
||||
mPresenter?.getPhoneCode(biz_ace_login_phone_value.text.toString())
|
||||
}
|
||||
iv_login_offline.setOnClickListener {
|
||||
mPresenter?.gotoOfflineMode()
|
||||
}
|
||||
|
||||
biz_ace_login_phone_value.addTextChangedListener {
|
||||
it?.let { itEditable ->
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="#000000"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M17,7h-4v1.9h4c1.71,0 3.1,1.39 3.1,3.1 0,1.43 -0.98,2.63 -2.31,2.98l1.46,1.46C20.88,15.61 22,13.95 22,12c0,-2.76 -2.24,-5 -5,-5zM16,11h-2.19l2,2L16,13zM2,4.27l3.11,3.11C3.29,8.12 2,9.91 2,12c0,2.76 2.24,5 5,5h4v-1.9L7,15.1c-1.71,0 -3.1,-1.39 -3.1,-3.1 0,-1.59 1.21,-2.9 2.76,-3.07L8.73,11L8,11v2h2.73L13,15.27L13,17h1.73l4.01,4L20,19.74 3.27,3 2,4.27z"/>
|
||||
</vector>
|
||||
@@ -159,5 +159,16 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_login_offline"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:layout_marginTop="@dimen/dp_24"
|
||||
android:layout_marginEnd="@dimen/dp_24"
|
||||
android:src="@drawable/baseline_link_off_24"
|
||||
android:padding="@dimen/dp_20"
|
||||
android:layout_width="@dimen/dp_100"
|
||||
android:layout_height="@dimen/dp_100"/>
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.mogo.och.common.module.biz.lansocket
|
||||
|
||||
import com.mogo.eagle.core.data.config.FunctionBuildConfig
|
||||
import com.mogo.och.common.module.BuildConfig
|
||||
import com.mogo.och.common.module.biz.login.ILoginCallback
|
||||
import com.mogo.och.common.module.biz.login.LoginStatusEnum
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.mogo.och.common.module.biz.login
|
||||
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.alibaba.android.arouter.launcher.ARouter
|
||||
import com.mogo.eagle.core.data.config.FunctionBuildConfig
|
||||
import com.mogo.och.common.module.constant.OchCommonConst
|
||||
import com.mogo.och.common.module.manager.loop.BizLoopManager
|
||||
import com.mogo.och.common.module.manager.loop.LoopInfo
|
||||
@@ -119,10 +120,12 @@ object LoginStatusManager : CallerBase<ILoginCallback>() {
|
||||
}
|
||||
|
||||
fun invokeLoginStatusChange(currentStatus: LoginStatusEnum) {
|
||||
if(currentStatus==LoginStatusEnum.Login){
|
||||
BizLoopManager.setLoopFunction(TAGLoopStatus, LoopInfo(60*2, ::queryLoginStatusByNet,immediately = true, scheduler = Schedulers.io()))
|
||||
}else{
|
||||
BizLoopManager.removeLoopFunction(TAGLoopStatus)
|
||||
if(!FunctionBuildConfig.isOffLine){
|
||||
if(currentStatus==LoginStatusEnum.Login){
|
||||
BizLoopManager.setLoopFunction(TAGLoopStatus, LoopInfo(60*2, ::queryLoginStatusByNet,immediately = true, scheduler = Schedulers.io()))
|
||||
}else{
|
||||
BizLoopManager.removeLoopFunction(TAGLoopStatus)
|
||||
}
|
||||
}
|
||||
M_LISTENERS.forEach {
|
||||
val listener = it.value
|
||||
|
||||
@@ -47,6 +47,10 @@ class OchCommonConst {
|
||||
const val TAXI_UNMANNED_DRIVER = "/taxiunman/taxiunmandriver"
|
||||
const val TAXI_UNMANNED_PASSENGER = "/taxiunman/taxiunmanpassenger"
|
||||
|
||||
const val OFFLINE_DRIVER = "/offline/offlinedriver"
|
||||
const val OFFLINE_PASSENGER = "/offline/offlinepassenger"
|
||||
|
||||
|
||||
const val BUSINESS_STRING = 100
|
||||
|
||||
// 自动驾驶自动规划的最大距离
|
||||
|
||||
@@ -23,6 +23,8 @@ object OchChainLogManager {
|
||||
// 音乐播放日志
|
||||
const val EVENT_KEY_INFE_WITH_MUSIC = "event_key_och_music_info"
|
||||
|
||||
const val EVENT_KEY_INFE_WITH_BUS = "event_key_och_bus_info"
|
||||
|
||||
// 需要举行观察的
|
||||
const val EVENT_KEY_INFE_ERROR = "event_key_och_error"
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.mogo.och.common.module.manager.socket.cloud;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2019-12-31
|
||||
* <p>
|
||||
* 消息回调
|
||||
*/
|
||||
public interface IOchOnMessageListener< T > {
|
||||
|
||||
Class< T > target();
|
||||
|
||||
void onMsgReceived( T obj );
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import com.mogo.eagle.core.data.msgbox.MsgBoxBean
|
||||
import com.mogo.eagle.core.data.msgbox.MsgBoxType
|
||||
import com.mogo.eagle.core.data.msgbox.OperationMsg
|
||||
import com.mogo.eagle.core.function.call.msgbox.CallerMsgBoxManager
|
||||
import com.mogo.och.common.module.manager.logchainanalytic.OchChainLogManager
|
||||
|
||||
/**
|
||||
* 统一管理业务长链消息推送
|
||||
@@ -22,9 +23,18 @@ object OCHSocketMessageManager {
|
||||
const val OPERATION_ROAD_SIDE_TYPE: Int = 1 //靠边停车通知
|
||||
|
||||
fun <T> registerSocketMessageListener(msgType:Int,
|
||||
mogoOnMessageListener :IMogoOnMessageListener<T>){
|
||||
mogoOnMessageListener :IOchOnMessageListener<T>){
|
||||
MogoAiCloudSocketManager.getInstance(AbsMogoApplication.getApp().applicationContext)
|
||||
.registerOnMessageListener(msgType,mogoOnMessageListener)
|
||||
.registerOnMessageListener(msgType,object :IMogoOnMessageListener<T>{
|
||||
override fun target(): Class<T> {
|
||||
return mogoOnMessageListener.target()
|
||||
}
|
||||
|
||||
override fun onMsgReceived(obj: T) {
|
||||
OchChainLogManager.writeChainLogLanSocket("收到服务端数据","obj:${obj}}","receive");
|
||||
mogoOnMessageListener.onMsgReceived(obj)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun releaseSocketMessageListener(msgType:Int){
|
||||
|
||||
@@ -18,8 +18,10 @@ class FRetryWithTime<T : BaseData> : Function<T, ObservableSource<T>> {
|
||||
MoGoAiCloudClient.getInstance().refreshToken()
|
||||
return Observable.error(OchCommonRetryException())
|
||||
}else if(it.code == 1003){
|
||||
if (AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)) {
|
||||
LoginStatusManager.setLoginStatus(LoginStatusEnum.Logout)
|
||||
if(!FunctionBuildConfig.isOffLine){
|
||||
if (AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)) {
|
||||
LoginStatusManager.setLoginStatus(LoginStatusEnum.Logout)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,6 +44,10 @@ public class BusRoutesResult {
|
||||
return lineId;
|
||||
}
|
||||
|
||||
public void setLineId(int lineId) {
|
||||
this.lineId = lineId;
|
||||
}
|
||||
|
||||
public int getTaskId() {
|
||||
return taskId;
|
||||
}
|
||||
@@ -52,6 +56,10 @@ public class BusRoutesResult {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public List<BusStationBean> getSites() {
|
||||
return sites;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,13 @@ project.dependencies {
|
||||
if (Boolean.valueOf(USE_MAVEN_PACKAGE)) {
|
||||
|
||||
} else {
|
||||
|
||||
if (isDriver()) {
|
||||
implementation project.project(':OCH:offline:driver')
|
||||
}else if(isPassenger){
|
||||
implementation project.project(':OCH:offline:passenger')
|
||||
}
|
||||
|
||||
if (isCurrentDriver("C1")) {
|
||||
implementation project.project(':OCH:sweeper:driver')
|
||||
} else if (isCurrentDriver("B1")) {
|
||||
|
||||
@@ -79,6 +79,13 @@ abstract class FacadeProvider : IMoGoFunctionProvider, ILoginCallback {
|
||||
}
|
||||
|
||||
private fun getFragment(): Fragment {
|
||||
if(FunctionBuildConfig.isOffLine){
|
||||
if(AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)){
|
||||
return getFragmentByServeName(OchCommonConst.OFFLINE_DRIVER)
|
||||
}else if(AppIdentityModeUtils.isPassenger(FunctionBuildConfig.appIdentityMode)){
|
||||
return getFragmentByServeName(OchCommonConst.OFFLINE_PASSENGER)
|
||||
}
|
||||
}
|
||||
if(DeviceUtils.isEB5Model()&&AppIdentityModeUtils.isCharterPassenger(FunctionBuildConfig.appIdentityMode)){
|
||||
val maxVolume = VolumeUtils.getMaxVolume(AudioManager.STREAM_MUSIC)
|
||||
val volume = VolumeUtils.getVolume(AudioManager.STREAM_MUSIC)
|
||||
|
||||
1
OCH/offline/driver/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
||||
69
OCH/offline/driver/build.gradle
Normal file
@@ -0,0 +1,69 @@
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
apply plugin: 'kotlin-kapt'
|
||||
|
||||
android {
|
||||
compileSdkVersion rootProject.ext.android.compileSdkVersion
|
||||
// buildToolsVersion rootProject.ext.android.buildToolsVersion
|
||||
defaultConfig {
|
||||
minSdkVersion rootProject.ext.android.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.android.targetSdkVersion
|
||||
versionCode Integer.valueOf(VERSION_CODE)
|
||||
versionName getValueFromRootProperties("${project.name.replace("-", "_").toUpperCase()}_VERSION")
|
||||
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
consumerProguardFiles "consumer-rules.pro"
|
||||
|
||||
kapt {
|
||||
useBuildCache = false
|
||||
arguments {
|
||||
arg("AROUTER_MODULE_NAME", "offline"+project.getName())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
debug {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: "libs", include: ["*.jar"])
|
||||
implementation rootProject.ext.dependencies.kotlinstdlib
|
||||
implementation rootProject.ext.dependencies.androidxappcompat
|
||||
implementation rootProject.ext.dependencies.arouter
|
||||
kapt rootProject.ext.dependencies.aroutercompiler
|
||||
implementation rootProject.ext.dependencies.androidxconstraintlayout
|
||||
implementation rootProject.ext.dependencies.amapnavi3dmap
|
||||
|
||||
implementation rootProject.ext.dependencies.rxjava
|
||||
implementation rootProject.ext.dependencies.rxandroid
|
||||
implementation rootProject.ext.dependencies.androidxrecyclerview
|
||||
compileOnly rootProject.ext.dependencies.recyclerviewadapterhelper
|
||||
|
||||
implementation project(":OCH:common:common")
|
||||
implementation project(":OCH:common:data")
|
||||
compileOnly project(":libraries:mogo-map")
|
||||
|
||||
}
|
||||
|
||||
apply from: new File(rootProject.rootDir, "gradle/upload.gradle").toString()
|
||||
0
OCH/offline/driver/consumer-rules.pro
Normal file
3
OCH/offline/driver/gradle.properties
Normal file
@@ -0,0 +1,3 @@
|
||||
GROUP=com.mogo.och
|
||||
POM_ARTIFACT_ID=och-bus
|
||||
VERSION_CODE=1
|
||||
21
OCH/offline/driver/proguard-rules.pro
vendored
Normal file
@@ -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
|
||||
11
OCH/offline/driver/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.mogo.och.offline">
|
||||
|
||||
<application>
|
||||
<activity android:name=".ui.BusSwitchLineActivity"
|
||||
android:theme="@style/SwitchLineDialogStyle"
|
||||
android:launchMode="singleTask"
|
||||
android:screenOrientation="landscape" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.mogo.och.offline
|
||||
|
||||
import android.content.Context
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant
|
||||
import com.mogo.och.offline.fragment.ShuttleFragment
|
||||
import com.mogo.och.common.module.constant.OchCommonConst
|
||||
import com.mogo.och.common.module.biz.provider.CommonServiceImpl
|
||||
|
||||
/**
|
||||
* 网约车小巴业务实现入口
|
||||
*
|
||||
* @author tongchenfei
|
||||
*/
|
||||
@Route(path = OchCommonConst.OFFLINE_DRIVER)
|
||||
class ShuttleDriverProvider : CommonServiceImpl() {
|
||||
|
||||
private val TAG = ShuttleDriverProvider::class.java.simpleName
|
||||
private var busFragment: ShuttleFragment?=null
|
||||
|
||||
override fun init(context: Context) {
|
||||
d(SceneConstant.M_TAXI + TAG, "init")
|
||||
}
|
||||
|
||||
override fun getFragment(): Fragment {
|
||||
if(busFragment==null){
|
||||
busFragment = ShuttleFragment()
|
||||
}
|
||||
return busFragment!!
|
||||
}
|
||||
|
||||
override fun resetFragment() {
|
||||
busFragment = null
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.mogo.och.offline.bean
|
||||
|
||||
import com.mogo.eagle.core.data.BaseData
|
||||
import com.mogo.och.data.bean.BusRoutesResult
|
||||
import com.mogo.och.data.bean.BusStationBean
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
data class BindLineListResponse(val data: List<Result>?) : BaseData(){
|
||||
|
||||
data class Result(
|
||||
var line: LineInfo?,
|
||||
var siteList: List<BusStationBean>?,//站点名称
|
||||
val contrail: Contrail?,//站点名称
|
||||
)
|
||||
|
||||
data class LineInfo(
|
||||
val lineId:Long?,
|
||||
var lineName:String?,
|
||||
)
|
||||
|
||||
data class Contrail(
|
||||
val csvFileUrl:String?,
|
||||
val csvFileMd5:String?,
|
||||
val txtFileUrl:String?,
|
||||
val txtFileMd5:String?,
|
||||
val contrailSaveTime:Long?,
|
||||
)
|
||||
companion object{
|
||||
@JvmStatic
|
||||
fun getCommonLineInfo(dataItem:Result):BusRoutesResult?{
|
||||
val result = BusRoutesResult()
|
||||
dataItem.siteList?.forEach {
|
||||
it.drivingStatus = 3
|
||||
}
|
||||
result.setSite(dataItem.siteList)
|
||||
result.csvFileUrl = dataItem.contrail?.csvFileUrl
|
||||
result.csvFileMd5 = dataItem.contrail?.csvFileMd5
|
||||
result.txtFileUrl = dataItem.contrail?.txtFileUrl
|
||||
result.txtFileMd5 = dataItem.contrail?.txtFileMd5
|
||||
result.contrailSaveTime = dataItem.contrail?.contrailSaveTime?:0
|
||||
result.name = dataItem.line?.lineName?:""
|
||||
result.lineId = dataItem.line?.lineId?.toInt()?:0
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.mogo.och.offline.callback;
|
||||
|
||||
/**
|
||||
* Created on 2021/9/8
|
||||
*
|
||||
* Model->Presenter回调:ADAS相关(自动驾驶状态回调,到达终点等等)
|
||||
*/
|
||||
public interface IBusADASStatusCallback {
|
||||
//自驾返回失败
|
||||
void onStartAdasFailure();
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.mogo.och.offline.callback;
|
||||
|
||||
import com.mogo.eagle.core.data.map.MogoLocation;
|
||||
|
||||
/**
|
||||
* Created on 2021/9/10
|
||||
*
|
||||
* Model->Presenter回调:状态控制器监听(accOn、adas ui show、voice ui show、push ui show、v2x ui show等等)
|
||||
*/
|
||||
public interface IBusControllerStatusCallback {
|
||||
// 自车定位
|
||||
void onCarLocationChanged(MogoLocation location);
|
||||
//开始开启自动驾驶
|
||||
void startOpenAutopilot();
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.mogo.och.offline.callback;
|
||||
|
||||
import com.mogo.och.offline.bean.BindLineListResponse;
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
* @date: 2022/2/9
|
||||
*/
|
||||
public interface IBusLinesCallback {
|
||||
void onBusLinesChange(BindLineListResponse lines);
|
||||
void onChangeLineIdSuccess(BindLineListResponse.Result checkLineInfo);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.mogo.och.offline.callback;
|
||||
|
||||
import com.mogo.och.data.bean.BusStationBean;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
* @date: 2021/10/22
|
||||
*/
|
||||
public interface IRefreshBusStationsCallback {
|
||||
void updateBusTaskStatus(String lineName,String lintTime,
|
||||
List<BusStationBean> stationList,
|
||||
int arrivingOrArrivedIndex,
|
||||
boolean isArrived);
|
||||
|
||||
/**
|
||||
* 结束清理一遍、选择任务后清理一遍
|
||||
*/
|
||||
void clearBusStationsMarkers();
|
||||
|
||||
void updateEmptyUi();
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.mogo.och.offline.callback;
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
* @date: 2021/10/22
|
||||
*/
|
||||
public interface ISlidePannelHideCallback {
|
||||
void hideSlidePanel();
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.mogo.och.offline.constant
|
||||
|
||||
import com.mogo.commons.debug.DebugConfig
|
||||
|
||||
/**
|
||||
* Created on 2021/12/6
|
||||
*/
|
||||
class BusConst {
|
||||
companion object {
|
||||
// OCH arouter 路由path
|
||||
const val PATH = "/driver/api"
|
||||
|
||||
// 测试用的广播
|
||||
const val BROADCAST_TEST_BUS_CONTROL_TYPE_EXTRA_KEY = "sceneType"
|
||||
// 无状态
|
||||
const val STATION_STATUS_IDLE = 0
|
||||
// 已过站(历史站)
|
||||
const val STATION_STATUS_LEAVING = 1
|
||||
// 到站(当前站)
|
||||
const val STATION_STATUS_STOPPED = 2
|
||||
// 未到站(未到站)
|
||||
const val STATION_STATUS_ARRIVING = 3
|
||||
|
||||
// 上报心跳轮询ms
|
||||
const val LOOP_PERIOD_60S = 60 * 1000L
|
||||
// 开始服务启动自动驾驶等待时间(埋点上传)
|
||||
const val LOOP_PERIOD_15S = 15 * 1000L
|
||||
const val LOOP_PERIOD_1S = 1 * 1000L
|
||||
const val LOOP_DELAY = 100L
|
||||
|
||||
// 下发给MEC轨迹信息间隔时间 10秒
|
||||
const val LOOP_PERIOD_10S = 10 * 1000L
|
||||
// 尝试下发给MEC轨迹最多10次
|
||||
const val LOOP_SEND_TRAJ_TIMES = 10
|
||||
|
||||
//起点UUID
|
||||
const val BUS_START_MAP_MAKER = "bus_start_map_maker";
|
||||
//终点UUID
|
||||
const val BUS_END_MAP_MAKER = "bus_end_map_maker";
|
||||
|
||||
|
||||
/**
|
||||
* 订单起终点Marker类型
|
||||
*/
|
||||
const val TYPE_MARKER_BUS_ORDER = "TYPE_MARKER_BUS_ORDER"
|
||||
|
||||
const val TIMER_START_AUTOPILOT_INTERVAL = 20 * 1000L
|
||||
|
||||
//围栏到站 暂定10米
|
||||
const val ARRIVE_AT_END_STATION_DISTANCE = 10
|
||||
|
||||
// 轮询
|
||||
const val LOOP_PASSENGER_5S = 5 * 1000L
|
||||
const val LOOP_PASSENGER_2S = 2 * 1000L
|
||||
const val LOOP_PASSENGER_1S = 1 * 1000L
|
||||
const val LOOP_DELAY_500 = 500L
|
||||
|
||||
const val DELAY_10S = 10 * 1000L
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,558 @@
|
||||
package com.mogo.och.offline.fragment;
|
||||
|
||||
import static com.mogo.och.offline.constant.BusConst.TIMER_START_AUTOPILOT_INTERVAL;
|
||||
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.LinearInterpolator;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.constraintlayout.widget.Group;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.mogo.commons.AbsMogoApplication;
|
||||
import com.mogo.commons.mvp.IView;
|
||||
import com.mogo.commons.mvp.MvpFragment;
|
||||
import com.mogo.commons.mvp.Presenter;
|
||||
import com.mogo.eagle.core.data.config.FunctionBuildConfig;
|
||||
import com.mogo.eagle.core.data.config.HdMapBuildConfig;
|
||||
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener;
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotControlManager;
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager;
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotRecordListenerManager;
|
||||
import com.mogo.eagle.core.function.call.devatools.CallerDevaToolsManager;
|
||||
import com.mogo.eagle.core.function.call.map.CallerMapUIServiceManager;
|
||||
import com.mogo.eagle.core.function.hmi.ui.msgbox.DriverMsgBoxBubbleView;
|
||||
import com.mogo.eagle.core.function.hmi.ui.msgbox.DriverMsgBoxButtonView;
|
||||
import com.mogo.eagle.core.function.hmi.ui.msgbox.DriverMsgBoxListView;
|
||||
import com.mogo.eagle.core.function.smp.view.SmallMapView;
|
||||
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils;
|
||||
import com.mogo.eagle.core.utilcode.mogo.view.OnPreventFastClickListener;
|
||||
import com.mogo.eagle.core.utilcode.util.UiThreadHandler;
|
||||
import com.mogo.map.MogoMap;
|
||||
import com.mogo.map.uicontroller.IMogoMapUIController;
|
||||
import com.mogo.och.common.module.utils.ResourcesUtils;
|
||||
import com.mogo.och.offline.R;
|
||||
import com.mogo.och.offline.model.OrderModel;
|
||||
import com.mogo.och.offline.view.BizMapView;
|
||||
import com.mogo.och.data.bean.BusRoutesResult;
|
||||
import com.mogo.och.offline.view.SlidePanelView;
|
||||
import com.mogo.och.common.module.utils.SoundPoolHelper;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
/**
|
||||
* 网约车基础Fragment,主要负责布局通用界面,处理站点面板和通话面板互斥情况
|
||||
* <p>
|
||||
* 部分业务放在了此处处理
|
||||
*
|
||||
* @author tongchenfei
|
||||
*/
|
||||
public abstract class BaseShuttleTabFragment<V extends IView, P extends Presenter<V>> extends MvpFragment<V, P> {
|
||||
|
||||
private static final String TAG = "BaseBusTabFragment";
|
||||
|
||||
protected SlidePanelView slidePanelView;
|
||||
private RelativeLayout ctvAutopilotStatus;
|
||||
private ImageView ctvAutopilotStatusIv;
|
||||
private TextView ctvAutopilotStatusTv;
|
||||
protected TextView tvArrived;
|
||||
private FrameLayout flStationPanelContainer;
|
||||
private BizMapView mapBizView;
|
||||
private Group groupTestPanel;
|
||||
|
||||
protected SmallMapView smallMapView;
|
||||
|
||||
//消息盒子
|
||||
private DriverMsgBoxButtonView viewDriverMsgBoxButton;
|
||||
private DriverMsgBoxListView viewDriverMsgBoxList;
|
||||
private DriverMsgBoxBubbleView viewDriverMsgBoxBubble;
|
||||
|
||||
private ObjectAnimator autopilotLoadingAnimator;
|
||||
|
||||
public boolean isAnimateRunning = false;
|
||||
|
||||
/**
|
||||
* 滑动按钮触发的事件
|
||||
*/
|
||||
private final SlidePanelView.OnSlidePanelMoveToEndListener onSlideToEndListener = () -> {
|
||||
// 此处做一个代理,处理一下共有情况
|
||||
if (getSlidePanelOnEndListener() != null) {
|
||||
getSlidePanelOnEndListener().moveToEnd();
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.offline_base_fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initViews() {
|
||||
mapBizView = findViewById(R.id.mapBizView);
|
||||
groupTestPanel = findViewById(R.id.groupTestPanel);
|
||||
slidePanelView = findViewById(R.id.module_mogo_och_slide_panel);
|
||||
ctvAutopilotStatus = findViewById(R.id.module_mogo_och_autopilot_status);
|
||||
ctvAutopilotStatusIv = findViewById(R.id.bus_autopilot_btn_iv);
|
||||
ctvAutopilotStatusTv = findViewById(R.id.bus_autopolot_btn_tv);
|
||||
flStationPanelContainer = findViewById(R.id.module_mogo_och_station_panel_container);
|
||||
|
||||
tvArrived = findViewById(R.id.module_mogo_och_arrived_tv);
|
||||
|
||||
FrameLayout flSpeed = findViewById(R.id.fl_speed);
|
||||
if (flSpeed != null) {
|
||||
CallerDevaToolsManager.INSTANCE.attachAutopilotBeforeLaunchView(flSpeed.getContext(), flSpeed);
|
||||
}
|
||||
|
||||
LayoutInflater.from(getContext()).inflate(getStationPanelViewId(), flStationPanelContainer);
|
||||
slidePanelView.setOnSlidePanelMoveToEndListener(onSlideToEndListener);
|
||||
|
||||
updateSwitchMapIcon();
|
||||
|
||||
initListener();
|
||||
setAutopilotBtnStatus(CallerAutoPilotStatusListenerManager.INSTANCE.getState(),
|
||||
CallerAutoPilotControlManager.INSTANCE.isCanStartAutopilot(false, 0));
|
||||
ctvAutopilotStatus.setOnClickListener(new OnPreventFastClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClickImpl(View v) {
|
||||
restartAutopilot();
|
||||
}
|
||||
});
|
||||
|
||||
// 模拟 不可自动驾驶,目前场景是刚开机,adas还未和工控机连接
|
||||
findViewById(R.id.btnAutopilotDisable).setOnClickListener(view ->
|
||||
debugAutoPilotStatus(IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE)
|
||||
);
|
||||
|
||||
// 模拟 可自动驾驶,工控机连接正常,且处于人工干预状态
|
||||
findViewById(R.id.btnAutopilotEnable).setOnClickListener(view ->
|
||||
debugAutoPilotStatus(IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE)
|
||||
);
|
||||
|
||||
// 模拟 自动驾驶能力,自动驾驶中,可能是停车,可能是行进,但是是机器在处理车的前进后退,不是人
|
||||
findViewById(R.id.btnAutopilotRunning).setOnClickListener(view ->
|
||||
debugAutoPilotStatus(IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING)
|
||||
);
|
||||
|
||||
findViewById(R.id.btnAutopilotPingxing).setOnClickListener(view ->
|
||||
debugAutoPilotStatus(IMoGoAutopilotStatusListener.STATUS_PARALLEL_DRIVING)
|
||||
);
|
||||
|
||||
// 模拟 自动驾驶网约车回调数据
|
||||
findViewById(R.id.btnAutopilotArrive).setOnClickListener(view ->
|
||||
debugArrivedStation()
|
||||
);
|
||||
|
||||
tvArrived.setOnClickListener(view -> {
|
||||
onArriveStation();
|
||||
});
|
||||
|
||||
//消息盒子
|
||||
viewDriverMsgBoxButton = findViewById(R.id.viewDriverMsgBoxButton);
|
||||
viewDriverMsgBoxList = findViewById(R.id.viewDriverMsgBoxList);
|
||||
viewDriverMsgBoxBubble = findViewById(R.id.viewDriverMsgBoxBubble);
|
||||
viewDriverMsgBoxButton.setClickListener(show -> {
|
||||
if(show){
|
||||
viewDriverMsgBoxList.setVisibility(View.VISIBLE);
|
||||
viewDriverMsgBoxList.notifyData();
|
||||
viewDriverMsgBoxBubble.setVisibility(View.GONE);
|
||||
viewDriverMsgBoxBubble.isShowData(false);
|
||||
}else{
|
||||
viewDriverMsgBoxList.setVisibility(View.GONE);
|
||||
viewDriverMsgBoxBubble.setVisibility(View.VISIBLE);
|
||||
viewDriverMsgBoxBubble.isShowData(true);
|
||||
}
|
||||
});
|
||||
|
||||
smallMapView = findViewById(R.id.smallMapView);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initViews(Bundle savedInstanceState) {
|
||||
super.initViews(savedInstanceState);
|
||||
mapBizView.onCreate(savedInstanceState);
|
||||
smallMapView.onCreateView(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
mapBizView.onResume();
|
||||
smallMapView.onResume();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container
|
||||
, @Nullable Bundle savedInstanceState) {
|
||||
EventBus.getDefault().register(this);
|
||||
return super.onCreateView(inflater, container, savedInstanceState);
|
||||
}
|
||||
|
||||
protected abstract void onArriveStation();
|
||||
|
||||
private void updateSwitchMapIcon() {
|
||||
|
||||
IMogoMapUIController mapUIController = CallerMapUIServiceManager.INSTANCE.getMapUIController(MogoMap.DEFAULT);
|
||||
if(mapUIController!=null){
|
||||
if (AppIdentityModeUtils.isB2(FunctionBuildConfig.appIdentityMode)) {
|
||||
mapUIController.changeCurrentIcon(R.raw.m2);
|
||||
HdMapBuildConfig.currentCarVrIconRes = R.raw.m2;
|
||||
}else if (AppIdentityModeUtils.isB1(FunctionBuildConfig.appIdentityMode)) {
|
||||
mapUIController.changeCurrentIcon(R.raw.xiaoba);
|
||||
HdMapBuildConfig.currentCarVrIconRes = R.raw.xiaoba;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(@NonNull Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapBizView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapBizView.onLowMemory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
mapBizView.onPause();
|
||||
smallMapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
mapBizView.onDestroy();
|
||||
if(smallMapView != null){
|
||||
smallMapView.onDestroy();
|
||||
}
|
||||
super.onDestroyView();
|
||||
CallerAutopilotRecordListenerManager.INSTANCE.removeListener(TAG);
|
||||
EventBus.getDefault().unregister(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试到站
|
||||
*/
|
||||
protected abstract void debugArrivedStation();
|
||||
|
||||
private void initListener() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 展示滑动按钮
|
||||
*
|
||||
* @param text 指定的文字
|
||||
*/
|
||||
public void showSlidePanel(String text) {
|
||||
UiThreadHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
slidePanelView.setText(text);
|
||||
slidePanelView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}, UiThreadHandler.MODE.QUEUE);
|
||||
setArrivedClikable(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置进站按钮状态
|
||||
*
|
||||
* @param isClickable
|
||||
*/
|
||||
public void setArrivedClikable(boolean isClickable) {
|
||||
UiThreadHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
tvArrived.setEnabled(isClickable);
|
||||
if (isClickable) {
|
||||
tvArrived.setTextColor(ContextCompat.getColor(AbsMogoApplication.getApp(),R.color.bus_white));
|
||||
} else {
|
||||
tvArrived.setTextColor(ContextCompat.getColor(AbsMogoApplication.getApp(),R.color.bus_arrived_btn_un_clickable_color));
|
||||
}
|
||||
}
|
||||
}, UiThreadHandler.MODE.QUEUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 隐藏滑动按钮
|
||||
*/
|
||||
public void hideSlidePanel() {
|
||||
UiThreadHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
slidePanelView.setVisibility(View.GONE);
|
||||
}
|
||||
}, UiThreadHandler.MODE.QUEUE);
|
||||
}
|
||||
|
||||
public void playDI() {
|
||||
SoundPoolHelper.getSoundPoolHelper().playSoundWithRedId(getContext(), R.raw.bus_di);
|
||||
}
|
||||
|
||||
/**
|
||||
* 改变自动驾驶状态
|
||||
*
|
||||
* @param autopilotStatus 0:不可用 1:可用状态 2:自动驾驶中
|
||||
*/
|
||||
public void onAutopilotStatusChanged(int autopilotStatus,boolean canStartAuto) {
|
||||
UiThreadHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
changeAutopilotBtnView(autopilotStatus, isAnimateRunning,canStartAuto);
|
||||
}
|
||||
}, UiThreadHandler.MODE.QUEUE);
|
||||
}
|
||||
|
||||
public void setAutopilotBtnStatus(int autopilotStatus,boolean canStartAuto) {
|
||||
if (IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE == autopilotStatus) {//0不可用
|
||||
ctvAutopilotStatusTv.setTextColor(ResourcesUtils.getColor(R.color.bus_autopilot_text_color_disable));
|
||||
ctvAutopilotStatusTv.setText(ResourcesUtils.getString(R.string.bus_loading_autopilot_runnig_tv));
|
||||
ctvAutopilotStatusIv.setImageResource(R.drawable.bus_disable_autopilot_icon);
|
||||
ctvAutopilotStatus.setClickable(true);
|
||||
ctvAutopilotStatus.setBackgroundResource(R.drawable.common_autopilot_start_fail);
|
||||
} else {
|
||||
ctvAutopilotStatusTv.setTextColor(AbsMogoApplication.getApp().getColor(R.color.bus_autopilot_text_color_normal));
|
||||
ctvAutopilotStatusIv.setImageResource(R.drawable.bus_ic_autopilot);
|
||||
if (IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE == autopilotStatus) { //1可用
|
||||
ctvAutopilotStatusTv.setText(ResourcesUtils.getString(R.string.bus_loading_autopilot_runnig_tv));
|
||||
if(canStartAuto){
|
||||
ctvAutopilotStatus.setClickable(true);
|
||||
ctvAutopilotStatus.setBackgroundResource(R.drawable.common_autopilot_press);
|
||||
}else {
|
||||
ctvAutopilotStatusTv.setTextColor(ResourcesUtils.getColor(R.color.bus_autopilot_text_color_disable));
|
||||
ctvAutopilotStatusIv.setImageResource(R.drawable.bus_disable_autopilot_icon);
|
||||
ctvAutopilotStatus.setClickable(true);
|
||||
ctvAutopilotStatus.setBackgroundResource(R.drawable.common_autopilot_start_fail);
|
||||
}
|
||||
} else if (IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING == autopilotStatus) {
|
||||
ctvAutopilotStatusTv.setText(R.string.bus_loading_autopilot_runnig_tv);
|
||||
ctvAutopilotStatus.setClickable(true);
|
||||
ctvAutopilotStatus.setBackgroundResource(R.drawable.common_autopilot_in_autopilot);
|
||||
} else if (IMoGoAutopilotStatusListener.STATUS_PARALLEL_DRIVING
|
||||
== autopilotStatus){
|
||||
ctvAutopilotStatusTv.setText(R.string.bus_pingxing_driver);
|
||||
ctvAutopilotStatus.setClickable(false);
|
||||
ctvAutopilotStatus.setBackgroundResource(R.drawable.common_autopilot_pxjs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void updateAutopilotStatus(int autopilotStatus) {
|
||||
if (IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING
|
||||
== autopilotStatus) {//2 running
|
||||
ctvAutopilotStatusIv.setImageResource(R.drawable.bus_right_autopilot_icon);
|
||||
ctvAutopilotStatusTv.setTextColor(ResourcesUtils.getColor(R.color.bus_autopilot_text_color_normal));
|
||||
ctvAutopilotStatusTv.setText(ResourcesUtils.getString(R.string.bus_loading_autopilot_success_tv));
|
||||
// ctvAutopilotStatus.setSelected(false);
|
||||
ctvAutopilotStatus.setClickable(false);
|
||||
} else {
|
||||
ctvAutopilotStatusIv.setImageResource(R.drawable.bus_wrong_autopilot_icon);
|
||||
ctvAutopilotStatusTv.setTextColor(ResourcesUtils.getColor(R.color.bus_autopilot_text_color_normal));
|
||||
ctvAutopilotStatusTv.setText(ResourcesUtils.getString(R.string.bus_loading_autopilot_failure_tv));
|
||||
ctvAutopilotStatus.setClickable(false);
|
||||
// ctvAutopilotStatus.setSelected(false);
|
||||
}
|
||||
UiThreadHandler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
setAutopilotBtnStatus(autopilotStatus,CallerAutoPilotControlManager.INSTANCE.isCanStartAutopilot(false, 0));
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
private void changeAutopilotBtnView(int autopilotStatus, boolean isAnimateRunning,boolean canStartAuto) {
|
||||
if (isAnimateRunning && IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING
|
||||
!= autopilotStatus) {
|
||||
// 主动开启自动驾驶中,不为2(为0、1)则继续loading
|
||||
return;
|
||||
}
|
||||
if (isAnimateRunning) {
|
||||
stopAnimAndUpdateBtnStatus();
|
||||
} else {
|
||||
setAutopilotBtnStatus(autopilotStatus,canStartAuto);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void stopAnimAndUpdateBtnStatus() {
|
||||
stopAutopilotAnimation();
|
||||
updateAutopilotStatus(CallerAutoPilotStatusListenerManager.INSTANCE.getState());
|
||||
}
|
||||
|
||||
/**
|
||||
* 隐藏【自动驾驶】按钮
|
||||
*/
|
||||
public void hideAutopilotBiz() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 展示【自动驾驶】按钮
|
||||
*/
|
||||
public void showAutopilotBiz() {
|
||||
}
|
||||
|
||||
public SlidePanelView.OnSlidePanelMoveToEndListener getSlidePanelOnEndListener() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取站点面板view,在{@link #initViews()}时候添加到container中
|
||||
*
|
||||
* @return 站点面板view
|
||||
*/
|
||||
public abstract int getStationPanelViewId();
|
||||
|
||||
/**
|
||||
* 重新开启自动驾驶
|
||||
*/
|
||||
public abstract void restartAutopilot();
|
||||
|
||||
/**
|
||||
* 模拟自动驾驶返回状态
|
||||
*
|
||||
* @param status
|
||||
*/
|
||||
public abstract void debugAutoPilotStatus(int status);
|
||||
|
||||
/**
|
||||
* 开启自动驾驶中间动画
|
||||
*/
|
||||
public void startAutopilotAnimation() {
|
||||
isAnimateRunning = true;
|
||||
ctvAutopilotStatusTv.setText(ResourcesUtils.getString(R.string.bus_loading_autopilot_tv));
|
||||
ctvAutopilotStatusTv.setTextColor(ResourcesUtils.getColor(R.color.bus_autopilot_text_color_normal));
|
||||
ctvAutopilotStatus.setClickable(true);
|
||||
ctvAutopilotStatusIv.setImageResource(R.drawable.bus_loading_autopilot_icon);
|
||||
if (autopilotLoadingAnimator == null) {
|
||||
autopilotLoadingAnimator = ObjectAnimator.ofFloat(ctvAutopilotStatusIv, "rotation", 0f, 360f);
|
||||
autopilotLoadingAnimator.setInterpolator(new LinearInterpolator());
|
||||
autopilotLoadingAnimator.setRepeatCount(-1);//无限循环
|
||||
autopilotLoadingAnimator.setDuration(1000);//设置持续时间
|
||||
}
|
||||
autopilotLoadingAnimator.start();//动画开始
|
||||
|
||||
startingAutoApilotCountDown();
|
||||
|
||||
}
|
||||
|
||||
private void startingAutoApilotCountDown() {
|
||||
//10s 若自动驾驶没有开启,则结束动画
|
||||
UiThreadHandler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() { //未启动成功做处理
|
||||
if (isAnimateRunning) {// 只判断动画是否在进行,根据自动驾驶当前状态去设置自动驾驶状态
|
||||
stopAutopilotAnimation();
|
||||
updateAutopilotStatus(CallerAutoPilotStatusListenerManager.INSTANCE.getState());
|
||||
}
|
||||
}
|
||||
}, TIMER_START_AUTOPILOT_INTERVAL);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止自动驾驶中间动画
|
||||
*/
|
||||
protected void stopAutopilotAnimation() {
|
||||
if (autopilotLoadingAnimator != null) {
|
||||
autopilotLoadingAnimator.end();
|
||||
ctvAutopilotStatusIv.clearAnimation();
|
||||
autopilotLoadingAnimator = null;
|
||||
isAnimateRunning = false;
|
||||
}
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 迈速表实时更新
|
||||
// *
|
||||
// * @param newSpeed
|
||||
// */
|
||||
// public void updateSpeedView(float newSpeed) {
|
||||
// int speed = (int) (Math.abs(newSpeed) * 3.6F); // 倒车时工控机反馈定位信息中speed为负值
|
||||
// if (mTrafficDataView != null) {
|
||||
// mTrafficDataView.updateSpeedWithValue(speed);
|
||||
// }
|
||||
// }
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* bus调试面板打开关闭
|
||||
*/
|
||||
public void debugTestBar() {
|
||||
if (groupTestPanel.getVisibility() == View.VISIBLE) {
|
||||
groupTestPanel.setVisibility(View.GONE);
|
||||
} else {
|
||||
groupTestPanel.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Bus调试信息:线路、轨迹等信息
|
||||
* <p>
|
||||
* START
|
||||
*/
|
||||
private View busTestBar;
|
||||
private TextView lineIdTV;
|
||||
private TextView lineNameTV;
|
||||
private TextView trajMd5TV;
|
||||
private TextView stopMd5TV;
|
||||
private TextView trajMd5DPQPTV;
|
||||
private TextView stopMd5DPQPTV;
|
||||
|
||||
public void showHideTestBar() {
|
||||
if (busTestBar == null) {
|
||||
busTestBar = findViewById(R.id.module_mogo_och_bus_test_bar);
|
||||
lineIdTV = findViewById(R.id.bus_test_bar_current_line_id);
|
||||
lineNameTV = findViewById(R.id.bus_test_bar_current_line_name);
|
||||
trajMd5TV = findViewById(R.id.bus_test_bar_current_traj_md5);
|
||||
stopMd5TV = findViewById(R.id.bus_test_bar_current_stop_md5);
|
||||
trajMd5DPQPTV = findViewById(R.id.bus_test_bar_current_traj_md5_dpqp);
|
||||
stopMd5DPQPTV = findViewById(R.id.bus_test_bar_current_stop_md5_dpqp);
|
||||
}
|
||||
|
||||
if (busTestBar.getVisibility() == View.VISIBLE) {
|
||||
busTestBar.setVisibility(View.GONE);
|
||||
} else {
|
||||
BusRoutesResult routesResult = OrderModel.getInstance().getBusRoutesResult();
|
||||
lineIdTV.setText("lineId:" + (routesResult == null ? "" : String.valueOf(routesResult.getLineId())));
|
||||
lineNameTV.setText("lineName:" + (routesResult == null ? "" : routesResult.getName()));
|
||||
trajMd5TV.setText("TMd5:" + (routesResult == null ? "" : routesResult.csvFileMd5));
|
||||
stopMd5TV.setText("SMd5:" + (routesResult == null ? "" : routesResult.txtFileMd5));
|
||||
trajMd5DPQPTV.setText("TMd5DPQP:" + (routesResult == null ? "" : routesResult.csvFileMd5DPQP));
|
||||
stopMd5DPQPTV.setText("SMd5DPQP:" + (routesResult == null ? "" : routesResult.txtFileMd5DPQP));
|
||||
busTestBar.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateBusTestBarInfo() {
|
||||
if (busTestBar != null && busTestBar.getVisibility() == View.VISIBLE) {
|
||||
BusRoutesResult routesResult = OrderModel.getInstance().getBusRoutesResult();
|
||||
lineIdTV.setText("lineId:" + (routesResult == null ? "" : String.valueOf(routesResult.getLineId())));
|
||||
lineNameTV.setText("lineName:" + (routesResult == null ? "" : routesResult.getName()));
|
||||
trajMd5TV.setText("TMd5:" + (routesResult == null ? "" : routesResult.csvFileMd5));
|
||||
stopMd5TV.setText("SMd5:" + (routesResult == null ? "" : routesResult.txtFileMd5));
|
||||
trajMd5DPQPTV.setText("TMd5DPQP:" + (routesResult == null ? "" : routesResult.csvFileMd5DPQP));
|
||||
stopMd5DPQPTV.setText("SMd5DPQP:" + (routesResult == null ? "" : routesResult.txtFileMd5DPQP));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* END
|
||||
*/
|
||||
}
|
||||
@@ -0,0 +1,551 @@
|
||||
package com.mogo.och.offline.fragment;
|
||||
|
||||
import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS;
|
||||
import static com.mogo.map.MogoMap.DEFAULT;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
import androidx.constraintlayout.widget.Group;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.mogo.commons.storage.SharedPrefsMgr;
|
||||
import com.mogo.eagle.core.data.config.FunctionBuildConfig;
|
||||
import com.mogo.eagle.core.data.temp.EventLogout;
|
||||
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener;
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager;
|
||||
import com.mogo.eagle.core.function.call.map.CallerMapUIServiceManager;
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant;
|
||||
import com.mogo.eagle.core.utilcode.util.ActivityUtils;
|
||||
import com.mogo.eagle.core.utilcode.util.ToastUtils;
|
||||
import com.mogo.eagle.core.utilcode.util.UiThreadHandler;
|
||||
import com.mogo.map.overlay.IMoGoOverlayManager;
|
||||
import com.mogo.map.overlay.core.Level;
|
||||
import com.mogo.map.overlay.point.Point;
|
||||
import com.mogo.och.common.module.utils.ResourcesUtils;
|
||||
import com.mogo.och.offline.R;
|
||||
import com.mogo.och.offline.presenter.BusPresenter;
|
||||
import com.mogo.och.offline.ui.BusStationCommonItem;
|
||||
import com.mogo.och.offline.ui.BusSwitchLineActivity;
|
||||
import com.mogo.och.data.bean.BusStationBean;
|
||||
import com.mogo.och.offline.constant.BusConst;
|
||||
import com.mogo.och.offline.view.SlidePanelView;
|
||||
import com.mogo.och.common.module.utils.BlinkAnimationUtil;
|
||||
import com.mogo.och.common.module.utils.OCHThreadPoolManager;
|
||||
import com.mogo.och.common.module.utils.QRUtilsKt;
|
||||
import com.mogo.och.common.module.wigets.BindQRCodeDialog;
|
||||
import com.mogo.och.common.module.wigets.MarqueeTextView;
|
||||
import com.mogo.och.common.module.wigets.OCHCommitDialog;
|
||||
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import me.jessyan.autosize.utils.AutoSizeUtils;
|
||||
|
||||
|
||||
/**
|
||||
* 网约车小巴界面
|
||||
*
|
||||
* @author tongchenfei
|
||||
*/
|
||||
public class ShuttleFragment extends BaseShuttleTabFragment<ShuttleFragment, BusPresenter>
|
||||
implements SlidePanelView.OnSlidePanelMoveToEndListener, View.OnClickListener {
|
||||
public static final String TAG = "BusFragment";
|
||||
|
||||
private TextView mSwitchLine; //切换路线
|
||||
private MarqueeTextView mLineName;
|
||||
private TextView mTaskTime;
|
||||
private Group groupStationsPanel;
|
||||
private ConstraintLayout noDataView;
|
||||
|
||||
private BusStationBean startStation = null;
|
||||
private BusStationBean endStation = null;
|
||||
private BusStationCommonItem firstStationItem;
|
||||
private BusStationCommonItem secondStationItem;
|
||||
private BusStationCommonItem thirdStationItem;
|
||||
|
||||
|
||||
@Override
|
||||
public String getTagName() {
|
||||
return "BusFragment";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
}
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
if (mPresenter != null) {
|
||||
mPresenter.onDestroy(this);
|
||||
}
|
||||
IMoGoOverlayManager overlayManager = CallerMapUIServiceManager.INSTANCE.getOverlayManager();
|
||||
if(overlayManager!=null) {
|
||||
overlayManager.removeAllLines();
|
||||
overlayManager.removeAllPoints();
|
||||
}
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initViews() {
|
||||
super.initViews();
|
||||
|
||||
mSwitchLine = findViewById(R.id.switch_line_btn);
|
||||
mSwitchLine.setTag(0);
|
||||
mLineName = findViewById(R.id.module_och_bus_line_name);
|
||||
|
||||
firstStationItem = findViewById(R.id.bus_panel_first_station);
|
||||
secondStationItem = findViewById(R.id.bus_panel_second_station);
|
||||
thirdStationItem = findViewById(R.id.bus_panel_third_station);
|
||||
mTaskTime = findViewById(R.id.bus_task_time_tv);
|
||||
groupStationsPanel = findViewById(R.id.group_stations_panel);
|
||||
noDataView = findViewById(R.id.no_line_data_view);
|
||||
|
||||
CallerLogger.d(M_BUS + TAG, "initView: " + CallerAutoPilotStatusListenerManager.INSTANCE.getState());
|
||||
// 初始化的时候设置 UI 按钮状态
|
||||
showAutopilotBiz();
|
||||
|
||||
mSwitchLine.setOnClickListener(this);
|
||||
|
||||
mLineName.setOnLongClickListener(new View.OnLongClickListener() {
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
showHideTestBar();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void changeOverview(EventLogout eventLogout){
|
||||
if (eventLogout.getMessgae() == EventLogout.LOGOUT_TYPE){
|
||||
CallerLogger.d(M_BUS + TAG,"changeOverview Event消息去登出");
|
||||
mPresenter.logout();
|
||||
}else if (eventLogout.getMessgae() == EventLogout.SHOW_QR_TYPE){ //显示二维码
|
||||
CallerLogger.d(M_BUS + TAG,"changeOverview Event qrcode,sn = "
|
||||
+ SharedPrefsMgr.getInstance().getSn());
|
||||
String qrUrl = String.format(FunctionBuildConfig.urlJson.getBindDriverQRUrl(),
|
||||
SharedPrefsMgr.getInstance().getSn());
|
||||
Bitmap bmQr = QRUtilsKt.createQRCodeWithPicture(
|
||||
BitmapFactory.decodeResource(getResources(), R.drawable.icon_qr_center_logo)
|
||||
,qrUrl, AutoSizeUtils.dp2px(getContext(),340f),
|
||||
AutoSizeUtils.dp2px(getContext(),340f),true);
|
||||
if (bmQr != null){
|
||||
BindQRCodeDialog.Builder builder = new BindQRCodeDialog.Builder();
|
||||
builder.title(getString(R.string.bind_driver_qr_title))
|
||||
.cancelStr(getString(R.string.qr_cancel))
|
||||
.qrBm(bmQr).build(getContext()).show();
|
||||
}else {
|
||||
CallerLogger.d(M_BUS + TAG,"bmQr = null ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onArriveStation() {
|
||||
mPresenter.onAutopilotArriveAtStation(null);
|
||||
mPresenter.arriveStation(null,"点击进站触发进站操作");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void debugArrivedStation() {
|
||||
mPresenter.onAutopilotArriveAtStation(null);
|
||||
mPresenter.arriveStation(null,"点击debug进站按钮触发进站操作");
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected BusPresenter createPresenter() {
|
||||
return new BusPresenter(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
public void hideStationsPanel(){
|
||||
groupStationsPanel.setVisibility(View.GONE);
|
||||
noDataView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
public void showStationsPanel(){
|
||||
groupStationsPanel.setVisibility(View.VISIBLE);
|
||||
noDataView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
public void updateLineEmptyUI(){
|
||||
setArrivedClikable(false);
|
||||
showOrHideSwitchLineBtn(true);
|
||||
hideStationsPanel();
|
||||
hideSlidePanel();
|
||||
resetStationBlinkAnim();
|
||||
}
|
||||
|
||||
private void resetStationBlinkAnim() {
|
||||
BlinkAnimationUtil.clearAnimation(firstStationItem.getCircleImageView());
|
||||
BlinkAnimationUtil.clearAnimation(secondStationItem.getCircleImageView());
|
||||
BlinkAnimationUtil.clearAnimation(thirdStationItem.getCircleImageView());
|
||||
}
|
||||
|
||||
public void updateBusTaskStatus(String lineName, String lineTime,
|
||||
List<BusStationBean> stationList,
|
||||
int arrivingOrArrivedIndex,
|
||||
boolean isArrived){
|
||||
|
||||
if (getActivity() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
UiThreadHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (stationList == null) {
|
||||
// 获取小巴数据失败
|
||||
return;
|
||||
}
|
||||
|
||||
showStationsPanel();
|
||||
showOrHideSwitchLineBtn(false);
|
||||
|
||||
mLineName.setText(lineName);
|
||||
mTaskTime.setText(getString(R.string.bus_line_time_tag)+ lineTime);
|
||||
// 渲染小巴路线数据
|
||||
updateBusStationStatus(stationList,arrivingOrArrivedIndex,isArrived);
|
||||
}
|
||||
},UiThreadHandler.MODE.QUEUE);
|
||||
}
|
||||
|
||||
private void updateBusStationStatus(List<BusStationBean> stationList,
|
||||
int arrivingOrArrivedIndex,
|
||||
boolean isArrived) {
|
||||
|
||||
startStation = stationList.get(0);
|
||||
endStation = stationList.get(stationList.size() - 1);
|
||||
|
||||
if (arrivingOrArrivedIndex == stationList.size() - 1 && isArrived){
|
||||
//切换路线和结束路线按钮切换
|
||||
showSlidePanel("单程结束");
|
||||
|
||||
setOrRemoveMapMaker(false, BusConst.BUS_END_MAP_MAKER, endStation.getLat()
|
||||
, endStation.getLon(),R.raw.end_marker);
|
||||
}else if (arrivingOrArrivedIndex == 0 && isArrived){
|
||||
|
||||
showSlidePanel("滑动出发");
|
||||
|
||||
setOrRemoveMapMaker(true, BusConst.BUS_START_MAP_MAKER,
|
||||
startStation.getLat(), startStation.getLon(),R.raw.star_marker);
|
||||
setOrRemoveMapMaker(true, BusConst.BUS_END_MAP_MAKER,
|
||||
endStation.getLat(), endStation.getLon(),R.raw.end_marker);
|
||||
}else{
|
||||
if (isArrived){
|
||||
// 重置滑动按钮文字
|
||||
showSlidePanel("滑动出发");
|
||||
}
|
||||
|
||||
setOrRemoveMapMaker(false, BusConst.BUS_START_MAP_MAKER, startStation.getLat()
|
||||
, startStation.getLon(),R.raw.star_marker);
|
||||
setOrRemoveMapMaker(true, BusConst.BUS_END_MAP_MAKER, endStation.getLat()
|
||||
, endStation.getLon(),R.raw.end_marker);
|
||||
}
|
||||
|
||||
if (stationList.size() > 2){ //只有两个站点
|
||||
updateMoreThanTwoStationsUI(stationList,arrivingOrArrivedIndex,isArrived);
|
||||
}else {
|
||||
updateTwoStationsUI(stationList,arrivingOrArrivedIndex,isArrived);
|
||||
}
|
||||
|
||||
updateBusTestBarInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* 有两个以上站点的路线
|
||||
* @param stationList
|
||||
* @param arrivingOrArrivedIndex
|
||||
* @param isArrived
|
||||
*/
|
||||
private void updateMoreThanTwoStationsUI(List<BusStationBean> stationList,
|
||||
int arrivingOrArrivedIndex,
|
||||
boolean isArrived) {
|
||||
secondStationItem.setStationTag("");
|
||||
secondStationItem.showOrHideStationArrowBg(true);
|
||||
thirdStationItem.setStationTag("");
|
||||
secondStationItem.setVisibility(View.VISIBLE);
|
||||
thirdStationItem.showOrHideStationArrowBg(false);
|
||||
|
||||
if (arrivingOrArrivedIndex == 0 || arrivingOrArrivedIndex -1 == 0
|
||||
|| (arrivingOrArrivedIndex -2 == 0 && stationList.size() == 3)){
|
||||
firstStationItem.setStationTag(ResourcesUtils.getString(R.string.bus_station_txt_tag_start));
|
||||
}else {
|
||||
firstStationItem.setStationTag("");
|
||||
}
|
||||
|
||||
if (arrivingOrArrivedIndex + 1 == stationList.size() - 1 || arrivingOrArrivedIndex == stationList.size() - 1
|
||||
|| (arrivingOrArrivedIndex == 0 && arrivingOrArrivedIndex + 2 == stationList.size() - 1)){ //确认是否显示 "终"
|
||||
thirdStationItem.setStationTag(ResourcesUtils.getString(R.string.bus_station_txt_tag_end));
|
||||
}else {
|
||||
thirdStationItem.setStationTag("");
|
||||
}
|
||||
|
||||
//圆点: 0:灰色 过站 1:绿色 到站或者即将到站 2:蓝色:未到站
|
||||
if (arrivingOrArrivedIndex == 0 && isArrived){
|
||||
firstStationItem.setStationNameColor(ResourcesUtils.getColor(R.color.bus_line_station_color_selected));
|
||||
secondStationItem.setStationNameColor(ResourcesUtils.getColor(R.color.bus_arrived_station_name_text_color));
|
||||
thirdStationItem.setStationNameColor(ResourcesUtils.getColor(R.color.bus_arrived_station_name_text_color));
|
||||
|
||||
firstStationItem.setStationName(stationList.get(0).getName());
|
||||
secondStationItem.setStationName(stationList.get(1).getName());
|
||||
thirdStationItem.setStationName(stationList.get(2).getName());
|
||||
|
||||
firstStationItem.setStationPointBg(1);
|
||||
secondStationItem.setStationPointBg(2);
|
||||
thirdStationItem.setStationPointBg(2);
|
||||
|
||||
firstStationItem.setStationArrowBg(2);
|
||||
secondStationItem.setStationArrowBg(2);
|
||||
|
||||
}else if (arrivingOrArrivedIndex == stationList.size() - 1){
|
||||
firstStationItem.setStationNameColor(ResourcesUtils.getColor(R.color.bus_station_tag_txt_un_color));
|
||||
secondStationItem.setStationNameColor(ResourcesUtils.getColor(R.color.bus_station_tag_txt_un_color));
|
||||
thirdStationItem.setStationNameColor(ResourcesUtils.getColor(R.color.bus_line_station_color_selected));
|
||||
|
||||
firstStationItem.setStationName(stationList.get(arrivingOrArrivedIndex -2).getName());
|
||||
secondStationItem.setStationName(stationList.get(arrivingOrArrivedIndex -1).getName());
|
||||
thirdStationItem.setStationName(stationList.get(arrivingOrArrivedIndex).getName());
|
||||
|
||||
firstStationItem.setStationPointBg(0);
|
||||
secondStationItem.setStationPointBg(0);
|
||||
thirdStationItem.setStationPointBg(1);
|
||||
|
||||
firstStationItem.setStationArrowBg(0);
|
||||
if (isArrived){
|
||||
secondStationItem.setStationArrowBg(0);
|
||||
}else {
|
||||
secondStationItem.setStationArrowBg(1);
|
||||
}
|
||||
|
||||
}else {
|
||||
firstStationItem.setStationNameColor(ResourcesUtils.getColor(R.color.bus_station_tag_txt_un_color));
|
||||
secondStationItem.setStationNameColor(ResourcesUtils.getColor(R.color.bus_line_station_color_selected));
|
||||
thirdStationItem.setStationNameColor(ResourcesUtils.getColor(R.color.bus_arrived_station_name_text_color));
|
||||
|
||||
firstStationItem.setStationName(stationList.get(arrivingOrArrivedIndex -1).getName());
|
||||
secondStationItem.setStationName(stationList.get(arrivingOrArrivedIndex).getName());
|
||||
thirdStationItem.setStationName(stationList.get(arrivingOrArrivedIndex + 1).getName());
|
||||
|
||||
firstStationItem.setStationPointBg(0);
|
||||
secondStationItem.setStationPointBg(1);
|
||||
thirdStationItem.setStationPointBg(2);
|
||||
|
||||
secondStationItem.setStationArrowBg(2);
|
||||
if (isArrived){
|
||||
firstStationItem.setStationArrowBg(0);
|
||||
}else {
|
||||
firstStationItem.setStationArrowBg(1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 只有两个站点的路线
|
||||
* @param stationList
|
||||
* @param arrivingOrArrivedIndex
|
||||
* @param isArrived
|
||||
*/
|
||||
private void updateTwoStationsUI(List<BusStationBean> stationList,
|
||||
int arrivingOrArrivedIndex,
|
||||
boolean isArrived) {
|
||||
|
||||
secondStationItem.setVisibility(View.GONE);
|
||||
secondStationItem.showOrHideStationArrowBg(false);
|
||||
thirdStationItem.showOrHideStationArrowBg(false);
|
||||
|
||||
firstStationItem.setStationTag(ResourcesUtils.getString(R.string.bus_station_txt_tag_start));
|
||||
thirdStationItem.setStationTag(ResourcesUtils.getString(R.string.bus_station_txt_tag_end));
|
||||
|
||||
firstStationItem.setStationName(stationList.get(0).getName());
|
||||
thirdStationItem.setStationName(stationList.get(1).getName());
|
||||
|
||||
//圆点: 0:灰色 过站 1:绿色 到站或者即将到站 2:蓝色:未到站
|
||||
if (arrivingOrArrivedIndex == 0 && isArrived){//到站
|
||||
firstStationItem.setStationNameColor(ResourcesUtils.getColor(R.color.bus_line_station_color_selected));
|
||||
thirdStationItem.setStationNameColor(ResourcesUtils.getColor(R.color.bus_arrived_station_name_text_color));
|
||||
firstStationItem.setStationPointBg(1);
|
||||
firstStationItem.setStationArrowBg(2);
|
||||
thirdStationItem.setStationPointBg(0);
|
||||
|
||||
}else {
|
||||
firstStationItem.setStationNameColor(ResourcesUtils.getColor(R.color.bus_station_tag_txt_un_color));
|
||||
thirdStationItem.setStationNameColor(ResourcesUtils.getColor(R.color.bus_line_station_color_selected));
|
||||
if (isArrived){ //到终点
|
||||
firstStationItem.setStationPointBg(0);
|
||||
firstStationItem.setStationArrowBg(0);
|
||||
thirdStationItem.setStationPointBg(1);
|
||||
|
||||
}else { //到终点途中
|
||||
firstStationItem.setStationPointBg(0);
|
||||
firstStationItem.setStationArrowBg(1);
|
||||
thirdStationItem.setStationPointBg(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void showOrHideSwitchLineBtn(boolean isShow) {
|
||||
if (isShow){//显示切换路线
|
||||
mSwitchLine.setTag(0);
|
||||
mSwitchLine.setText(ResourcesUtils.getString(R.string.bus_switch_line_btn));
|
||||
}else {//显示结束路线
|
||||
mSwitchLine.setTag(1);
|
||||
mSwitchLine.setText(ResourcesUtils.getString(R.string.bus_close_line_btn));
|
||||
}
|
||||
}
|
||||
|
||||
public void hideOchBus() {
|
||||
// tvNotice.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStationPanelViewId() {
|
||||
return R.layout.offline_fragment_och;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restartAutopilot() {
|
||||
if (!isAnimateRunning) {
|
||||
mPresenter.restartAutopilot();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SlidePanelView.OnSlidePanelMoveToEndListener getSlidePanelOnEndListener() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveToEnd() {
|
||||
// 开启自动驾驶到下一站
|
||||
if (isAnimateRunning){
|
||||
stopAutopilotAnimation();
|
||||
}
|
||||
mPresenter.autoDriveToNextStation();
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置自动驾驶可用状态
|
||||
*/
|
||||
public void onAutopilotEnableChange(boolean isEnable) {
|
||||
if (isEnable) {
|
||||
showAutopilotBiz();
|
||||
} else {
|
||||
hideAutopilotBiz();
|
||||
}
|
||||
}
|
||||
|
||||
public void clearBusStationsMarkers(){
|
||||
CallerLogger.d(M_BUS + TAG,"clearBusStationsMarkers()");
|
||||
if (null != startStation) {
|
||||
setOrRemoveMapMaker(false, BusConst.BUS_START_MAP_MAKER, startStation.getLat()
|
||||
, startStation.getLon(),R.raw.star_marker);
|
||||
}
|
||||
if (null != endStation) {
|
||||
setOrRemoveMapMaker(false, BusConst.BUS_END_MAP_MAKER, endStation.getLat()
|
||||
, endStation.getLon(),R.raw.end_marker);
|
||||
}
|
||||
|
||||
//清除鹰眼右下角小地图轨迹
|
||||
CallerLogger.d(SceneConstant.M_BUS, "clearBusStationsMarkers --------->");
|
||||
smallMapView.clearPolyline();
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制地图起点终点
|
||||
*
|
||||
* @param isAdd
|
||||
* @param uuid
|
||||
*/
|
||||
private void setOrRemoveMapMaker(boolean isAdd, String uuid, double lat, double longi,int resourceId) {
|
||||
if (isAdd) {
|
||||
Runnable setMapMarkerRunnable = () -> {
|
||||
CallerLogger.d(M_BUS + "setMapMaker= "+Thread.currentThread().getName(),
|
||||
uuid + "=latitude=" + lat + ",longitude=" + longi);
|
||||
|
||||
Point.Options.Builder builder = new Point.Options.Builder(BusConst.TYPE_MARKER_BUS_ORDER, Level.MAP_MARKER)
|
||||
.setId(uuid)
|
||||
.anchor(0.5f, 0.5f)
|
||||
.set3DMode(true)
|
||||
.isUseGps(true)
|
||||
.controlAngle(false)
|
||||
.icon3DRes(resourceId)
|
||||
.latitude(lat)
|
||||
.longitude(longi);
|
||||
IMoGoOverlayManager overlayManager = CallerMapUIServiceManager.INSTANCE.getOverlayManager();
|
||||
if (overlayManager != null) {
|
||||
overlayManager.showOrUpdatePoint(builder.build(),DEFAULT);
|
||||
}
|
||||
};
|
||||
|
||||
OCHThreadPoolManager.getsInstance().execute(setMapMarkerRunnable);
|
||||
|
||||
}else {
|
||||
Runnable removeMapMarkerRunnable = () -> {
|
||||
CallerLogger.d(M_BUS + "RemoveMapMaker="+Thread.currentThread().getName(),
|
||||
uuid+"=latitude="+lat+",longitude="+longi);
|
||||
Objects.requireNonNull(CallerMapUIServiceManager.INSTANCE.getOverlayManager()).removePoint(uuid);
|
||||
};
|
||||
OCHThreadPoolManager.getsInstance().execute(removeMapMarkerRunnable);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debugAutoPilotStatus(int status) {
|
||||
mPresenter.debugAutoPilotStatus(status);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (v.getId() == R.id.switch_line_btn) {//切换路线条件: 自动驾驶过程中,点击则toast提示:自动驾驶中,不可切换路线
|
||||
//本次行程未结束,不支持切换路线。点击则toast提示:当前行程未完成,不可切换路线
|
||||
if (CallerAutoPilotStatusListenerManager.INSTANCE.getState()
|
||||
== IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING) {
|
||||
ToastUtils.showLong(ResourcesUtils.getString(R.string.bus_switch_line_btn_warning1));
|
||||
return;
|
||||
}
|
||||
if ((int)mSwitchLine.getTag() == 0){//切换路线
|
||||
Intent intent = new Intent(getContext(), BusSwitchLineActivity.class);
|
||||
ActivityUtils.startActivity(intent);
|
||||
}else {//结束任务
|
||||
OCHCommitDialog.Builder builder = new OCHCommitDialog.Builder();
|
||||
OCHCommitDialog closeLineConfirmDialog = builder
|
||||
.title(getString(R.string.bus_dialog_title))
|
||||
.tips(getString(R.string.bus_dialog_tips))
|
||||
.confirmStr(getString(R.string.bus_dialog_confirm))
|
||||
.cancelStr(getString(R.string.bus_dialog_cancel))
|
||||
.build(getContext());
|
||||
closeLineConfirmDialog.setClickListener(new OCHCommitDialog.ClickListener() {
|
||||
@Override
|
||||
public void confirm() {
|
||||
mPresenter.abortTask();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
closeLineConfirmDialog.dismiss();
|
||||
}
|
||||
});
|
||||
closeLineConfirmDialog.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
package com.mogo.och.offline.model
|
||||
|
||||
import com.mogo.commons.storage.SharedPrefsMgr
|
||||
import com.mogo.eagle.core.utilcode.util.GsonUtils
|
||||
import com.mogo.och.common.module.manager.loop.BizLoopManager
|
||||
import com.mogo.och.common.module.manager.loop.LoopInfo
|
||||
import com.mogo.och.common.module.network.OchCommonServiceCallback
|
||||
import com.mogo.och.offline.bean.BindLineListResponse
|
||||
import com.mogo.och.offline.callback.IBusLinesCallback
|
||||
import com.mogo.och.offline.net.OrderServiceManager
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
* @date: 2022/2/9
|
||||
*/
|
||||
object BusLineModel {
|
||||
private var mBusLinesCallback: IBusLinesCallback? = null
|
||||
|
||||
private const val Catche4AllLines = "Catche4AllLines"
|
||||
private const val TAG = "BusLineModel"
|
||||
|
||||
private var lastAllLinesJson = ""
|
||||
|
||||
@JvmStatic
|
||||
fun setBusLinesCallback(callback: IBusLinesCallback?) {
|
||||
mBusLinesCallback = callback
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun queryBusLines() {
|
||||
val catche4AllLines = SharedPrefsMgr.getInstance().getString(Catche4AllLines)
|
||||
val bindLineListResponse =
|
||||
GsonUtils.fromJson(catche4AllLines, BindLineListResponse::class.java)
|
||||
if (bindLineListResponse != null && mBusLinesCallback != null) {
|
||||
mBusLinesCallback!!.onBusLinesChange(bindLineListResponse)
|
||||
}
|
||||
lastAllLinesJson = catche4AllLines
|
||||
OrderServiceManager.queryBindLineListBySn(object : OchCommonServiceCallback<BindLineListResponse> {
|
||||
override fun onSuccess(data: BindLineListResponse) {
|
||||
if (null == data && mBusLinesCallback != null) {
|
||||
mBusLinesCallback?.onBusLinesChange(null)
|
||||
return
|
||||
}
|
||||
mBusLinesCallback?.onBusLinesChange(data)
|
||||
val toJson = GsonUtils.toJson(data)
|
||||
if(lastAllLinesJson==toJson){
|
||||
return
|
||||
}else{
|
||||
lastAllLinesJson = toJson
|
||||
SharedPrefsMgr.getInstance().putString(Catche4AllLines, toJson)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onError() {
|
||||
}
|
||||
|
||||
override fun onFail(code: Int, failMsg: String) {
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
@JvmStatic
|
||||
fun queryBusLinesByIo() {
|
||||
OrderServiceManager.queryBindLineListBySn(object : OchCommonServiceCallback<BindLineListResponse> {
|
||||
override fun onSuccess(data: BindLineListResponse) {
|
||||
if (null == data) {
|
||||
return
|
||||
}
|
||||
|
||||
val toJson = GsonUtils.toJson(data)
|
||||
if(lastAllLinesJson==toJson){
|
||||
return
|
||||
}else{
|
||||
lastAllLinesJson = toJson
|
||||
SharedPrefsMgr.getInstance().putString(Catche4AllLines, toJson)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onError() {
|
||||
}
|
||||
|
||||
override fun onFail(code: Int, failMsg: String) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@JvmStatic
|
||||
fun commitSwitchLineId(checkLineInfo: BindLineListResponse.Result?) {
|
||||
if (mBusLinesCallback != null) {
|
||||
mBusLinesCallback!!.onChangeLineIdSuccess(checkLineInfo)
|
||||
}
|
||||
}
|
||||
@JvmStatic
|
||||
fun startLoopAllLine() {
|
||||
BizLoopManager.setLoopFunction(TAG, LoopInfo(60,::queryBusLinesByIo, scheduler = Schedulers.io()))
|
||||
}
|
||||
@JvmStatic
|
||||
fun stopLoopAllLine() {
|
||||
BizLoopManager.removeLoopFunction(TAG)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.mogo.och.offline.net;
|
||||
import com.mogo.och.offline.bean.BindLineListResponse;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import retrofit2.http.GET;
|
||||
import retrofit2.http.Header;
|
||||
import retrofit2.http.Query;
|
||||
|
||||
/**
|
||||
* 小巴车相关接口
|
||||
*
|
||||
* @author tongchenfei
|
||||
* <p>
|
||||
* wiki: http://wiki.zhidaohulian.com/pages/viewpage.action?pageId=48970072
|
||||
*/
|
||||
public interface IBascApiService {
|
||||
|
||||
/**
|
||||
* 查询车辆配置的所有路线
|
||||
* @param appId
|
||||
* @param ticket
|
||||
* @param sn
|
||||
* @return
|
||||
*/
|
||||
@GET("/och-vehicle/public/car/queryBindLineListBySn")
|
||||
Observable<BindLineListResponse> queryBindLineListBySn(@Header ("appId") String appId, @Header("ticket") String ticket, @Query("sn") String sn);
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.mogo.och.offline.net
|
||||
|
||||
import com.mogo.cloud.passport.MoGoAiCloudClientConfig
|
||||
import com.mogo.commons.AbsMogoApplication
|
||||
import com.mogo.eagle.core.network.MoGoRetrofitFactory
|
||||
import com.mogo.commons.storage.SharedPrefsMgr
|
||||
import com.mogo.och.common.module.constant.OchCommonConst
|
||||
import com.mogo.och.common.module.network.OchCommonServiceCallback
|
||||
import com.mogo.och.common.module.network.OchCommonSubscribeImpl
|
||||
import com.mogo.och.common.module.network.interceptor.transformIoTry
|
||||
import com.mogo.och.offline.bean.BindLineListResponse
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
* @date: 2021/10/20
|
||||
*/
|
||||
object OrderServiceManager {
|
||||
|
||||
private val mService: IBascApiService = MoGoRetrofitFactory.getInstance(OchCommonConst.getShuttleUrl()).create(
|
||||
IBascApiService::class.java
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
fun queryBindLineListBySn(
|
||||
callback: OchCommonServiceCallback<BindLineListResponse>?
|
||||
) {
|
||||
mService.queryBindLineListBySn(
|
||||
MoGoAiCloudClientConfig.getInstance().serviceAppId,
|
||||
SharedPrefsMgr.getInstance().token,
|
||||
SharedPrefsMgr.getInstance().sn
|
||||
)
|
||||
.transformIoTry()
|
||||
.subscribe(OchCommonSubscribeImpl(AbsMogoApplication.getApp(), callback, "queryBindLineListBySn"))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package com.mogo.och.offline.presenter;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
|
||||
import com.mogo.commons.mvp.Presenter;
|
||||
import com.mogo.eagle.core.utilcode.util.UiThreadHandler;
|
||||
import com.mogo.och.offline.bean.BindLineListResponse;
|
||||
import com.mogo.och.offline.ui.BusSwitchLineView;
|
||||
import com.mogo.och.offline.callback.IBusLinesCallback;
|
||||
import com.mogo.och.offline.model.BusLineModel;
|
||||
import com.mogo.och.offline.model.OrderModel;
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
* @date: 2022/2/9
|
||||
*/
|
||||
public class BusLinePresenter extends Presenter<BusSwitchLineView> implements IBusLinesCallback {
|
||||
|
||||
public BusLinePresenter(BusSwitchLineView view) {
|
||||
super(view);
|
||||
OrderModel.getInstance().init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@NonNull LifecycleOwner owner) {
|
||||
super.onCreate(owner);
|
||||
initListener();
|
||||
}
|
||||
|
||||
private void initListener() {
|
||||
BusLineModel.setBusLinesCallback(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBusLinesChange(BindLineListResponse lines) {
|
||||
UiThreadHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if(mView!=null) {
|
||||
mView.onBusLinesChange(lines);
|
||||
}
|
||||
}
|
||||
}, UiThreadHandler.MODE.QUEUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeLineIdSuccess(BindLineListResponse.Result checkLineInfo) {
|
||||
OrderModel.getInstance().pushCacheTransferData(BindLineListResponse.getCommonLineInfo(checkLineInfo));
|
||||
OrderModel.getInstance().clearBusStationDatas();
|
||||
UiThreadHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if(mView!=null) {
|
||||
mView.onChangeLineIdSuccess();
|
||||
}
|
||||
}
|
||||
}, UiThreadHandler.MODE.QUEUE);
|
||||
}
|
||||
|
||||
public void queryBusLines(){
|
||||
BusLineModel.queryBusLines();
|
||||
}
|
||||
|
||||
public void commitSwitchLineId(BindLineListResponse.Result checkLineInfo){
|
||||
BusLineModel.commitSwitchLineId(checkLineInfo);
|
||||
}
|
||||
|
||||
public void removeListener(){
|
||||
BusLineModel.setBusLinesCallback(null);
|
||||
}
|
||||
|
||||
public void queryBusRoutes(){
|
||||
OrderModel.getInstance().queryBusRoutes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy(@NonNull LifecycleOwner owner) {
|
||||
super.onDestroy(owner);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,328 @@
|
||||
package com.mogo.och.offline.presenter;
|
||||
|
||||
import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS;
|
||||
|
||||
import android.os.Looper;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
|
||||
import com.mogo.commons.AbsMogoApplication;
|
||||
import com.mogo.commons.mvp.Presenter;
|
||||
import com.mogo.eagle.core.data.config.FunctionBuildConfig;
|
||||
import com.mogo.eagle.core.data.map.MogoLocation;
|
||||
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener;
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotControlManager;
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager;
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
|
||||
import com.mogo.eagle.core.utilcode.util.UiThreadHandler;
|
||||
import com.mogo.och.common.module.biz.login.LoginStatusEnum;
|
||||
import com.mogo.och.common.module.manager.autopilot.autopilot.ArrivedStation;
|
||||
import com.mogo.och.common.module.manager.autopilot.autopilot.IOchAutopilotStatusListener;
|
||||
import com.mogo.och.common.module.manager.autopilot.autopilot.OchAutoPilotStatusListenerManager;
|
||||
import com.mogo.och.data.bean.BusStationBean;
|
||||
import com.mogo.och.offline.callback.IBusADASStatusCallback;
|
||||
import com.mogo.och.offline.callback.IBusControllerStatusCallback;
|
||||
import com.mogo.och.offline.callback.IRefreshBusStationsCallback;
|
||||
import com.mogo.och.offline.callback.ISlidePannelHideCallback;
|
||||
import com.mogo.och.offline.fragment.ShuttleFragment;
|
||||
import com.mogo.och.offline.model.BusLineModel;
|
||||
import com.mogo.och.offline.model.OrderModel;
|
||||
import com.mogo.och.offline.util.BusTrajectoryManager;
|
||||
import com.mogo.och.common.module.biz.login.ILoginCallback;
|
||||
import com.mogo.och.common.module.biz.login.LoginStatusManager;
|
||||
import com.mogo.och.common.module.manager.autopilot.OCHAdasAbilityManager;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import mogo_msg.MogoReportMsg;
|
||||
|
||||
/**
|
||||
* 网约车小巴
|
||||
*
|
||||
* @author tongchenfei
|
||||
*/
|
||||
public class BusPresenter extends Presenter<ShuttleFragment>
|
||||
implements IRefreshBusStationsCallback, ISlidePannelHideCallback
|
||||
, IOchAutopilotStatusListener, IBusControllerStatusCallback, ILoginCallback, IBusADASStatusCallback {
|
||||
|
||||
private static final String TAG = "BusPresenter";
|
||||
|
||||
private final List<BusStationBean> mStationList = new ArrayList<>();
|
||||
private int mCurrentStation = 0;
|
||||
|
||||
public BusPresenter(ShuttleFragment view) {
|
||||
super(view);
|
||||
//2021.11.1 鹰眼架构整合,由IMoGoAutopilotStatusListener逐步替代IMogoAdasOCHCallback接口
|
||||
OrderModel.getInstance().init();
|
||||
OCHAdasAbilityManager.getInstance().init(AbsMogoApplication.getApp());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@NonNull LifecycleOwner owner) {
|
||||
super.onCreate(owner);
|
||||
initModelListener();
|
||||
|
||||
OrderModel.getInstance().queryBusCacheRoutes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy(@NonNull LifecycleOwner owner) {
|
||||
super.onDestroy(owner);
|
||||
OrderModel.getInstance().release();
|
||||
releaseListener();
|
||||
}
|
||||
|
||||
public void initModelListener() {
|
||||
OrderModel.getInstance().setRefreshBusStationsCallback(this);
|
||||
OrderModel.getInstance().setSlidePanelHideCallback(this);
|
||||
OrderModel.getInstance().setControllerStatusCallback(this);
|
||||
OrderModel.getInstance().setAdasStatusCallback(this);
|
||||
OchAutoPilotStatusListenerManager.INSTANCE.addListener(TAG,this);
|
||||
LoginStatusManager.INSTANCE.addListener(TAG,this);
|
||||
}
|
||||
|
||||
public void releaseListener() {
|
||||
OrderModel.getInstance().setRefreshBusStationsCallback(null);
|
||||
OrderModel.getInstance().setSlidePanelHideCallback(null);
|
||||
OrderModel.getInstance().setControllerStatusCallback(null);
|
||||
OrderModel.getInstance().setAdasStatusCallback(null);
|
||||
OCHAdasAbilityManager.getInstance().release();
|
||||
OchAutoPilotStatusListenerManager.INSTANCE.removeListener(TAG);
|
||||
LoginStatusManager.INSTANCE.removeListener(TAG);
|
||||
}
|
||||
|
||||
public void abortTask() {
|
||||
OrderModel.getInstance().abortTask();
|
||||
}
|
||||
|
||||
public void autoDriveToNextStation() {
|
||||
OrderModel.getInstance().autoDriveToNextStation();
|
||||
}
|
||||
|
||||
public void restartAutopilot() {
|
||||
if (OrderModel.getInstance().isGoingToNextStation()){
|
||||
OrderModel.getInstance().restartAutopilot();
|
||||
}
|
||||
}
|
||||
|
||||
// 登出
|
||||
public void logout() {
|
||||
OrderModel.getInstance().logout();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBusTaskStatus(String lineName,String lineTime,
|
||||
List<BusStationBean> stationList,
|
||||
int arrivingOrArrivedIndex,
|
||||
boolean isArrived) {
|
||||
mStationList.clear();
|
||||
mStationList.addAll(stationList);
|
||||
if (arrivingOrArrivedIndex == 0 || isArrived){
|
||||
mCurrentStation = arrivingOrArrivedIndex;
|
||||
}else {
|
||||
mCurrentStation = arrivingOrArrivedIndex -1;
|
||||
}
|
||||
CallerLogger.d(M_BUS + "BusOrderModel =", " mCurrentStation =" + mCurrentStation);
|
||||
|
||||
UiThreadHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if(mView!=null) {
|
||||
mView.updateBusTaskStatus(lineName,lineTime,
|
||||
stationList, arrivingOrArrivedIndex, isArrived);
|
||||
}
|
||||
}
|
||||
}, UiThreadHandler.MODE.QUEUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateEmptyUi() {
|
||||
UiThreadHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if(mView!=null) {
|
||||
mView.updateLineEmptyUI();
|
||||
}
|
||||
}
|
||||
}, UiThreadHandler.MODE.QUEUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearBusStationsMarkers() {
|
||||
UiThreadHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if(mView!=null) {
|
||||
mView.clearBusStationsMarkers();
|
||||
}
|
||||
}
|
||||
}, UiThreadHandler.MODE.QUEUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideSlidePanel() {
|
||||
if (mView != null) {
|
||||
mView.hideSlidePanel();
|
||||
mView.setArrivedClikable(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAutopilotArriveAtStation(ArrivedStation arrivedStation) {
|
||||
CallerLogger.e( M_BUS + TAG, "行程日志-onAutopilotArriveAtStation arrive");
|
||||
arriveStation(arrivedStation,"底盘触发进站");
|
||||
}
|
||||
|
||||
public void arriveStation(ArrivedStation arrivedStation,String type){
|
||||
OrderModel.getInstance().onArriveAt(arrivedStation,type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAutopilotStatusResponse(int state) {
|
||||
switch (state) {
|
||||
case IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE:
|
||||
case IMoGoAutopilotStatusListener.STATUS_PARALLEL_DRIVING:
|
||||
case IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE:
|
||||
if (FunctionBuildConfig.isDemoMode
|
||||
&& (
|
||||
(mCurrentStation >= 0 && mCurrentStation <= mStationList.size() - 1)
|
||||
&& OrderModel.getInstance().isGoingToNextStation()
|
||||
)
|
||||
) {
|
||||
CallerLogger.d(M_BUS + "BusOrderModel=", "有美化功能");
|
||||
return;
|
||||
}
|
||||
// 改变UI自动驾驶状态
|
||||
UiThreadHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if(mView!=null) {
|
||||
mView.onAutopilotStatusChanged(state, CallerAutoPilotControlManager.INSTANCE.isCanStartAutopilot(false,0));
|
||||
}
|
||||
}
|
||||
}, UiThreadHandler.MODE.QUEUE);
|
||||
break;
|
||||
case IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING:
|
||||
OrderModel.getInstance().triggerStartServiceEvent(
|
||||
OrderModel.getInstance().isRestartAutopilot(), true);
|
||||
// 改变UI自动驾驶状态
|
||||
UiThreadHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if(mView!=null) {
|
||||
mView.onAutopilotStatusChanged(state, CallerAutoPilotControlManager.INSTANCE.isCanStartAutopilot(false,0));
|
||||
}
|
||||
}
|
||||
}, UiThreadHandler.MODE.QUEUE);
|
||||
break;
|
||||
default:
|
||||
UiThreadHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if(mView!=null) {
|
||||
mView.onAutopilotEnableChange(false);
|
||||
}
|
||||
}
|
||||
}, UiThreadHandler.MODE.QUEUE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCarLocationChanged(MogoLocation location) {
|
||||
// if (null != location) {
|
||||
// runOnUIThread(() -> mView.updateSpeedView(location.getGnssSpeed()));
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startOpenAutopilot() {
|
||||
//非美化模式下启动动画
|
||||
UiThreadHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if(mView!=null) {
|
||||
mView.startAutopilotAnimation();
|
||||
}
|
||||
}
|
||||
}, UiThreadHandler.MODE.QUEUE);
|
||||
|
||||
//中间站点再次开启自驾时, 自动驾驶状态是2未改变, 此次鹰眼底层不再返给业务,需优化按钮动画显示
|
||||
if (IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING
|
||||
== CallerAutoPilotStatusListenerManager.INSTANCE.getState()&&mView!=null){
|
||||
mView.onAutopilotStatusChanged(CallerAutoPilotStatusListenerManager.INSTANCE.getState(),
|
||||
CallerAutoPilotControlManager.INSTANCE.isCanStartAutopilot(false,0));
|
||||
}
|
||||
}
|
||||
|
||||
private void runOnUIThread(Runnable executor) {
|
||||
if (executor == null) {
|
||||
return;
|
||||
}
|
||||
if (Looper.myLooper() != Looper.getMainLooper()) {
|
||||
UiThreadHandler.post(executor);
|
||||
} else {
|
||||
executor.run();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试使用
|
||||
*/
|
||||
public void debugAutoPilotStatus(int status) {
|
||||
onAutopilotStatusResponse(status);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onAutopilotGuardian(MogoReportMsg.MogoReportMessage guardianInfo, long lineId) {
|
||||
BusTrajectoryManager.getInstance().onAutopilotGuardian(guardianInfo,lineId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStatusChange(LoginStatusEnum currentStatus) {
|
||||
CallerLogger.d(M_BUS + TAG, " loginStatus =" + LoginStatusManager.isLogin());
|
||||
if(LoginStatusManager.isLogin()){
|
||||
// OrderModel.getInstance().queryBusRoutes();
|
||||
OrderModel.getInstance().queryBusCacheRoutes();
|
||||
BusLineModel.startLoopAllLine();
|
||||
}else {
|
||||
BusLineModel.stopLoopAllLine();
|
||||
BusTrajectoryManager.getInstance().stopTrajReqLoop();
|
||||
BusTrajectoryManager.getInstance().stopTrajReqLoop();
|
||||
clearBusStationsMarkers();
|
||||
if(mView!=null) {
|
||||
mView.hideSlidePanel();
|
||||
}
|
||||
OrderModel.getInstance().closeBeautificationMode();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartAdasFailure() {
|
||||
UiThreadHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if(mView!=null) {
|
||||
mView.stopAnimAndUpdateBtnStatus();
|
||||
}
|
||||
}
|
||||
}, UiThreadHandler.MODE.QUEUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void canStartAutopilot(boolean canStart) {
|
||||
UiThreadHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if(mView!=null) {
|
||||
mView.onAutopilotStatusChanged(CallerAutoPilotStatusListenerManager.INSTANCE.getState(),canStart);
|
||||
}
|
||||
}
|
||||
}, UiThreadHandler.MODE.QUEUE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package com.mogo.och.offline.ui
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.mogo.och.common.module.utils.BlinkAnimationUtil
|
||||
import com.mogo.och.offline.R
|
||||
import kotlinx.android.synthetic.main.offline_stations_common_item.view.*
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
* @date: 2022/9/15
|
||||
*/
|
||||
class BusStationCommonItem @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0
|
||||
) : LinearLayout(context, attrs, defStyleAttr){
|
||||
|
||||
init {
|
||||
LayoutInflater.from(context).inflate(R.layout.offline_stations_common_item,this,true)
|
||||
}
|
||||
|
||||
fun setStationName(name: String){
|
||||
busStationNameTv.text = name
|
||||
}
|
||||
|
||||
fun setStationNameColor(color: Int){
|
||||
busStationNameTv.setTextColor(color)
|
||||
}
|
||||
|
||||
fun setStationPointBg(type: Int) { // 0:灰色 过站 1:绿色 到站或者即将到站 2:蓝色:未到站
|
||||
BlinkAnimationUtil.clearAnimation(busCircleIv)
|
||||
when (type) {
|
||||
0 -> {
|
||||
busCircleIvBg.visibility = GONE
|
||||
busCircleIv.setImageDrawable(
|
||||
ContextCompat.getDrawable(
|
||||
context,
|
||||
R.drawable.icon_point_grey_bus
|
||||
)
|
||||
)
|
||||
}
|
||||
1 -> {
|
||||
busCircleIvBg.visibility = VISIBLE
|
||||
busCircleIv.setImageDrawable(
|
||||
ContextCompat.getDrawable(
|
||||
context,
|
||||
R.drawable.icon_point_green_bus
|
||||
)
|
||||
)
|
||||
BlinkAnimationUtil.setAnimation(busCircleIv)
|
||||
}
|
||||
2 -> {
|
||||
busCircleIvBg.visibility = GONE
|
||||
busCircleIv.setImageDrawable(
|
||||
ContextCompat.getDrawable(
|
||||
context,
|
||||
R.drawable.icon_point_blue_bus
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fun getCircleImageView() : ImageView{
|
||||
return busCircleIv
|
||||
}
|
||||
|
||||
fun setStationArrowBg(type: Int){// 0:灰色 过站 1:绿色 前往下一站 2:蓝色 未到站
|
||||
when(type){
|
||||
0 -> busArrowBg.setImageResource(R.drawable.icon_arrow_grey_bus)
|
||||
1 -> busArrowBg.setImageResource(R.drawable.icon_arrow_green_bus)
|
||||
2 -> busArrowBg.setImageResource(R.drawable.icon_arrow_blue_bus)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun setStationTag(tag: String){ // 0:起 1:终
|
||||
if (tag.isNullOrEmpty()){
|
||||
busTagTxt.visibility = GONE
|
||||
}else{
|
||||
busTagTxt.text = tag
|
||||
busTagTxt.visibility = VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
fun showOrHideStationArrowBg(isShow:Boolean){
|
||||
if (isShow){
|
||||
busArrowBg.visibility = VISIBLE
|
||||
}else{
|
||||
busArrowBg.visibility = GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
package com.mogo.och.offline.ui
|
||||
|
||||
import android.graphics.Point
|
||||
import android.os.Bundle
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowManager
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.mogo.commons.mvp.MvpActivity
|
||||
import com.mogo.commons.storage.SharedPrefsMgr
|
||||
import com.mogo.och.offline.presenter.BusLinePresenter
|
||||
import com.mogo.och.offline.ui.adapter.SwitchLineAdapter
|
||||
import com.mogo.och.offline.ui.adapter.OpenItemAnimator
|
||||
import com.mogo.eagle.core.utilcode.mogo.view.SpacesItemDecoration
|
||||
import com.mogo.eagle.core.utilcode.util.ToastUtils
|
||||
import com.mogo.och.offline.R
|
||||
import com.mogo.och.offline.bean.BindLineListResponse
|
||||
import java.util.ArrayList
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
* @date: 2022/2/8
|
||||
*/
|
||||
class BusSwitchLineActivity : MvpActivity<BusSwitchLineView?, BusLinePresenter?>(),
|
||||
View.OnClickListener, BusSwitchLineView {
|
||||
|
||||
companion object{
|
||||
const val LASTCOMMITLINEID = "lastcommitlineid"
|
||||
}
|
||||
|
||||
private lateinit var mClose: ImageView
|
||||
private lateinit var mNoDatasView: ConstraintLayout
|
||||
private lateinit var mLinesListView: RecyclerView
|
||||
private lateinit var mLineCommitBtn: TextView
|
||||
private lateinit var mAdapter: SwitchLineAdapter
|
||||
private lateinit var linearLayoutManager:LinearLayoutManager
|
||||
private val mData: MutableList<BindLineListResponse.Result> = ArrayList()
|
||||
private var checkLineInfo:BindLineListResponse.Result? = null
|
||||
override fun getLayoutId(): Int {
|
||||
return R.layout.offline_switch_line
|
||||
}
|
||||
|
||||
override fun createPresenter(): BusLinePresenter {
|
||||
return BusLinePresenter(this)
|
||||
}
|
||||
|
||||
override fun initViews() {
|
||||
initWH()
|
||||
initView()
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
initDatas()
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化view
|
||||
*/
|
||||
private fun initView() {
|
||||
mClose = findViewById(R.id.switch_line_close)
|
||||
mClose.setOnClickListener(this)
|
||||
mNoDatasView = findViewById(R.id.no_order_data_view)
|
||||
mLineCommitBtn = findViewById(R.id.switch_line_btn_commit)
|
||||
mLineCommitBtn.setOnClickListener(this)
|
||||
mLinesListView = findViewById(R.id.switch_line_rv)
|
||||
linearLayoutManager = LinearLayoutManager(this)
|
||||
mLinesListView.setLayoutManager(linearLayoutManager)
|
||||
mLinesListView.setItemAnimator(OpenItemAnimator())
|
||||
mAdapter = SwitchLineAdapter(applicationContext, mData)
|
||||
mLinesListView.addItemDecoration(
|
||||
SpacesItemDecoration(
|
||||
4
|
||||
)
|
||||
)
|
||||
mLinesListView.setAdapter(mAdapter)
|
||||
//设置item 点击事件
|
||||
mAdapter.setOnLineItemClickListener(object : SwitchLineAdapter.LineItemClickListener{
|
||||
override fun onItemClick(lineInfo: BindLineListResponse.Result) {
|
||||
// 选中的线路
|
||||
checkLineInfo = lineInfo
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置布局宽高
|
||||
*/
|
||||
private fun initWH() {
|
||||
val window = window
|
||||
val params = window.attributes
|
||||
val windowManager = getSystemService(WINDOW_SERVICE) as WindowManager
|
||||
val point = Point()
|
||||
windowManager.defaultDisplay.getSize(point) //用于获取屏幕高度
|
||||
params.width = (point.x * 0.375).toInt()
|
||||
params.height = ViewGroup.LayoutParams.MATCH_PARENT
|
||||
window.attributes = params
|
||||
window.setGravity(Gravity.START or Gravity.BOTTOM)
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化数据
|
||||
*/
|
||||
private fun initDatas() {
|
||||
mPresenter?.queryBusLines()
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询返回绑定路线集合
|
||||
* @param data
|
||||
*/
|
||||
override fun onBusLinesChange(data: BindLineListResponse?) {
|
||||
if (null == data) {
|
||||
showNoData(true)
|
||||
return
|
||||
}
|
||||
if (data.data != null && data.data.size > 0) {
|
||||
showNoData(false)
|
||||
mData.clear()
|
||||
mData.addAll(data.data)
|
||||
mAdapter.notifyDataSetChanged()
|
||||
} else {
|
||||
showNoData(true)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onChangeLineIdSuccess() {
|
||||
ToastUtils.showLong(resources.getString(R.string.bus_change_line_commit_tip_s))
|
||||
mPresenter?.queryBusRoutes()
|
||||
mAdapter.setOnLineItemClickListener(null)
|
||||
mPresenter?.removeListener()
|
||||
finish()
|
||||
}
|
||||
|
||||
/**
|
||||
* 有无数据UI显示
|
||||
* @param b
|
||||
*/
|
||||
private fun showNoData(b: Boolean) {
|
||||
if (b) {
|
||||
mLinesListView.visibility = View.GONE
|
||||
mLineCommitBtn.visibility = View.GONE
|
||||
mNoDatasView.visibility = View.VISIBLE
|
||||
} else {
|
||||
mLinesListView.visibility = View.VISIBLE
|
||||
mLineCommitBtn.visibility = View.VISIBLE
|
||||
mNoDatasView.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
override fun onClick(v: View) {
|
||||
//关闭dialog
|
||||
if (v.id == R.id.switch_line_close) {
|
||||
finish()
|
||||
return
|
||||
}
|
||||
//切换路线提交
|
||||
if (v.id == R.id.switch_line_btn_commit) {
|
||||
if (checkLineInfo==null) {
|
||||
ToastUtils.showLong("请选择任务")
|
||||
}else{
|
||||
mPresenter?.commitSwitchLineId(checkLineInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
mPresenter!!.removeListener()
|
||||
super.onDestroy()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.mogo.och.offline.ui;
|
||||
|
||||
import com.mogo.commons.mvp.IView;
|
||||
import com.mogo.och.offline.bean.BindLineListResponse;
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
* @date: 2022/2/10
|
||||
*/
|
||||
public interface BusSwitchLineView extends IView {
|
||||
|
||||
void onBusLinesChange(BindLineListResponse data);
|
||||
void onChangeLineIdSuccess();
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,643 @@
|
||||
package com.mogo.och.offline.ui.adapter;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.TimeInterpolator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.view.View;
|
||||
import android.view.ViewPropertyAnimator;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.recyclerview.widget.DefaultItemAnimator;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.recyclerview.widget.SimpleItemAnimator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This implementation of {@link RecyclerView.ItemAnimator} provides basic
|
||||
* animations on remove, add, and move events that happen to the items in
|
||||
* a RecyclerView. RecyclerView uses a DefaultItemAnimator by default.
|
||||
*
|
||||
* @see RecyclerView#setItemAnimator(RecyclerView.ItemAnimator)
|
||||
*/
|
||||
public class OpenItemAnimator extends DefaultItemAnimator {
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private static TimeInterpolator sDefaultInterpolator;
|
||||
|
||||
private final ArrayList<RecyclerView.ViewHolder> mPendingRemovals = new ArrayList<>();
|
||||
private final ArrayList<RecyclerView.ViewHolder> mPendingAdditions = new ArrayList<>();
|
||||
private final ArrayList<MoveInfo> mPendingMoves = new ArrayList<>();
|
||||
private final ArrayList<ChangeInfo> mPendingChanges = new ArrayList<>();
|
||||
|
||||
ArrayList<ArrayList<RecyclerView.ViewHolder>> mAdditionsList = new ArrayList<>();
|
||||
ArrayList<ArrayList<MoveInfo>> mMovesList = new ArrayList<>();
|
||||
ArrayList<ArrayList<ChangeInfo>> mChangesList = new ArrayList<>();
|
||||
|
||||
ArrayList<RecyclerView.ViewHolder> mAddAnimations = new ArrayList<>();
|
||||
ArrayList<RecyclerView.ViewHolder> mMoveAnimations = new ArrayList<>();
|
||||
ArrayList<RecyclerView.ViewHolder> mRemoveAnimations = new ArrayList<>();
|
||||
ArrayList<RecyclerView.ViewHolder> mChangeAnimations = new ArrayList<>();
|
||||
|
||||
private static class MoveInfo {
|
||||
public RecyclerView.ViewHolder holder;
|
||||
public int fromX, fromY, toX, toY;
|
||||
|
||||
MoveInfo(RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) {
|
||||
this.holder = holder;
|
||||
this.fromX = fromX;
|
||||
this.fromY = fromY;
|
||||
this.toX = toX;
|
||||
this.toY = toY;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ChangeInfo {
|
||||
public RecyclerView.ViewHolder oldHolder, newHolder;
|
||||
public int fromX, fromY, toX, toY;
|
||||
private ChangeInfo(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder) {
|
||||
this.oldHolder = oldHolder;
|
||||
this.newHolder = newHolder;
|
||||
}
|
||||
|
||||
ChangeInfo(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder,
|
||||
int fromX, int fromY, int toX, int toY) {
|
||||
this(oldHolder, newHolder);
|
||||
this.fromX = fromX;
|
||||
this.fromY = fromY;
|
||||
this.toX = toX;
|
||||
this.toY = toY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ChangeInfo{"
|
||||
+ "oldHolder=" + oldHolder
|
||||
+ ", newHolder=" + newHolder
|
||||
+ ", fromX=" + fromX
|
||||
+ ", fromY=" + fromY
|
||||
+ ", toX=" + toX
|
||||
+ ", toY=" + toY
|
||||
+ '}';
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runPendingAnimations() {
|
||||
boolean removalsPending = !mPendingRemovals.isEmpty();
|
||||
boolean movesPending = !mPendingMoves.isEmpty();
|
||||
boolean changesPending = !mPendingChanges.isEmpty();
|
||||
boolean additionsPending = !mPendingAdditions.isEmpty();
|
||||
if (!removalsPending && !movesPending && !additionsPending && !changesPending) {
|
||||
// nothing to animate
|
||||
return;
|
||||
}
|
||||
// First, remove stuff
|
||||
for (RecyclerView.ViewHolder holder : mPendingRemovals) {
|
||||
animateRemoveImpl(holder);
|
||||
}
|
||||
mPendingRemovals.clear();
|
||||
// Next, move stuff
|
||||
if (movesPending) {
|
||||
final ArrayList<MoveInfo> moves = new ArrayList<>(mPendingMoves);
|
||||
mMovesList.add(moves);
|
||||
mPendingMoves.clear();
|
||||
Runnable mover = () -> {
|
||||
for (MoveInfo moveInfo : moves) {
|
||||
animateMoveImpl(moveInfo.holder, moveInfo.fromX, moveInfo.fromY,
|
||||
moveInfo.toX, moveInfo.toY);
|
||||
}
|
||||
moves.clear();
|
||||
mMovesList.remove(moves);
|
||||
};
|
||||
if (removalsPending) {
|
||||
View view = moves.get(0).holder.itemView;
|
||||
ViewCompat.postOnAnimationDelayed(view, mover, getRemoveDuration());
|
||||
} else {
|
||||
mover.run();
|
||||
}
|
||||
}
|
||||
// Next, change stuff, to run in parallel with move animations
|
||||
if (changesPending) {
|
||||
final ArrayList<ChangeInfo> changes = new ArrayList<>(mPendingChanges);
|
||||
mChangesList.add(changes);
|
||||
mPendingChanges.clear();
|
||||
Runnable changer = () -> {
|
||||
for (ChangeInfo change : changes) {
|
||||
animateChangeImpl(change);
|
||||
}
|
||||
changes.clear();
|
||||
mChangesList.remove(changes);
|
||||
};
|
||||
if (removalsPending) {
|
||||
RecyclerView.ViewHolder holder = changes.get(0).oldHolder;
|
||||
ViewCompat.postOnAnimationDelayed(holder.itemView, changer, getRemoveDuration());
|
||||
} else {
|
||||
changer.run();
|
||||
}
|
||||
}
|
||||
// Next, add stuff
|
||||
if (additionsPending) {
|
||||
final ArrayList<RecyclerView.ViewHolder> additions = new ArrayList<>(mPendingAdditions);
|
||||
mAdditionsList.add(additions);
|
||||
mPendingAdditions.clear();
|
||||
Runnable adder = () -> {
|
||||
for (RecyclerView.ViewHolder holder : additions) {
|
||||
animateAddImpl(holder);
|
||||
}
|
||||
additions.clear();
|
||||
mAdditionsList.remove(additions);
|
||||
};
|
||||
if (removalsPending || movesPending || changesPending) {
|
||||
long removeDuration = removalsPending ? getRemoveDuration() : 0;
|
||||
long moveDuration = movesPending ? getMoveDuration() : 0;
|
||||
long changeDuration = changesPending ? getChangeDuration() : 0;
|
||||
long totalDelay = removeDuration + Math.max(moveDuration, changeDuration);
|
||||
View view = additions.get(0).itemView;
|
||||
ViewCompat.postOnAnimationDelayed(view, adder, totalDelay);
|
||||
} else {
|
||||
adder.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean animateRemove(final RecyclerView.ViewHolder holder) {
|
||||
resetAnimation(holder);
|
||||
mPendingRemovals.add(holder);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void animateRemoveImpl(final RecyclerView.ViewHolder holder) {
|
||||
final View view = holder.itemView;
|
||||
final ViewPropertyAnimator animation = view.animate();
|
||||
mRemoveAnimations.add(holder);
|
||||
animation.setDuration(getRemoveDuration()).alpha(0).setListener(
|
||||
new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animator) {
|
||||
dispatchRemoveStarting(holder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animator) {
|
||||
animation.setListener(null);
|
||||
view.setAlpha(1);
|
||||
dispatchRemoveFinished(holder);
|
||||
mRemoveAnimations.remove(holder);
|
||||
dispatchFinishedWhenDone();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean animateAdd(final RecyclerView.ViewHolder holder) {
|
||||
resetAnimation(holder);
|
||||
holder.itemView.setAlpha(0);
|
||||
mPendingAdditions.add(holder);
|
||||
return true;
|
||||
}
|
||||
|
||||
void animateAddImpl(final RecyclerView.ViewHolder holder) {
|
||||
final View view = holder.itemView;
|
||||
final ViewPropertyAnimator animation = view.animate();
|
||||
mAddAnimations.add(holder);
|
||||
animation.alpha(1).setDuration(getAddDuration())
|
||||
.setListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animator) {
|
||||
dispatchAddStarting(holder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancel(Animator animator) {
|
||||
view.setAlpha(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animator) {
|
||||
animation.setListener(null);
|
||||
dispatchAddFinished(holder);
|
||||
mAddAnimations.remove(holder);
|
||||
dispatchFinishedWhenDone();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean animateMove(final RecyclerView.ViewHolder holder, int fromX, int fromY,
|
||||
int toX, int toY) {
|
||||
final View view = holder.itemView;
|
||||
fromX += (int) holder.itemView.getTranslationX();
|
||||
fromY += (int) holder.itemView.getTranslationY();
|
||||
resetAnimation(holder);
|
||||
int deltaX = toX - fromX;
|
||||
int deltaY = toY - fromY;
|
||||
if (deltaX == 0 && deltaY == 0) {
|
||||
dispatchMoveFinished(holder);
|
||||
return false;
|
||||
}
|
||||
if (deltaX != 0) {
|
||||
view.setTranslationX(-deltaX);
|
||||
}
|
||||
if (deltaY != 0) {
|
||||
view.setTranslationY(-deltaY);
|
||||
}
|
||||
mPendingMoves.add(new MoveInfo(holder, fromX, fromY, toX, toY));
|
||||
return true;
|
||||
}
|
||||
|
||||
void animateMoveImpl(final RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) {
|
||||
final View view = holder.itemView;
|
||||
final int deltaX = toX - fromX;
|
||||
final int deltaY = toY - fromY;
|
||||
if (deltaX != 0) {
|
||||
view.animate().translationX(0);
|
||||
}
|
||||
if (deltaY != 0) {
|
||||
view.animate().translationY(0);
|
||||
}
|
||||
// TODO: make EndActions end listeners instead, since end actions aren't called when
|
||||
// vpas are canceled (and can't end them. why?)
|
||||
// need listener functionality in VPACompat for this. Ick.
|
||||
final ViewPropertyAnimator animation = view.animate();
|
||||
mMoveAnimations.add(holder);
|
||||
animation.setDuration(getMoveDuration()).setListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animator) {
|
||||
dispatchMoveStarting(holder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancel(Animator animator) {
|
||||
if (deltaX != 0) {
|
||||
view.setTranslationX(0);
|
||||
}
|
||||
if (deltaY != 0) {
|
||||
view.setTranslationY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animator) {
|
||||
animation.setListener(null);
|
||||
dispatchMoveFinished(holder);
|
||||
mMoveAnimations.remove(holder);
|
||||
dispatchFinishedWhenDone();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder,
|
||||
int fromX, int fromY, int toX, int toY) {
|
||||
if (oldHolder == newHolder) {
|
||||
// Don't know how to run change animations when the same view holder is re-used.
|
||||
// run a move animation to handle position changes.
|
||||
return animateMove(oldHolder, fromX, fromY, toX, toY);
|
||||
}
|
||||
final float prevTranslationX = oldHolder.itemView.getTranslationX();
|
||||
final float prevTranslationY = oldHolder.itemView.getTranslationY();
|
||||
final float prevAlpha = oldHolder.itemView.getAlpha();
|
||||
resetAnimation(oldHolder);
|
||||
int deltaX = (int) (toX - fromX - prevTranslationX);
|
||||
int deltaY = (int) (toY - fromY - prevTranslationY);
|
||||
// recover prev translation state after ending animation
|
||||
oldHolder.itemView.setTranslationX(prevTranslationX);
|
||||
oldHolder.itemView.setTranslationY(prevTranslationY);
|
||||
oldHolder.itemView.setAlpha(prevAlpha);
|
||||
if (newHolder != null) {
|
||||
// carry over translation values
|
||||
resetAnimation(newHolder);
|
||||
newHolder.itemView.setTranslationX(-deltaX);
|
||||
newHolder.itemView.setTranslationY(-deltaY);
|
||||
newHolder.itemView.setAlpha(0);
|
||||
}
|
||||
mPendingChanges.add(new ChangeInfo(oldHolder, newHolder, fromX, fromY, toX, toY));
|
||||
return true;
|
||||
}
|
||||
|
||||
void animateChangeImpl(final ChangeInfo changeInfo) {
|
||||
final RecyclerView.ViewHolder holder = changeInfo.oldHolder;
|
||||
final View view = holder == null ? null : holder.itemView;
|
||||
final RecyclerView.ViewHolder newHolder = changeInfo.newHolder;
|
||||
final View newView = newHolder != null ? newHolder.itemView : null;
|
||||
if (view != null) {
|
||||
final ViewPropertyAnimator oldViewAnim = view.animate().setDuration(
|
||||
getChangeDuration());
|
||||
mChangeAnimations.add(changeInfo.oldHolder);
|
||||
oldViewAnim.translationX((float)(changeInfo.toX - changeInfo.fromX));
|
||||
oldViewAnim.translationY((float)(changeInfo.toY - changeInfo.fromY));
|
||||
oldViewAnim.alpha(0).setListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animator) {
|
||||
dispatchChangeStarting(changeInfo.oldHolder, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animator) {
|
||||
oldViewAnim.setListener(null);
|
||||
view.setAlpha(1);
|
||||
view.setTranslationX(0);
|
||||
view.setTranslationY(0);
|
||||
dispatchChangeFinished(changeInfo.oldHolder, true);
|
||||
mChangeAnimations.remove(changeInfo.oldHolder);
|
||||
dispatchFinishedWhenDone();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
if (newView != null) {
|
||||
final ViewPropertyAnimator newViewAnimation = newView.animate();
|
||||
mChangeAnimations.add(changeInfo.newHolder);
|
||||
newViewAnimation.translationX(0).translationY(0).setDuration(getChangeDuration())
|
||||
.alpha(1).setListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animator) {
|
||||
dispatchChangeStarting(changeInfo.newHolder, false);
|
||||
}
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animator) {
|
||||
newViewAnimation.setListener(null);
|
||||
newView.setAlpha(1);
|
||||
newView.setTranslationX(0);
|
||||
newView.setTranslationY(0);
|
||||
dispatchChangeFinished(changeInfo.newHolder, false);
|
||||
mChangeAnimations.remove(changeInfo.newHolder);
|
||||
dispatchFinishedWhenDone();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
|
||||
private void endChangeAnimation(List<ChangeInfo> infoList, RecyclerView.ViewHolder item) {
|
||||
for (int i = infoList.size() - 1; i >= 0; i--) {
|
||||
ChangeInfo changeInfo = infoList.get(i);
|
||||
if (endChangeAnimationIfNecessary(changeInfo, item)) {
|
||||
if (changeInfo.oldHolder == null && changeInfo.newHolder == null) {
|
||||
infoList.remove(changeInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void endChangeAnimationIfNecessary(ChangeInfo changeInfo) {
|
||||
if (changeInfo.oldHolder != null) {
|
||||
endChangeAnimationIfNecessary(changeInfo, changeInfo.oldHolder);
|
||||
}
|
||||
if (changeInfo.newHolder != null) {
|
||||
endChangeAnimationIfNecessary(changeInfo, changeInfo.newHolder);
|
||||
}
|
||||
}
|
||||
private boolean endChangeAnimationIfNecessary(ChangeInfo changeInfo, RecyclerView.ViewHolder item) {
|
||||
boolean oldItem = false;
|
||||
if (changeInfo.newHolder == item) {
|
||||
changeInfo.newHolder = null;
|
||||
} else if (changeInfo.oldHolder == item) {
|
||||
changeInfo.oldHolder = null;
|
||||
oldItem = true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
item.itemView.setAlpha(1);
|
||||
item.itemView.setTranslationX(0);
|
||||
item.itemView.setTranslationY(0);
|
||||
dispatchChangeFinished(item, oldItem);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endAnimation(RecyclerView.ViewHolder item) {
|
||||
final View view = item.itemView;
|
||||
// this will trigger end callback which should set properties to their target values.
|
||||
view.animate().cancel();
|
||||
// TODO if some other animations are chained to end, how do we cancel them as well?
|
||||
for (int i = mPendingMoves.size() - 1; i >= 0; i--) {
|
||||
MoveInfo moveInfo = mPendingMoves.get(i);
|
||||
if (moveInfo.holder == item) {
|
||||
view.setTranslationY(0);
|
||||
view.setTranslationX(0);
|
||||
dispatchMoveFinished(item);
|
||||
mPendingMoves.remove(i);
|
||||
}
|
||||
}
|
||||
endChangeAnimation(mPendingChanges, item);
|
||||
if (mPendingRemovals.remove(item)) {
|
||||
view.setAlpha(1);
|
||||
dispatchRemoveFinished(item);
|
||||
}
|
||||
if (mPendingAdditions.remove(item)) {
|
||||
view.setAlpha(1);
|
||||
dispatchAddFinished(item);
|
||||
}
|
||||
|
||||
for (int i = mChangesList.size() - 1; i >= 0; i--) {
|
||||
ArrayList<ChangeInfo> changes = mChangesList.get(i);
|
||||
endChangeAnimation(changes, item);
|
||||
if (changes.isEmpty()) {
|
||||
mChangesList.remove(i);
|
||||
}
|
||||
}
|
||||
for (int i = mMovesList.size() - 1; i >= 0; i--) {
|
||||
ArrayList<MoveInfo> moves = mMovesList.get(i);
|
||||
for (int j = moves.size() - 1; j >= 0; j--) {
|
||||
MoveInfo moveInfo = moves.get(j);
|
||||
if (moveInfo.holder == item) {
|
||||
view.setTranslationY(0);
|
||||
view.setTranslationX(0);
|
||||
dispatchMoveFinished(item);
|
||||
moves.remove(j);
|
||||
if (moves.isEmpty()) {
|
||||
mMovesList.remove(i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = mAdditionsList.size() - 1; i >= 0; i--) {
|
||||
ArrayList<RecyclerView.ViewHolder> additions = mAdditionsList.get(i);
|
||||
if (additions.remove(item)) {
|
||||
view.setAlpha(1);
|
||||
dispatchAddFinished(item);
|
||||
if (additions.isEmpty()) {
|
||||
mAdditionsList.remove(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// animations should be ended by the cancel above.
|
||||
//noinspection PointlessBooleanExpression,ConstantConditions
|
||||
if (mRemoveAnimations.remove(item) && DEBUG) {
|
||||
throw new IllegalStateException("after animation is cancelled, item should not be in "
|
||||
+ "mRemoveAnimations list");
|
||||
}
|
||||
|
||||
//noinspection PointlessBooleanExpression,ConstantConditions
|
||||
if (mAddAnimations.remove(item) && DEBUG) {
|
||||
throw new IllegalStateException("after animation is cancelled, item should not be in "
|
||||
+ "mAddAnimations list");
|
||||
}
|
||||
|
||||
//noinspection PointlessBooleanExpression,ConstantConditions
|
||||
if (mChangeAnimations.remove(item) && DEBUG) {
|
||||
throw new IllegalStateException("after animation is cancelled, item should not be in "
|
||||
+ "mChangeAnimations list");
|
||||
}
|
||||
|
||||
//noinspection PointlessBooleanExpression,ConstantConditions
|
||||
if (mMoveAnimations.remove(item) && DEBUG) {
|
||||
throw new IllegalStateException("after animation is cancelled, item should not be in "
|
||||
+ "mMoveAnimations list");
|
||||
}
|
||||
dispatchFinishedWhenDone();
|
||||
}
|
||||
|
||||
private void resetAnimation(RecyclerView.ViewHolder holder) {
|
||||
if (sDefaultInterpolator == null) {
|
||||
sDefaultInterpolator = new ValueAnimator().getInterpolator();
|
||||
}
|
||||
holder.itemView.animate().setInterpolator(sDefaultInterpolator);
|
||||
endAnimation(holder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRunning() {
|
||||
return (!mPendingAdditions.isEmpty()
|
||||
|| !mPendingChanges.isEmpty()
|
||||
|| !mPendingMoves.isEmpty()
|
||||
|| !mPendingRemovals.isEmpty()
|
||||
|| !mMoveAnimations.isEmpty()
|
||||
|| !mRemoveAnimations.isEmpty()
|
||||
|| !mAddAnimations.isEmpty()
|
||||
|| !mChangeAnimations.isEmpty()
|
||||
|| !mMovesList.isEmpty()
|
||||
|| !mAdditionsList.isEmpty()
|
||||
|| !mChangesList.isEmpty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the state of currently pending and running animations. If there are none
|
||||
* pending/running, call {@link #dispatchAnimationsFinished()} to notify any
|
||||
* listeners.
|
||||
*/
|
||||
void dispatchFinishedWhenDone() {
|
||||
if (!isRunning()) {
|
||||
dispatchAnimationsFinished();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endAnimations() {
|
||||
int count = mPendingMoves.size();
|
||||
for (int i = count - 1; i >= 0; i--) {
|
||||
MoveInfo item = mPendingMoves.get(i);
|
||||
View view = item.holder.itemView;
|
||||
view.setTranslationY(0);
|
||||
view.setTranslationX(0);
|
||||
dispatchMoveFinished(item.holder);
|
||||
mPendingMoves.remove(i);
|
||||
}
|
||||
count = mPendingRemovals.size();
|
||||
for (int i = count - 1; i >= 0; i--) {
|
||||
RecyclerView.ViewHolder item = mPendingRemovals.get(i);
|
||||
dispatchRemoveFinished(item);
|
||||
mPendingRemovals.remove(i);
|
||||
}
|
||||
count = mPendingAdditions.size();
|
||||
for (int i = count - 1; i >= 0; i--) {
|
||||
RecyclerView.ViewHolder item = mPendingAdditions.get(i);
|
||||
item.itemView.setAlpha(1);
|
||||
dispatchAddFinished(item);
|
||||
mPendingAdditions.remove(i);
|
||||
}
|
||||
count = mPendingChanges.size();
|
||||
for (int i = count - 1; i >= 0; i--) {
|
||||
endChangeAnimationIfNecessary(mPendingChanges.get(i));
|
||||
}
|
||||
mPendingChanges.clear();
|
||||
if (!isRunning()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int listCount = mMovesList.size();
|
||||
for (int i = listCount - 1; i >= 0; i--) {
|
||||
ArrayList<MoveInfo> moves = mMovesList.get(i);
|
||||
count = moves.size();
|
||||
for (int j = count - 1; j >= 0; j--) {
|
||||
MoveInfo moveInfo = moves.get(j);
|
||||
RecyclerView.ViewHolder item = moveInfo.holder;
|
||||
View view = item.itemView;
|
||||
view.setTranslationY(0);
|
||||
view.setTranslationX(0);
|
||||
dispatchMoveFinished(moveInfo.holder);
|
||||
moves.remove(j);
|
||||
if (moves.isEmpty()) {
|
||||
mMovesList.remove(moves);
|
||||
}
|
||||
}
|
||||
}
|
||||
listCount = mAdditionsList.size();
|
||||
for (int i = listCount - 1; i >= 0; i--) {
|
||||
ArrayList<RecyclerView.ViewHolder> additions = mAdditionsList.get(i);
|
||||
count = additions.size();
|
||||
for (int j = count - 1; j >= 0; j--) {
|
||||
RecyclerView.ViewHolder item = additions.get(j);
|
||||
View view = item.itemView;
|
||||
view.setAlpha(1);
|
||||
dispatchAddFinished(item);
|
||||
additions.remove(j);
|
||||
if (additions.isEmpty()) {
|
||||
mAdditionsList.remove(additions);
|
||||
}
|
||||
}
|
||||
}
|
||||
listCount = mChangesList.size();
|
||||
for (int i = listCount - 1; i >= 0; i--) {
|
||||
ArrayList<ChangeInfo> changes = mChangesList.get(i);
|
||||
count = changes.size();
|
||||
for (int j = count - 1; j >= 0; j--) {
|
||||
endChangeAnimationIfNecessary(changes.get(j));
|
||||
if (changes.isEmpty()) {
|
||||
mChangesList.remove(changes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cancelAll(mRemoveAnimations);
|
||||
cancelAll(mMoveAnimations);
|
||||
cancelAll(mAddAnimations);
|
||||
cancelAll(mChangeAnimations);
|
||||
|
||||
dispatchAnimationsFinished();
|
||||
}
|
||||
|
||||
void cancelAll(List<RecyclerView.ViewHolder> viewHolders) {
|
||||
for (int i = viewHolders.size() - 1; i >= 0; i--) {
|
||||
viewHolders.get(i).itemView.animate().cancel();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>
|
||||
* If the payload list is not empty, DefaultItemAnimator returns <code>true</code>.
|
||||
* When this is the case:
|
||||
* <ul>
|
||||
* <li>If you override {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)}, both
|
||||
* ViewHolder arguments will be the same instance.
|
||||
* </li>
|
||||
* <li>
|
||||
* If you are not overriding {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)},
|
||||
* then DefaultItemAnimator will call {@link #animateMove(RecyclerView.ViewHolder, int, int, int, int)} and
|
||||
* run a move animation instead.
|
||||
* </li>
|
||||
* </ul>
|
||||
*/
|
||||
@Override
|
||||
public boolean canReuseUpdatedViewHolder(@NonNull RecyclerView.ViewHolder viewHolder,
|
||||
@NonNull List<Object> payloads) {
|
||||
return !payloads.isEmpty() || super.canReuseUpdatedViewHolder(viewHolder, payloads);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
package com.mogo.och.offline.ui.adapter
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import androidx.appcompat.widget.AppCompatTextView
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.mogo.och.offline.R
|
||||
import com.mogo.och.offline.bean.BindLineListResponse
|
||||
import com.mogo.och.offline.ui.adapter.SwitchLineAdapter.SwitchLineViewHolder
|
||||
import kotlin.text.StringBuilder
|
||||
|
||||
/**
|
||||
* 路线列表adapter
|
||||
*/
|
||||
class SwitchLineAdapter(
|
||||
private val mContext: Context,
|
||||
private val mData: List<BindLineListResponse.Result>
|
||||
) : RecyclerView.Adapter<SwitchLineViewHolder>() {
|
||||
companion object{
|
||||
const val TAG = "SwitchLineAdapter"
|
||||
}
|
||||
// RecyclerView设置点击事件
|
||||
private var mItemClickListener: LineItemClickListener? = null
|
||||
private var checkInfo:BindLineListResponse.Result? = null
|
||||
override fun onCreateViewHolder(
|
||||
parent: ViewGroup,
|
||||
viewType: Int
|
||||
): SwitchLineViewHolder {
|
||||
val view = LayoutInflater.from(mContext).inflate(
|
||||
R.layout.offline_switch_line_list_item, parent, false
|
||||
)
|
||||
return SwitchLineViewHolder(view)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: SwitchLineViewHolder, position: Int) {
|
||||
val currentPosition = holder.bindingAdapterPosition
|
||||
val lineInfo = mData[currentPosition]
|
||||
|
||||
if (lineInfo==checkInfo) {
|
||||
holder.itemView.setBackgroundResource(R.drawable.bus_shape_select_line_item_bg_normal)
|
||||
} else {
|
||||
holder.itemView.setBackgroundColor(Color.parseColor("#162761"))
|
||||
}
|
||||
|
||||
lineInfo.line?.let {line->
|
||||
line.lineName?.let {
|
||||
if(it.length>10){
|
||||
holder.linelineName.text = it.substring(0,10)+"…"
|
||||
}else{
|
||||
holder.linelineName.text = lineInfo.line?.lineName
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
lineInfo.siteList?.let {
|
||||
val last = it.last()
|
||||
last.name?.let {siteName->
|
||||
val sb = StringBuilder()
|
||||
if (siteName.length>10) {
|
||||
sb.append(siteName.substring(0,5))
|
||||
sb.append("…")
|
||||
sb.append(siteName.substring(siteName.length-5,siteName.length))
|
||||
}else{
|
||||
sb.append(siteName)
|
||||
}
|
||||
val string = mContext.getString(R.string.bus_line_goto_end, sb.toString())
|
||||
holder.lineEndlineName.text = string
|
||||
}
|
||||
}
|
||||
|
||||
//设置item点击事件
|
||||
holder.itemView.setOnClickListener {
|
||||
val oldPosition = mData.indexOf(checkInfo)
|
||||
checkInfo = lineInfo
|
||||
notifyItemChanged(oldPosition)
|
||||
notifyItemChanged(currentPosition)
|
||||
mItemClickListener?.onItemClick(lineInfo)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return mData.size
|
||||
}
|
||||
|
||||
fun setOnLineItemClickListener(itemClickListener: LineItemClickListener?) {
|
||||
mItemClickListener = itemClickListener
|
||||
}
|
||||
|
||||
class SwitchLineViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||
val linelineName: AppCompatTextView//线路名称
|
||||
val lineEndlineName: AppCompatTextView //终点
|
||||
|
||||
init {
|
||||
linelineName = itemView.findViewById(R.id.switch_line_name)
|
||||
lineEndlineName = itemView.findViewById(R.id.switch_line_end_station)
|
||||
}
|
||||
}
|
||||
|
||||
interface LineItemClickListener {
|
||||
fun onItemClick(lineInfo: BindLineListResponse.Result)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.mogo.och.offline.util;
|
||||
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.mogo.och.common.module.manager.autopilot.autopilot.OchAutopilotAnalytics;
|
||||
|
||||
/**
|
||||
* OCH Bus埋点工具
|
||||
* <p>
|
||||
* Created on 2022/3/24
|
||||
*/
|
||||
public class BusAnalyticsManager extends OchAutopilotAnalytics {
|
||||
|
||||
// 埋点key:开启自动驾驶前已识别的异常,会导致无法开启自驾
|
||||
private static final String EVENT_KEY_AP_UNABLE_START_REASON = "event_key_och_bus_ap_unable_start_reason";
|
||||
// 埋点key:接管后点击'自动驾驶'按钮启动
|
||||
private static final String EVENT_KEY_RESTART_AUTOPILOT = "event_key_och_bus_restart_autopilot";
|
||||
// 埋点key:开始服务开启自动驾驶(成功/失败)
|
||||
private static final String EVENT_KEY_START_SERVICE = "event_key_och_bus_start_service";
|
||||
// 埋点key:点击启动自驾
|
||||
private static final String EVENT_KEY_CLICK_START_AUTOPILOT = "event_key_och_shuttle_click_start_autopilot";
|
||||
|
||||
private static final class SingletonHolder {
|
||||
private static final BusAnalyticsManager INSTANCE = new BusAnalyticsManager();
|
||||
}
|
||||
|
||||
public static BusAnalyticsManager getInstance() {
|
||||
return BusAnalyticsManager.SingletonHolder.INSTANCE;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getEventKeyStartService() {
|
||||
return EVENT_KEY_START_SERVICE;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getEventKeyRestartService() {
|
||||
return EVENT_KEY_RESTART_AUTOPILOT;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getEventKeyApUnableStartReason() {
|
||||
return EVENT_KEY_AP_UNABLE_START_REASON;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getEventKeyClickStartAutopilot() {
|
||||
return EVENT_KEY_CLICK_START_AUTOPILOT;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.mogo.och.offline.util
|
||||
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotControlManager
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
* @date: 2022/10/24
|
||||
*/
|
||||
object BusSendTripInfoManager{
|
||||
|
||||
const val START_TRIP = 1
|
||||
const val END_TRIP = 2
|
||||
const val LEAVE_STATION = 3
|
||||
const val ARRIVE_STATION = 4
|
||||
|
||||
/**
|
||||
* 行程信息
|
||||
* @param type 事件类型, 1:行程开始, 2:行程结束, 3:出站, 4:进站, 5:城市占道施工预警
|
||||
* @param lineName 路线名, for type 1, 2
|
||||
* @param departureStopName 出站站点名, for type 3, 4
|
||||
* @param arrivalStopName 下一站到达站点名, for type 3, 4
|
||||
* @param isLastStop 是否终点站(下一站或者要到达站)
|
||||
* @return
|
||||
*/
|
||||
fun sendBusTripInfo(type: Int, lineName: String,
|
||||
departureStopName: String,
|
||||
arrivalStopName: String,
|
||||
isLastStop: Boolean) {
|
||||
d(SceneConstant.M_BUS + "BusSendTripInfoManager", "type: "+ type
|
||||
+", lineName: "+ lineName +", departureStopName: "+ departureStopName
|
||||
+ ", arrivalStopName: "+arrivalStopName+", isLastStop: "+isLastStop)
|
||||
CallerAutoPilotControlManager.sendTripInfo(type,lineName,departureStopName, arrivalStopName, isLastStop)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
package com.mogo.och.offline.util;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.mogo.eagle.core.data.autopilot.AutopilotControlParameters;
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotControlManager;
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
|
||||
import com.mogo.eagle.core.utilcode.util.GsonUtils;
|
||||
import com.mogo.och.common.module.manager.logchainanalytic.OchChainLogManager;
|
||||
import com.mogo.och.data.bean.BusRoutesResult;
|
||||
import com.mogo.och.offline.constant.BusConst;
|
||||
import com.mogo.och.offline.model.OrderModel;
|
||||
import com.mogo.och.common.module.biz.login.LoginStatusManager;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import mogo_msg.MogoReportMsg;
|
||||
|
||||
import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS;
|
||||
|
||||
/**
|
||||
* Bus轨迹管理:给MEC下发用于轨迹下载的信息
|
||||
* Created on 2022/6/23
|
||||
*/
|
||||
public class BusTrajectoryManager {
|
||||
private static final String TAG = BusTrajectoryManager.class.getSimpleName();
|
||||
|
||||
private static final class SingletonHolder {
|
||||
private static final BusTrajectoryManager INSTANCE = new BusTrajectoryManager();
|
||||
}
|
||||
|
||||
public static BusTrajectoryManager getInstance() {
|
||||
return BusTrajectoryManager.SingletonHolder.INSTANCE;
|
||||
}
|
||||
|
||||
private AutopilotControlParameters.AutoPilotLine mAutoPilotLine = null;
|
||||
private Disposable mSendReqDisposable = null;
|
||||
|
||||
public BusTrajectoryManager() {
|
||||
mAutoPilotLine = new AutopilotControlParameters.AutoPilotLine(-1, "",
|
||||
"", "", "", "", 0, "",
|
||||
"", "", "", "", 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步Bus路线信息
|
||||
*/
|
||||
public void syncTrajectoryInfo() {
|
||||
BusRoutesResult routesResult = OrderModel.getInstance().getBusRoutesResult();
|
||||
if (LoginStatusManager.isLogin() && routesResult != null
|
||||
&& OrderModel.getInstance().getCurrentStationIndex() == 0
|
||||
&& !OrderModel.getInstance().isGoingToNextStation()) {
|
||||
CallerLogger.d(M_BUS + TAG, "syncTrajectoryInfo() start.");
|
||||
startTrajReqLoop();
|
||||
} else {
|
||||
// 无路线信息or当前未在始发站
|
||||
CallerLogger.d(M_BUS + TAG, "syncTrajectoryInfo() stop.");
|
||||
stopTrajReqLoop();
|
||||
}
|
||||
}
|
||||
|
||||
public void onAutopilotGuardian(@Nullable MogoReportMsg.MogoReportMessage guardianInfo,long lineId) {
|
||||
onAutopilotGuardian(guardianInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 接口MEC反馈的常规信息(MAP v2.5.0新增轨迹相关信息)
|
||||
* @param guardianInfo
|
||||
*/
|
||||
public void onAutopilotGuardian(@Nullable MogoReportMsg.MogoReportMessage guardianInfo) {
|
||||
if (guardianInfo == null || !guardianInfo.hasCode()) return;
|
||||
if ("ISYS_INIT_TRAJECTORY_START".equals(guardianInfo.getCode())) {
|
||||
// 1. 轨迹管理_轨迹开始下载(本地已有对应轨迹也触发)
|
||||
CallerLogger.d(M_BUS + TAG, "onAutopilotGuardian() 轨迹开始下载");
|
||||
OchChainLogManager.writeChainLog("轨迹监控","onAutopilotGuardian() 轨迹开始下载", true, OchChainLogManager.EVENT_KEY_INFE_WITH_TRAJECTORY);
|
||||
// ToastUtils.showShort("轨迹开始下载");
|
||||
stopTrajReqLoop();
|
||||
} else if ("ISYS_INIT_TRAJECTORY_SUCCESS".equals(guardianInfo.getCode())) {
|
||||
// 2. 轨迹管理_轨迹下载成功(本地已有对应轨迹也触发)
|
||||
CallerLogger.d(M_BUS + TAG, "onAutopilotGuardian() 轨迹下载成功");
|
||||
OchChainLogManager.writeChainLog("轨迹监控","onAutopilotGuardian() 轨迹下载成功", true, OchChainLogManager.EVENT_KEY_INFE_WITH_TRAJECTORY);
|
||||
// ToastUtils.showShort("轨迹下载成功");
|
||||
stopTrajReqLoop();
|
||||
} else if ("ISYS_INIT_TRAJECTORY_FAILURE".equals(guardianInfo.getCode())) {
|
||||
// 3. 轨迹管理_轨迹下载失败,本地无对应轨迹
|
||||
CallerLogger.d(M_BUS + TAG, "onAutopilotGuardian() " +
|
||||
"轨迹下载失败,本地无对应轨迹");
|
||||
OchChainLogManager.writeChainLog("轨迹监控","onAutopilotGuardian() 轨迹下载失败,本地无对应轨迹", true, OchChainLogManager.EVENT_KEY_INFE_WITH_TRAJECTORY);
|
||||
// ToastUtils.showShort("轨迹下载失败,本地无对应轨迹");
|
||||
} else if ("ISYS_INIT_TRAJECTORY_WARNING".equals(guardianInfo.getCode())) {
|
||||
// 4. 轨迹管理_轨迹下载失败,本地有对应轨迹,认为成功
|
||||
CallerLogger.d(M_BUS + TAG, "onAutopilotGuardian() " +
|
||||
"轨迹下载失败,本地有对应轨迹,认为成功");
|
||||
OchChainLogManager.writeChainLog("轨迹监控","onAutopilotGuardian() 轨迹下载失败,本地有对应轨迹,认为成功", true, OchChainLogManager.EVENT_KEY_INFE_WITH_TRAJECTORY);
|
||||
// ToastUtils.showShort("轨迹下载失败,本地有对应轨迹,认为成功");
|
||||
} else if ("ISYS_INIT_TRAJECTORY_TIMEOUT".equals(guardianInfo.getCode())) {
|
||||
// 5. 轨迹管理_轨迹下载超时
|
||||
CallerLogger.d(M_BUS + TAG, "onAutopilotGuardian() 轨迹下载超时");
|
||||
OchChainLogManager.writeChainLog("轨迹监控","onAutopilotGuardian() 轨迹下载超时", true, OchChainLogManager.EVENT_KEY_INFE_WITH_TRAJECTORY);
|
||||
// ToastUtils.showShort("轨迹下载超时");
|
||||
} else if ("ISSM_FUNC_AUTO_PILOT_READY".equals(guardianInfo.getCode())) {
|
||||
// 收到ssm的自动驾驶变为ready,再次下发轨迹下载.解决:域控重启,或者102域控启动太早,107节点初始化未完成导致的轨迹未进行下载。
|
||||
CallerLogger.d(M_BUS + TAG, "onAutopilotGuardian() ssm ready,再次发起下载");
|
||||
OchChainLogManager.writeChainLog("轨迹监控","onAutopilotGuardian() 再次发起下载", true, OchChainLogManager.EVENT_KEY_INFE_WITH_TRAJECTORY);
|
||||
syncTrajectoryInfo();
|
||||
}
|
||||
}
|
||||
|
||||
private void setupAutoPilotLine() {
|
||||
BusRoutesResult routesResult = OrderModel.getInstance().getBusRoutesResult();
|
||||
if (routesResult == null) {
|
||||
CallerLogger.e(M_BUS + TAG,
|
||||
"setupAutoPilotLine(): routesResult is null.");
|
||||
return;
|
||||
} else {
|
||||
if (mAutoPilotLine == null) {
|
||||
mAutoPilotLine = new AutopilotControlParameters.AutoPilotLine(
|
||||
routesResult.getLineId(), routesResult.getName(),
|
||||
routesResult.csvFileUrl, routesResult.csvFileMd5,
|
||||
routesResult.txtFileUrl, routesResult.txtFileMd5,
|
||||
routesResult.contrailSaveTime, routesResult.carModel,
|
||||
routesResult.csvFileUrlDPQP, routesResult.csvFileMd5DPQP,
|
||||
routesResult.txtFileUrlDPQP, routesResult.txtFileMd5DPQP,
|
||||
routesResult.contrailSaveTimeDPQP);
|
||||
} else {
|
||||
mAutoPilotLine.setLineId(routesResult.getLineId());
|
||||
mAutoPilotLine.setLineName(routesResult.getName());
|
||||
mAutoPilotLine.setTrajUrl(routesResult.csvFileUrl);
|
||||
mAutoPilotLine.setTrajMd5(routesResult.csvFileMd5);
|
||||
mAutoPilotLine.setStopUrl(routesResult.txtFileUrl);
|
||||
mAutoPilotLine.setStopMd5(routesResult.txtFileMd5);
|
||||
mAutoPilotLine.setTimestamp(routesResult.contrailSaveTime);
|
||||
mAutoPilotLine.setVehicleModel(routesResult.carModel);
|
||||
mAutoPilotLine.setTrajUrl_dpqp(routesResult.csvFileUrlDPQP);
|
||||
mAutoPilotLine.setTrajMd5_dpqp(routesResult.csvFileMd5DPQP);
|
||||
mAutoPilotLine.setStopUrl_dpqp(routesResult.txtFileUrlDPQP);
|
||||
mAutoPilotLine.setStopMd5_dpqp(routesResult.txtFileMd5DPQP);
|
||||
mAutoPilotLine.setTimestamp_dpqp(routesResult.contrailSaveTimeDPQP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void clearAutoPilotLine() {
|
||||
if (mAutoPilotLine == null) return;
|
||||
mAutoPilotLine.setLineId(-1);
|
||||
mAutoPilotLine.setLineName("");
|
||||
mAutoPilotLine.setTrajUrl("");
|
||||
mAutoPilotLine.setTrajMd5("");
|
||||
mAutoPilotLine.setStopUrl("");
|
||||
mAutoPilotLine.setStopMd5("");
|
||||
mAutoPilotLine.setTimestamp(0);
|
||||
mAutoPilotLine.setVehicleModel("");
|
||||
mAutoPilotLine.setTrajUrl_dpqp("");
|
||||
mAutoPilotLine.setTrajMd5_dpqp("");
|
||||
mAutoPilotLine.setStopUrl_dpqp("");
|
||||
mAutoPilotLine.setStopMd5_dpqp("");
|
||||
mAutoPilotLine.setTimestamp_dpqp(0);
|
||||
}
|
||||
|
||||
private void startTrajReqLoop() {
|
||||
if (mSendReqDisposable != null && !mSendReqDisposable.isDisposed()) {
|
||||
return;
|
||||
}
|
||||
CallerLogger.d(M_BUS + TAG, "startTrajReqLoop()");
|
||||
setupAutoPilotLine();
|
||||
mSendReqDisposable = Observable.interval(BusConst.LOOP_DELAY,
|
||||
BusConst.LOOP_PERIOD_10S, TimeUnit.MILLISECONDS)
|
||||
.map((aLong -> aLong + 1))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(aLong -> {
|
||||
if (aLong > BusConst.LOOP_SEND_TRAJ_TIMES) {
|
||||
stopTrajReqLoop();
|
||||
return;
|
||||
}
|
||||
CallerLogger.d(M_BUS + TAG, "loop sendTrajectoryReq: " + aLong);
|
||||
sendTrajectoryReq();
|
||||
});
|
||||
}
|
||||
|
||||
public void stopTrajReqLoop() {
|
||||
if (mSendReqDisposable != null) {
|
||||
CallerLogger.d(M_BUS + TAG, "stopTrajReqLoop()");
|
||||
mSendReqDisposable.dispose();
|
||||
mSendReqDisposable = null;
|
||||
clearAutoPilotLine();
|
||||
}
|
||||
}
|
||||
|
||||
private void sendTrajectoryReq() {
|
||||
if (mAutoPilotLine == null) {
|
||||
CallerLogger.e(M_BUS + TAG, "sendTrajectoryReq(): mAutoPilotLine is null!!!");
|
||||
return;
|
||||
}
|
||||
OchChainLogManager.writeChainLog("轨迹监控","sendTrajectoryReq() 下发轨迹 轨迹id"+mAutoPilotLine.getLineId(), true, OchChainLogManager.EVENT_KEY_INFE_WITH_TRAJECTORY);
|
||||
CallerAutoPilotControlManager.INSTANCE.sendTrajectoryDownloadReq(mAutoPilotLine);
|
||||
CallerLogger.d(M_BUS + TAG, "sendTrajectoryReq(): "
|
||||
+ GsonUtils.toJson(mAutoPilotLine));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package com.mogo.och.offline.util
|
||||
|
||||
import com.mogo.commons.AbsMogoApplication
|
||||
import com.mogo.commons.voice.AIAssist
|
||||
import com.mogo.eagle.core.data.config.FunctionBuildConfig
|
||||
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
|
||||
import com.mogo.och.common.module.voice.VoiceNotice
|
||||
import com.mogo.och.offline.R
|
||||
import com.mogo.tts.base.LangTtsEntity
|
||||
import com.mogo.tts.base.LanguageType
|
||||
import java.util.ArrayList
|
||||
|
||||
object ShuttleVoiceManager {
|
||||
|
||||
fun arrivedStationBus(siteNameCN: String?, siteNameKR: String?) {
|
||||
val context = AbsMogoApplication.getApp()
|
||||
val list: MutableList<LangTtsEntity> = ArrayList()
|
||||
siteNameCN?.let {
|
||||
val chineseTTS = LangTtsEntity(
|
||||
context.getString(R.string.bus_arrived_station_tip, it),
|
||||
LanguageType.CHINESE
|
||||
)
|
||||
val engTTS = LangTtsEntity(
|
||||
context.getString(R.string.bus_arrived_station_english_tip, it),
|
||||
LanguageType.CHINESE
|
||||
)
|
||||
val koreanTTS = LangTtsEntity(
|
||||
context.getString(R.string.bus_arrived_station_korean_tip, siteNameKR?:it),
|
||||
LanguageType.KOREAN
|
||||
)
|
||||
list.add(chineseTTS)
|
||||
list.add(engTTS)
|
||||
list.add(koreanTTS)
|
||||
}
|
||||
|
||||
VoiceNotice.showNotice(list, AIAssist.LEVEL1,null)
|
||||
}
|
||||
|
||||
fun leaveStationBus(siteNameCN: String?, siteNameKR: String?) {
|
||||
val list: MutableList<LangTtsEntity> = ArrayList()
|
||||
val context = AbsMogoApplication.getApp()
|
||||
siteNameCN?.let {
|
||||
val chineseTTS = LangTtsEntity(
|
||||
context.getString(R.string.bus_leave_station_tip, it),
|
||||
LanguageType.CHINESE
|
||||
)
|
||||
val engTTS = LangTtsEntity(
|
||||
context.getString(R.string.bus_leave_station_english_tip, it),
|
||||
LanguageType.CHINESE
|
||||
)
|
||||
list.add(chineseTTS)
|
||||
list.add(engTTS)
|
||||
|
||||
val koreanTTS = LangTtsEntity(
|
||||
context.getString(R.string.bus_leave_station_korean_tip, siteNameKR ?: it),
|
||||
LanguageType.KOREAN
|
||||
)
|
||||
list.add(koreanTTS)
|
||||
}
|
||||
VoiceNotice.showNotice(list, AIAssist.LEVEL1,null)
|
||||
}
|
||||
|
||||
fun endOrderBus() {
|
||||
val context = AbsMogoApplication.getApp()
|
||||
val list: MutableList<LangTtsEntity> = ArrayList()
|
||||
val chineseTTS = LangTtsEntity(context.getString(R.string.bus_end_task_tip), LanguageType.CHINESE)
|
||||
val engTTS = LangTtsEntity(context.getString(R.string.bus_end_task_english_tip), LanguageType.ENGLISH)
|
||||
val koreanTTS = LangTtsEntity(context.getString(R.string.bus_end_task_korean_tip), LanguageType.KOREAN)
|
||||
list.add(chineseTTS)
|
||||
list.add(engTTS)
|
||||
list.add(koreanTTS)
|
||||
VoiceNotice.showNotice(list, AIAssist.LEVEL0,null)
|
||||
}
|
||||
|
||||
fun writeOffCount(successNum:Int){
|
||||
if(successNum<=1){
|
||||
VoiceNotice.showNotice("核验通过", AIAssist.LEVEL3);
|
||||
}else{
|
||||
VoiceNotice.showNotice("$successNum 人核验通过", AIAssist.LEVEL3)
|
||||
}
|
||||
}
|
||||
|
||||
// 距离发车还有1分钟
|
||||
fun showLeafTime(tips: String) {
|
||||
//语音提示
|
||||
VoiceNotice.showNotice(tips)
|
||||
}
|
||||
|
||||
fun writeOffFaile(reaseon:String) {
|
||||
VoiceNotice.showNotice("验票失败,${reaseon}", AIAssist.LEVEL3)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.mogo.och.offline.view
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.widget.FrameLayout
|
||||
import com.mogo.eagle.core.data.config.FunctionBuildConfig
|
||||
import com.mogo.eagle.core.function.view.MapBizView
|
||||
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
|
||||
import com.mogo.map.uicontroller.IMogoMapUIController
|
||||
import com.mogo.och.offline.R
|
||||
|
||||
/**
|
||||
* 魔戒蓝牙控件
|
||||
* 放置于StatusBar右侧位置
|
||||
*/
|
||||
class BizMapView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0
|
||||
) : FrameLayout(context, attrs, defStyleAttr) {
|
||||
|
||||
private lateinit var mapBizView: MapBizView
|
||||
|
||||
init {
|
||||
if (AppIdentityModeUtils.isB2(FunctionBuildConfig.appIdentityMode)) {
|
||||
LayoutInflater.from(context).inflate(R.layout.offline_m2_bizmap_map, this, true)
|
||||
}else if(AppIdentityModeUtils.isB1(FunctionBuildConfig.appIdentityMode)){
|
||||
LayoutInflater.from(context).inflate(R.layout.offline_jl_bizmap_map, this, true)
|
||||
}else{
|
||||
LayoutInflater.from(context).inflate(R.layout.offline_jl_bizmap_map, this, true)
|
||||
}
|
||||
mapBizView = findViewById(R.id.bizMapView)
|
||||
}
|
||||
|
||||
fun getUI(): IMogoMapUIController? {
|
||||
return mapBizView.getUI()
|
||||
}
|
||||
|
||||
fun onCreate(bundle: Bundle?) {
|
||||
mapBizView.onCreate(bundle)
|
||||
}
|
||||
fun onResume() {
|
||||
mapBizView.onResume()
|
||||
}
|
||||
|
||||
fun onSaveInstanceState(outState: Bundle){
|
||||
mapBizView.onSaveInstanceState(outState)
|
||||
}
|
||||
|
||||
fun onLowMemory() {
|
||||
mapBizView.onLowMemory()
|
||||
}
|
||||
|
||||
fun onPause() {
|
||||
mapBizView.onPause()
|
||||
}
|
||||
|
||||
fun onDestroy() {
|
||||
mapBizView.onDestroy()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,300 @@
|
||||
package com.mogo.och.offline.view;
|
||||
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.LinearGradient;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Shader;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.animation.DecelerateInterpolator;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.mogo.commons.AbsMogoApplication;
|
||||
import com.mogo.eagle.core.utilcode.util.ConvertUtils;
|
||||
import com.mogo.eagle.core.utilcode.util.ThreadUtils;
|
||||
import com.mogo.eagle.core.utilcode.util.UiThreadHandler;
|
||||
import com.mogo.och.common.module.manager.logchainanalytic.OchChainLogManager;
|
||||
import com.mogo.och.offline.R;
|
||||
|
||||
import me.jessyan.autosize.AutoSizeConfig;
|
||||
import me.jessyan.autosize.utils.AutoSizeUtils;
|
||||
|
||||
/**
|
||||
* 滑块滑动面板
|
||||
*
|
||||
* @author tongchenfei
|
||||
*/
|
||||
public class SlidePanelView extends View {
|
||||
private static final String TAG = "SlidePanelView";
|
||||
|
||||
public SlidePanelView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public SlidePanelView(Context context, @Nullable AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public SlidePanelView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.SlidePanelView);
|
||||
textSize = (int) mTypedArray.getDimension(R.styleable.SlidePanelView_textSize, textSize);
|
||||
BLOCK_START_X = (int) mTypedArray.getDimension(R.styleable.SlidePanelView_BLOCK_START_X, BLOCK_START_X);
|
||||
BLOCK_START_Y = (int) mTypedArray.getDimension(R.styleable.SlidePanelView_BLOCK_START_Y, BLOCK_START_Y);
|
||||
NORMAL_TEXT_MARGIN_LEFT = (int) mTypedArray.getDimension(R.styleable.SlidePanelView_NORMAL_TEXT_MARGIN_LEFT, NORMAL_TEXT_MARGIN_LEFT);
|
||||
NORMAL_TEXT_MARGIN_RIGHT = (int) mTypedArray.getDimension(R.styleable.SlidePanelView_NORMAL_TEXT_MARGIN_RIGHT, NORMAL_TEXT_MARGIN_RIGHT);
|
||||
SHORT_TEXT_MARGIN_LEFT = (int) mTypedArray.getDimension(R.styleable.SlidePanelView_SHORT_TEXT_MARGIN_LEFT, SHORT_TEXT_MARGIN_LEFT);
|
||||
SHORT_TEXT_MARGIN_RIGHT = (int) mTypedArray.getDimension(R.styleable.SlidePanelView_SHORT_TEXT_MARGIN_RIGHT, SHORT_TEXT_MARGIN_RIGHT);
|
||||
init();
|
||||
}
|
||||
|
||||
private final Paint bgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
private final Paint blockPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
private final Paint textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
|
||||
private static int textSize = 40;
|
||||
private static int BLOCK_START_X = AutoSizeUtils.dp2px(AbsMogoApplication.getApp(),15);
|
||||
private static int BLOCK_START_Y = AutoSizeUtils.dp2px(AbsMogoApplication.getApp(),15);
|
||||
private static int NORMAL_TEXT_MARGIN_LEFT = AutoSizeUtils.dp2px(AbsMogoApplication.getApp(),40);
|
||||
private static int NORMAL_TEXT_MARGIN_RIGHT = AutoSizeUtils.dp2px(AbsMogoApplication.getApp(),60);
|
||||
private static int SHORT_TEXT_MARGIN_LEFT = AutoSizeUtils.dp2px(AbsMogoApplication.getApp(),60);;
|
||||
private static int SHORT_TEXT_MARGIN_RIGHT = AutoSizeUtils.dp2px(AbsMogoApplication.getApp(),70);;
|
||||
|
||||
private int textMarginLeft = NORMAL_TEXT_MARGIN_LEFT;
|
||||
private int textMarginRight = NORMAL_TEXT_MARGIN_RIGHT;
|
||||
|
||||
private OnSlidePanelMoveToEndListener moveToEndListener;
|
||||
|
||||
private int blockWidth = 0;
|
||||
private int blockOffset = 0;
|
||||
|
||||
private float lastX;
|
||||
private boolean isToEnd = false;
|
||||
|
||||
private static final String STRING_SLIDE_TO_RIGHT = "向右滑动";
|
||||
private RectF bgRectF;
|
||||
private Bitmap bmBlock;
|
||||
|
||||
private final Matrix gradientMatrix = new Matrix();
|
||||
private float matrixTranslate;
|
||||
private final Rect textRect = new Rect();
|
||||
private LinearGradient textGradient;
|
||||
|
||||
private ObjectAnimator matrixAnim;
|
||||
|
||||
private String blockText = STRING_SLIDE_TO_RIGHT;
|
||||
private final Paint.FontMetrics blockTextMetrics = new Paint.FontMetrics();
|
||||
|
||||
private static final int GRADIENT_OFFSET = 200;
|
||||
|
||||
public void setOnSlidePanelMoveToEndListener(OnSlidePanelMoveToEndListener moveToEndListener) {
|
||||
this.moveToEndListener = moveToEndListener;
|
||||
}
|
||||
|
||||
private void setBlockOffset(int blockOffset) {
|
||||
this.blockOffset = blockOffset;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
private void setMatrixTranslate(float matrixTranslate) {
|
||||
this.matrixTranslate = matrixTranslate;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.blockText = text;
|
||||
requestLayout();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
bgRectF = new RectF(0, 0, 0, 0);
|
||||
bgPaint.setColor(Color.parseColor("#CC0F1325"));
|
||||
bgPaint.setStyle(Paint.Style.FILL);
|
||||
|
||||
textPaint.setStyle(Paint.Style.FILL);
|
||||
textPaint.setTextSize(textSize);
|
||||
textPaint.setTextAlign(Paint.Align.LEFT);
|
||||
textGradient = new LinearGradient(-GRADIENT_OFFSET, 0, 0, 0, new int[]{0x33ffffff, 0xffffffff, 0x33ffffff}, null, Shader.TileMode.CLAMP);
|
||||
textGradient.setLocalMatrix(gradientMatrix);
|
||||
textPaint.setShader(textGradient);
|
||||
textPaint.getFontMetrics(blockTextMetrics);
|
||||
decodeImage();
|
||||
}
|
||||
|
||||
private void decodeImage(){
|
||||
ThreadUtils.getCpuPool().execute(() -> {
|
||||
int size = AutoSizeUtils.dp2px(getContext(), 120);
|
||||
BitmapFactory.Options opts = new BitmapFactory.Options();
|
||||
opts.inDensity = (int) AutoSizeConfig.getInstance().getInitDensity();
|
||||
bmBlock = BitmapFactory.decodeResource(getResources(), R.drawable.bus_base_slide_block,opts);
|
||||
bmBlock = Bitmap.createScaledBitmap(bmBlock, size, size, true);
|
||||
blockWidth = bmBlock.getWidth();
|
||||
UiThreadHandler.post(this::requestLayout,UiThreadHandler.MODE.QUEUE);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
|
||||
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
|
||||
int widthSize;
|
||||
int heightSize;
|
||||
|
||||
if (blockText.length() < 5) {
|
||||
textMarginLeft = SHORT_TEXT_MARGIN_LEFT;
|
||||
textMarginRight = SHORT_TEXT_MARGIN_RIGHT;
|
||||
} else {
|
||||
textMarginLeft = NORMAL_TEXT_MARGIN_LEFT;
|
||||
textMarginRight = NORMAL_TEXT_MARGIN_RIGHT;
|
||||
}
|
||||
if(bmBlock!=null) {
|
||||
if (widthMode == MeasureSpec.AT_MOST) {
|
||||
// 宽度根据图片大小,字符串长度,各种间隔确定
|
||||
// 高度根据图片大小和上下间隔确定
|
||||
textPaint.getTextBounds(blockText, 0, blockText.length(), textRect);
|
||||
widthSize = BLOCK_START_X * 2 + bmBlock.getWidth() + textMarginLeft + textMarginRight + textRect.width();
|
||||
heightSize = BLOCK_START_Y * 2 + bmBlock.getHeight();
|
||||
widthMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize, widthMode);
|
||||
heightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize, heightMode);
|
||||
}
|
||||
}
|
||||
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
}
|
||||
|
||||
private float textOffset = 0;
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||
super.onSizeChanged(w, h, oldw, oldh);
|
||||
if (bgRectF != null){
|
||||
bgRectF.left = 0;
|
||||
bgRectF.top = 0;
|
||||
bgRectF.right = w;
|
||||
bgRectF.bottom = h;
|
||||
}
|
||||
|
||||
if (matrixAnim != null) {
|
||||
matrixAnim.cancel();
|
||||
}
|
||||
textOffset = (getHeight() - blockTextMetrics.ascent - blockTextMetrics.descent) / 2;
|
||||
matrixAnim = ObjectAnimator.ofFloat(this, "matrixTranslate", 0, w + GRADIENT_OFFSET).setDuration(2000);
|
||||
matrixAnim.setRepeatCount(ValueAnimator.INFINITE);
|
||||
matrixAnim.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
if (matrixAnim != null) {
|
||||
matrixAnim.start();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
if (matrixAnim != null) {
|
||||
matrixAnim.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
float x = event.getX();
|
||||
float y = event.getY();
|
||||
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
if (x > BLOCK_START_X + blockOffset && x < blockWidth + BLOCK_START_X + blockOffset && y > BLOCK_START_Y && y < getHeight() - BLOCK_START_Y) {
|
||||
isToEnd = false;
|
||||
lastX = x;
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
if (lastX != 0) {
|
||||
blockOffset = (int) (x - lastX);
|
||||
if (blockOffset < 0) {
|
||||
blockOffset = 0;
|
||||
}
|
||||
if (blockOffset + BLOCK_START_X + blockWidth > getWidth()) {
|
||||
// 超出右边界
|
||||
blockOffset = getWidth() - BLOCK_START_X - blockWidth;
|
||||
if (!isToEnd) {
|
||||
isToEnd = true;
|
||||
if (moveToEndListener != null) {
|
||||
moveToEndListener.moveToEnd();
|
||||
}
|
||||
startBlockBackAnim();
|
||||
}
|
||||
}
|
||||
invalidate();
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
// 执行滑块回归动画
|
||||
if (!isToEnd) {
|
||||
startBlockBackAnim();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void startBlockBackAnim() {
|
||||
ObjectAnimator blockBackanimator = ObjectAnimator.ofInt(this, "blockOffset", blockOffset, 0);
|
||||
blockBackanimator.setInterpolator(new DecelerateInterpolator());
|
||||
blockBackanimator.setDuration(1000 * blockOffset / getWidth());
|
||||
blockBackanimator.start();
|
||||
lastX = 0;
|
||||
}
|
||||
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
// 画背景
|
||||
canvas.drawRoundRect(bgRectF, (float) getHeight() / 2.0f, (float) getHeight() / 2.0f, bgPaint);
|
||||
// 画文字
|
||||
gradientMatrix.setTranslate(matrixTranslate, 0);
|
||||
textGradient.setLocalMatrix(gradientMatrix);
|
||||
canvas.save();
|
||||
canvas.drawText(blockText, (float) (blockWidth + BLOCK_START_X + textMarginLeft), (float) textOffset, textPaint);
|
||||
canvas.restore();
|
||||
if (bmBlock != null) {
|
||||
if(bmBlock.getByteCount()>=5*1024*1024){
|
||||
OchChainLogManager.writeChainLog("崩溃兜底策略",
|
||||
"图片大小监听"+ ConvertUtils.byte2FitMemorySize(bmBlock.getByteCount()),true,OchChainLogManager.EVENT_KEY_INFE_ERROR);
|
||||
bmBlock.recycle();
|
||||
bmBlock = null;
|
||||
blockWidth = 0;
|
||||
decodeImage();
|
||||
}else {
|
||||
// 画滑块
|
||||
canvas.drawBitmap(bmBlock, (float) (BLOCK_START_X + blockOffset), (float) BLOCK_START_Y, blockPaint);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public interface OnSlidePanelMoveToEndListener {
|
||||
/**
|
||||
* 滑块滑到了末尾
|
||||
*/
|
||||
void moveToEnd();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.mogo.och.offline.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.DashPathEffect;
|
||||
import android.graphics.LinearGradient;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Shader;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* 垂直虚线
|
||||
*
|
||||
* @author tongchenfei
|
||||
*/
|
||||
public class VerticalDashLineView extends View {
|
||||
public VerticalDashLineView(Context context) {
|
||||
this(context,null);
|
||||
}
|
||||
|
||||
public VerticalDashLineView(Context context, @Nullable AttributeSet attrs) {
|
||||
this(context, attrs,0);
|
||||
}
|
||||
|
||||
public VerticalDashLineView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init();
|
||||
}
|
||||
|
||||
private final Paint linePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
private final Path dashPath = new Path();
|
||||
|
||||
private void init(){
|
||||
linePaint.setColor(Color.GREEN);
|
||||
linePaint.setStyle(Paint.Style.STROKE);
|
||||
linePaint.setStrokeWidth(2);
|
||||
linePaint.setPathEffect(new DashPathEffect(new float[]{5, 5}, 0));
|
||||
}
|
||||
|
||||
public void setGradient(int startColor, int endColor) {
|
||||
LinearGradient linearGradient = new LinearGradient(0, 0, getWidth(), getHeight(), startColor, endColor, Shader.TileMode.CLAMP);
|
||||
linePaint.setShader(linearGradient);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void setColor(int color) {
|
||||
linePaint.setShader(null);
|
||||
linePaint.setColor(color);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
dashPath.reset();
|
||||
dashPath.moveTo((float) getWidth()/2, 0);
|
||||
dashPath.lineTo((float) getWidth()/2,getHeight());
|
||||
canvas.drawPath(dashPath,linePaint);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="@color/bus_autopilot_text_color_normal"/>
|
||||
</selector>
|
||||
|
After Width: | Height: | Size: 8.6 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 4.8 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
BIN
OCH/offline/driver/src/main/res/drawable-nodpi/bus_dot_line.png
Normal file
|
After Width: | Height: | Size: 323 B |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 338 B |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 25 KiB |
BIN
OCH/offline/driver/src/main/res/drawable-nodpi/bus_line_panel_bg.png
Executable file
|
After Width: | Height: | Size: 53 KiB |
BIN
OCH/offline/driver/src/main/res/drawable-nodpi/bus_line_panel_bg_1.png
Executable file
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 491 B |
|
After Width: | Height: | Size: 2.5 KiB |
BIN
OCH/offline/driver/src/main/res/drawable-nodpi/bus_no_line_icon.png
Executable file
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 1004 B |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
BIN
OCH/offline/driver/src/main/res/drawable-nodpi/bus_switch_map_long.png
Executable file
|
After Width: | Height: | Size: 5.7 KiB |
BIN
OCH/offline/driver/src/main/res/drawable-nodpi/bus_switch_map_medium.png
Executable file
|
After Width: | Height: | Size: 5.4 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
BIN
OCH/offline/driver/src/main/res/drawable-nodpi/end_maker_icon.png
Executable file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
OCH/offline/driver/src/main/res/drawable-nodpi/icon_ai_collect.png
Executable file
|
After Width: | Height: | Size: 7.4 KiB |
BIN
OCH/offline/driver/src/main/res/drawable-nodpi/icon_ai_normal.png
Executable file
|
After Width: | Height: | Size: 4.7 KiB |
BIN
OCH/offline/driver/src/main/res/drawable-nodpi/icon_ai_select.png
Executable file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
OCH/offline/driver/src/main/res/drawable-nodpi/icon_arrow_blue_bus.png
Executable file
|
After Width: | Height: | Size: 377 B |
BIN
OCH/offline/driver/src/main/res/drawable-nodpi/icon_arrow_green_bus.png
Executable file
|
After Width: | Height: | Size: 400 B |
BIN
OCH/offline/driver/src/main/res/drawable-nodpi/icon_arrow_grey_bus.png
Executable file
|
After Width: | Height: | Size: 402 B |
BIN
OCH/offline/driver/src/main/res/drawable-nodpi/icon_bad_case.png
Executable file
|
After Width: | Height: | Size: 6.9 KiB |
BIN
OCH/offline/driver/src/main/res/drawable-nodpi/icon_bad_case_normal.png
Executable file
|
After Width: | Height: | Size: 6.9 KiB |
BIN
OCH/offline/driver/src/main/res/drawable-nodpi/icon_bad_case_select.png
Executable file
|
After Width: | Height: | Size: 6.7 KiB |
BIN
OCH/offline/driver/src/main/res/drawable-nodpi/icon_no_bus_line.png
Executable file
|
After Width: | Height: | Size: 13 KiB |
BIN
OCH/offline/driver/src/main/res/drawable-nodpi/icon_point_blue_bus.png
Executable file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
OCH/offline/driver/src/main/res/drawable-nodpi/icon_point_green_bus.png
Executable file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
OCH/offline/driver/src/main/res/drawable-nodpi/icon_point_grey_bus.png
Executable file
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 100 KiB |
BIN
OCH/offline/driver/src/main/res/drawable-nodpi/no_order_data.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 102 KiB |
BIN
OCH/offline/driver/src/main/res/drawable-nodpi/press_start_status.png
Executable file
|
After Width: | Height: | Size: 15 KiB |
BIN
OCH/offline/driver/src/main/res/drawable-nodpi/shuttle_write_off_bg.png
Executable file
|
After Width: | Height: | Size: 19 KiB |