[3.3.0][M1] 360环视需求代码提交
This commit is contained in:
@@ -3,7 +3,10 @@ package com.mogo.eagle.core.function.hmi.ui
|
||||
import android.content.Context
|
||||
import android.text.TextUtils
|
||||
import android.util.*
|
||||
import android.view.ViewGroup
|
||||
import android.view.*
|
||||
import android.view.ViewGroup.LayoutParams
|
||||
import android.widget.FrameLayout
|
||||
import androidx.core.view.*
|
||||
import androidx.lifecycle.ProcessLifecycleOwner
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
@@ -22,9 +25,10 @@ import com.mogo.eagle.core.data.biz.notice.NoticeNormalData
|
||||
import com.mogo.eagle.core.data.biz.notice.NoticeTrafficStylePushData
|
||||
import com.mogo.eagle.core.function.api.hmi.warning.IMoGoHmiProvider
|
||||
import com.mogo.eagle.core.function.api.hmi.warning.IMoGoWarningStatusListener
|
||||
import com.mogo.eagle.core.function.call.hmi.CallerHmiViewControlListenerManager
|
||||
import com.mogo.eagle.core.function.call.hmi.*
|
||||
import com.mogo.eagle.core.function.call.v2x.CallerV2XWarningListenerManager
|
||||
import com.mogo.eagle.core.function.hmi.ui.camera.RoadVideoDialog
|
||||
import com.mogo.eagle.core.function.hmi.ui.lookaround.*
|
||||
import com.mogo.eagle.core.function.hmi.ui.notice.DispatchDialogManager
|
||||
import com.mogo.eagle.core.function.hmi.ui.notice.NoticeCheckDialog
|
||||
import com.mogo.eagle.core.function.hmi.ui.notice.traffic.NoticeTrafficDialog
|
||||
@@ -35,15 +39,17 @@ import com.mogo.eagle.core.function.hmi.ui.tools.ModifyBindingCarDialog
|
||||
import com.mogo.eagle.core.function.hmi.ui.tools.ToBindingCarDialog
|
||||
import com.mogo.eagle.core.function.hmi.ui.tools.UpgradeAppDialog
|
||||
import com.mogo.eagle.core.function.hmi.ui.widget.StatusBarView
|
||||
import com.mogo.eagle.core.utilcode.floating.*
|
||||
import com.mogo.eagle.core.utilcode.kotlin.safeCancel
|
||||
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
|
||||
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.mogo.logger.scene.SceneConstant.Companion.M_HMI
|
||||
import com.mogo.eagle.core.utilcode.util.ThreadUtils
|
||||
import com.mogo.eagle.core.utilcode.util.*
|
||||
import com.zhjt.service_biz.BizConfig
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.selects.*
|
||||
import java.lang.ref.WeakReference
|
||||
import java.util.concurrent.atomic.AtomicReference
|
||||
|
||||
/**
|
||||
@@ -62,6 +68,11 @@ class MoGoHmiProvider : IMoGoHmiProvider {
|
||||
private var lastShowV2XJob: Job? = null
|
||||
private var context: Context? = null
|
||||
|
||||
/**
|
||||
* 360环视窗口引用
|
||||
*/
|
||||
private val lookAround by lazy { AtomicReference<MoGoPopWindow>() }
|
||||
|
||||
private val scope by lazy { CoroutineScope(Dispatchers.Default + SupervisorJob()) }
|
||||
|
||||
override fun init(context: Context?) {
|
||||
@@ -312,4 +323,38 @@ class MoGoHmiProvider : IMoGoHmiProvider {
|
||||
}
|
||||
}
|
||||
|
||||
override fun show360LookAround() {
|
||||
val activity = AppStateManager.currentActivity() ?: return
|
||||
val old = lookAround.get()
|
||||
if (old != null && old.isShowing()) {
|
||||
return
|
||||
}
|
||||
old?.hide()
|
||||
MoGoPopWindow.Builder()
|
||||
.attachToActivity(activity)
|
||||
.contentView(M1LookAroundView(activity))
|
||||
.draggable(true)
|
||||
.isDismissOnTouchOutside(false)
|
||||
.gravityInActivity(Gravity.CENTER)
|
||||
.width(700)
|
||||
.height(1400)
|
||||
.onDismissed {
|
||||
lookAround.set(null)
|
||||
}
|
||||
.build().also {
|
||||
lookAround.set(it)
|
||||
}.show()
|
||||
}
|
||||
|
||||
override fun hide360LookAround() {
|
||||
val old = lookAround.get()
|
||||
if (old == null || !old.isShowing()) {
|
||||
return
|
||||
}
|
||||
old.hide()
|
||||
}
|
||||
|
||||
override fun is360LookAroundShowing(): Boolean {
|
||||
return lookAround.get()?.isShowing() ?: false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,347 @@
|
||||
package com.mogo.eagle.core.function.hmi.ui.lookaround
|
||||
|
||||
import android.content.*
|
||||
import android.graphics.*
|
||||
import android.graphics.Paint.Style.STROKE
|
||||
import android.os.Handler
|
||||
import android.os.HandlerThread
|
||||
import android.os.SystemClock
|
||||
import android.util.*
|
||||
import android.view.SurfaceHolder
|
||||
import android.view.SurfaceView
|
||||
import android.widget.Toast
|
||||
import com.mogo.eagle.core.function.api.autopilot.*
|
||||
import com.mogo.eagle.core.function.api.lookaround.data.*
|
||||
import com.mogo.eagle.core.function.call.autopilot.*
|
||||
import com.mogo.eagle.core.function.call.devatools.*
|
||||
import com.mogo.eagle.core.utilcode.kotlin.*
|
||||
import com.mogo.eagle.core.utilcode.util.ThreadUtils
|
||||
import com.mogo.eagle.core.utilcode.util.Utils
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.Runnable
|
||||
import kotlinx.coroutines.flow.*
|
||||
import java.util.concurrent.atomic.AtomicReference
|
||||
import kotlin.math.*
|
||||
|
||||
class M1LookAroundView: SurfaceView, SurfaceHolder.Callback, Runnable, IMoGoChassisSteeringStateListener {
|
||||
|
||||
constructor(context: Context?) : super(context)
|
||||
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
|
||||
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
|
||||
|
||||
companion object {
|
||||
private const val TAG = "M1LookAroundView"
|
||||
|
||||
private const val BROKE_LINE_LENGTH = 40f
|
||||
|
||||
private const val VEHICLE_STEERING_RATIO = 21
|
||||
}
|
||||
|
||||
init {
|
||||
holder.addCallback(this)
|
||||
}
|
||||
|
||||
private val handler by lazy { AtomicReference<Handler>() }
|
||||
|
||||
private val bitmapPaint by lazy { Paint(Paint.ANTI_ALIAS_FLAG or Paint.FILTER_BITMAP_FLAG).also { it.xfermode = null } }
|
||||
|
||||
private val routerPaint = Paint().also {
|
||||
it.color = Color.RED
|
||||
it.isAntiAlias = true
|
||||
it.style = STROKE
|
||||
it.strokeWidth = 5f
|
||||
}
|
||||
|
||||
private val brokePaint = Paint().also {
|
||||
it.color = Color.RED
|
||||
it.isAntiAlias = true
|
||||
it.style = STROKE
|
||||
it.strokeJoin = Paint.Join.ROUND
|
||||
it.strokeWidth = 5f
|
||||
}
|
||||
|
||||
private val brokePath by lazy { Path() }
|
||||
|
||||
private val routerPath = Path()
|
||||
|
||||
private val innerRect by lazy { RectF() }
|
||||
|
||||
private val outerRect by lazy { RectF() }
|
||||
|
||||
/**
|
||||
* 方向盘转角
|
||||
*/
|
||||
@Volatile
|
||||
private var steering: Float = 0f
|
||||
|
||||
@Volatile
|
||||
private var surfaceWidth = 0
|
||||
|
||||
@Volatile
|
||||
private var surfaceHeight = 0
|
||||
|
||||
@Volatile
|
||||
private var isSurfaceValid = false
|
||||
|
||||
@Volatile
|
||||
private var data: LookAroundData? = null
|
||||
|
||||
override fun surfaceCreated(holder: SurfaceHolder?) {
|
||||
val old = handler.get()
|
||||
if (old == null) {
|
||||
handler.set(HandlerThread("look-around-drawer").let { it.start(); Handler(it.looper) })
|
||||
} else {
|
||||
old.looper.quitSafely()
|
||||
handler.set(HandlerThread("look-around-drawer").let { it.start(); Handler(it.looper) })
|
||||
}
|
||||
handler.get()?.removeCallbacks(this)
|
||||
handler.get()?.post(this)
|
||||
isSurfaceValid = true
|
||||
}
|
||||
|
||||
override fun surfaceChanged(holder: SurfaceHolder?, format: Int, width: Int, height: Int) {
|
||||
this.surfaceWidth = width
|
||||
this.surfaceHeight = height
|
||||
}
|
||||
|
||||
override fun surfaceDestroyed(holder: SurfaceHolder?) {
|
||||
isSurfaceValid = false
|
||||
}
|
||||
|
||||
override fun run() {
|
||||
var isTimedBlock = false
|
||||
try {
|
||||
Log.d(TAG, "--- 1 ---")
|
||||
if (!isSurfaceValid) {
|
||||
isTimedBlock = true
|
||||
return
|
||||
}
|
||||
if (this.surfaceWidth <= 0 || this.surfaceHeight <= 0) {
|
||||
Log.d(TAG, "--- 2 ---")
|
||||
isTimedBlock = true
|
||||
return
|
||||
}
|
||||
Log.d(TAG, "--- 3 ---")
|
||||
val data = this.data ?: return
|
||||
val targetX = data.targetX
|
||||
val targetY = data.targetY
|
||||
val targetWidth = data.targetWidth
|
||||
val targetHeight = data.targetHeight
|
||||
val bitmapWidth = data.bitmapWidth
|
||||
val bitmapHeight = data.bitmapHeight
|
||||
val scaleX = this.surfaceWidth * 1.0f / bitmapWidth
|
||||
val scaleY = this.surfaceHeight * 1.0f / bitmapHeight
|
||||
val bytes = data.data
|
||||
if (bytes == null) {
|
||||
isTimedBlock = true
|
||||
Log.d(TAG, "--- 4 ---")
|
||||
return
|
||||
}
|
||||
Log.d(TAG, "--- 5 ---")
|
||||
val canvas = holder.lockCanvas()
|
||||
try {
|
||||
if (canvas == null) {
|
||||
Log.d(TAG, "--- 6 ---")
|
||||
isTimedBlock = true
|
||||
return
|
||||
}
|
||||
//1. 绘制图片
|
||||
var startTime = SystemClock.elapsedRealtime()
|
||||
val bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.size)
|
||||
Log.d(TAG, "--- cost for decode bitmap: ${SystemClock.elapsedRealtime() - startTime}ms.")
|
||||
if (bitmap == null) {
|
||||
Log.d(TAG, "--- 7 ---")
|
||||
isTimedBlock = true
|
||||
return
|
||||
}
|
||||
try {
|
||||
startTime = SystemClock.elapsedRealtime()
|
||||
canvas.save()
|
||||
canvas.scale(scaleX, scaleY)
|
||||
canvas.drawBitmap(bitmap, 0f, 0f, bitmapPaint)
|
||||
} finally {
|
||||
canvas.restore()
|
||||
if (!bitmap.isRecycled) {
|
||||
bitmap.recycle()
|
||||
}
|
||||
Log.d(TAG, "--- draw decoded bitmap cost: ${SystemClock.elapsedRealtime() - startTime}ms.")
|
||||
}
|
||||
//2. 绘制车的信息
|
||||
Log.d(TAG, "--- 8 ---")
|
||||
val newTargetX = targetX * scaleX
|
||||
val newTargetY = targetY * scaleY
|
||||
val newTargetWidth = targetWidth * scaleX
|
||||
val newTargetHeight = targetHeight * scaleY
|
||||
try {
|
||||
//2.1 绘制车前的转向角
|
||||
canvas.save()
|
||||
var steering = this.steering
|
||||
if (abs(steering) < 1) {
|
||||
steering = 0f
|
||||
}
|
||||
if (steering == 0f) {
|
||||
canvas.translate(newTargetX + newTargetWidth * 0.5f, newTargetY)
|
||||
routerPath.reset()
|
||||
val halfX = newTargetWidth * 0.5f
|
||||
var startX = - halfX
|
||||
val startY= 0f
|
||||
routerPath.moveTo(startX, startY)
|
||||
var endX = startX
|
||||
val endY = - newTargetY
|
||||
routerPath.lineTo(endX, endY)
|
||||
canvas.drawPath(routerPath, routerPaint)
|
||||
startX += newTargetWidth
|
||||
endX += newTargetWidth
|
||||
routerPath.reset()
|
||||
routerPath.moveTo(startX, startY)
|
||||
routerPath.lineTo(endX, endY)
|
||||
canvas.drawPath(routerPath, routerPaint)
|
||||
} else {
|
||||
val outerAngle = abs(steering * 1.0 / VEHICLE_STEERING_RATIO)
|
||||
val radians = Math.toRadians(outerAngle)
|
||||
val d = (newTargetHeight / tan(radians)).toFloat()
|
||||
if (steering < 0) {
|
||||
// 左打轮
|
||||
// 将坐标原点平移到圆心
|
||||
canvas.translate(newTargetX - (d - newTargetWidth), newTargetY + newTargetHeight)
|
||||
//外圆半径
|
||||
val outerR = (newTargetHeight / sin(radians)).toFloat()
|
||||
//内圆半径
|
||||
val innerR = sqrt((newTargetHeight * 1.0).pow(2.0) + ((d - newTargetWidth) * 1.0).pow(2.0)).toFloat()
|
||||
val innerAngle = Math.toDegrees(asin(newTargetHeight / innerR) * 1.0)
|
||||
outerRect.set(-outerR, -outerR, outerR, outerR)
|
||||
innerRect.set(-innerR, -innerR, innerR, innerR)
|
||||
canvas.drawArc(outerRect, -outerAngle.toFloat(), -60f, false, routerPaint)
|
||||
canvas.drawArc(innerRect, -innerAngle.toFloat(), -60f, false, routerPaint)
|
||||
}
|
||||
|
||||
if (steering > 0) {
|
||||
//右打轮
|
||||
// 将坐标原点平移到圆心
|
||||
canvas.translate(newTargetX + d, newTargetY + newTargetHeight)
|
||||
//外圆半径
|
||||
val outerR = (newTargetHeight / sin(radians)).toFloat()
|
||||
//内圆半径
|
||||
val innerR = sqrt((newTargetHeight * 1.0).pow(2.0) + ((d - newTargetWidth) * 1.0).pow(2.0)).toFloat()
|
||||
val innerAngle = Math.toDegrees(asin(newTargetHeight / innerR) * 1.0)
|
||||
outerRect.set(-outerR, -outerR, outerR, outerR)
|
||||
innerRect.set(-innerR, -innerR, innerR, innerR)
|
||||
canvas.drawArc(outerRect, 180f + outerAngle.toFloat(), 60f, false, routerPaint)
|
||||
canvas.drawArc(innerRect, 180f + innerAngle.toFloat(), 60f, false, routerPaint)
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
canvas.restore()
|
||||
}
|
||||
|
||||
try {
|
||||
//2.2 绘制车周围盲区标定
|
||||
canvas.save()
|
||||
canvas.translate(newTargetX + newTargetWidth * 0.5f, newTargetY)
|
||||
Log.d(TAG, "--- 9 ---:[$targetX:$newTargetX, $targetY:$newTargetY, $targetWidth:$newTargetWidth, $targetHeight:$newTargetHeight]")
|
||||
val halfTargetWidth = newTargetWidth * 0.5f
|
||||
var startX = -halfTargetWidth
|
||||
var startY = BROKE_LINE_LENGTH
|
||||
var endX = startX
|
||||
var endY = 0f
|
||||
// 绘制左上角
|
||||
brokePath.reset()
|
||||
brokePath.moveTo(startX, startY)
|
||||
brokePath.lineTo(endX, endY)
|
||||
endX += BROKE_LINE_LENGTH
|
||||
brokePath.lineTo(endX, endY)
|
||||
canvas.drawPath(brokePath, brokePaint)
|
||||
|
||||
// 绘制右上角
|
||||
startX = halfTargetWidth - BROKE_LINE_LENGTH
|
||||
startY = 0f
|
||||
|
||||
endX = halfTargetWidth
|
||||
endY = 0f
|
||||
brokePath.reset()
|
||||
brokePath.moveTo(startX, startY)
|
||||
brokePath.lineTo(endX, endY)
|
||||
endY += BROKE_LINE_LENGTH
|
||||
brokePath.lineTo(endX, endY)
|
||||
canvas.drawPath(brokePath, brokePaint)
|
||||
|
||||
//绘制左下角
|
||||
startX = -halfTargetWidth
|
||||
startY = newTargetHeight - BROKE_LINE_LENGTH
|
||||
endX = startX
|
||||
endY = newTargetHeight
|
||||
brokePath.reset()
|
||||
brokePath.moveTo(startX, startY)
|
||||
brokePath.lineTo(endX, endY)
|
||||
endX += BROKE_LINE_LENGTH
|
||||
brokePath.lineTo(endX, endY)
|
||||
canvas.drawPath(brokePath, brokePaint)
|
||||
|
||||
//绘制右下角
|
||||
startX = halfTargetWidth - BROKE_LINE_LENGTH
|
||||
startY = newTargetHeight
|
||||
endX = halfTargetWidth
|
||||
endY = startY
|
||||
brokePath.reset()
|
||||
brokePath.moveTo(startX, startY)
|
||||
brokePath.lineTo(endX, endY)
|
||||
endY -= BROKE_LINE_LENGTH
|
||||
brokePath.lineTo(endX, endY)
|
||||
canvas.drawPath(brokePath, brokePaint)
|
||||
} finally {
|
||||
canvas.restore()
|
||||
}
|
||||
} finally {
|
||||
if (canvas != null) {
|
||||
holder.unlockCanvasAndPost(canvas)
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (isTimedBlock) {
|
||||
try {
|
||||
Thread.sleep(2000)
|
||||
} catch (ignore: Exception) { }
|
||||
}
|
||||
handler.get().post(this)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAttachedToWindow() {
|
||||
super.onAttachedToWindow()
|
||||
CallerChassisSteeringStateListenerManager.addListener(TAG, this)
|
||||
Log.d(TAG, "--- 发起订阅 ---")
|
||||
CallerAutoPilotControlManager.setIsSubscribeM1StitchedVideo(true)
|
||||
scope.launch(ThreadUtils.getCpuPool().asCoroutineDispatcher()) {
|
||||
CallerDevaToolsManager.lookAroundProvider()?.flow()?.also { flow ->
|
||||
flow.onEach {
|
||||
Log.d(TAG, "-- onEach ---:$it")
|
||||
if (it.isValid()) {
|
||||
data = it
|
||||
}
|
||||
}.collect()
|
||||
}
|
||||
}
|
||||
|
||||
// 订阅后,5秒内未收到有效数据, 提示用户当前MAP版本不支持
|
||||
scope.launch {
|
||||
delay(5000)
|
||||
val d = data
|
||||
if (d == null || !d.isValid()) {
|
||||
Toast.makeText(Utils.getApp(), "当前MAP版本不支持360环视,请升级MAP版本", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow()
|
||||
CallerChassisSteeringStateListenerManager.removeListener(TAG)
|
||||
Log.d(TAG, "--- 取消订阅 ---")
|
||||
CallerAutoPilotControlManager.setIsSubscribeM1StitchedVideo(false)
|
||||
handler.get()?.looper?.quitSafely()
|
||||
}
|
||||
|
||||
override fun onAutopilotSteeringData(steering: Float) {
|
||||
Log.d(TAG, "--- onAutopilotSteeringData --: steering: $steering")
|
||||
this.steering = steering
|
||||
}
|
||||
}
|
||||
@@ -223,6 +223,23 @@ internal class SOPSettingView @JvmOverloads constructor(
|
||||
FunctionBuildConfig.isNewV2NData = isChecked
|
||||
}
|
||||
|
||||
// M1 360度环视
|
||||
tbNew360LookAround?.also {
|
||||
if (!AppIdentityModeUtils.isM1(FunctionBuildConfig.appIdentityMode)) {
|
||||
it.isEnabled = false
|
||||
} else {
|
||||
it.isEnabled = true
|
||||
it.setOnCheckedChangeListener { _, isChecked ->
|
||||
if (isChecked) {
|
||||
CallerHmiManager.showM1360LookAround()
|
||||
} else {
|
||||
CallerHmiManager.hidM1360LookAround()
|
||||
}
|
||||
}
|
||||
it.isChecked = CallerHmiManager.isM1360LookAroundShowing()
|
||||
}
|
||||
}
|
||||
|
||||
//变道绕障的目标障碍物速度阈值
|
||||
tvSpeed.text = "${FunctionBuildConfig.detouringSpeed} m/s"
|
||||
ivSpeedReduce.setOnClickListener {
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
package com.mogo.eagle.core.function.hmi.ui.widget;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.widget.AppCompatImageView;
|
||||
|
||||
import com.bumptech.glide.Priority;
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||
import com.bumptech.glide.request.RequestOptions;
|
||||
import com.bumptech.glide.request.target.CustomTarget;
|
||||
import com.bumptech.glide.request.transition.Transition;
|
||||
import com.mogo.eagle.core.function.api.autopilot.IMoGoSweeperFutianBackCameraVideoListener;
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerSweeperFutianBackCameraVideoListenerManager;
|
||||
import com.mogo.eagle.core.utilcode.mogo.glide.GlideApp;
|
||||
import com.mogo.eagle.core.utilcode.util.ThreadUtils;
|
||||
|
||||
/**
|
||||
* 清扫车摄像头展示View
|
||||
*/
|
||||
public class SweeperVideoView extends AppCompatImageView implements IMoGoSweeperFutianBackCameraVideoListener {
|
||||
private static final String TAG = SweeperVideoView.class.getSimpleName();
|
||||
private final RequestOptions requestOptions = new RequestOptions()
|
||||
.priority(Priority.HIGH)
|
||||
.skipMemoryCache(true)
|
||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||
.dontAnimate();
|
||||
|
||||
public SweeperVideoView(@NonNull Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public SweeperVideoView(@NonNull Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public SweeperVideoView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
CallerSweeperFutianBackCameraVideoListenerManager.INSTANCE.addListener(TAG, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
CallerSweeperFutianBackCameraVideoListenerManager.INSTANCE.removeListener(this);
|
||||
}
|
||||
|
||||
private final CustomTarget<Bitmap> target = new CustomTarget<Bitmap>() {
|
||||
@Override
|
||||
public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
|
||||
//回调内容
|
||||
if (!resource.isRecycled()) {
|
||||
SweeperVideoView.this.setImageBitmap(resource);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadCleared(@Nullable Drawable placeholder) {
|
||||
//这个方法在target被回收时调用,如果在除了imageView以外的地方引用了imageView中的bitmap,在这里清除引用以避免崩溃
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onSweeperFutianBackCameraVideo(@NonNull byte[] data) {
|
||||
ThreadUtils.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
GlideApp.with(SweeperVideoView.this)
|
||||
.asBitmap()
|
||||
.load(data)
|
||||
.placeholder(SweeperVideoView.this.getDrawable())
|
||||
.apply(requestOptions)
|
||||
.into(target);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.mogo.eagle.core.function.hmi.ui.widget.MogoVideoView
|
||||
android:id="@+id/mogo_video_view"
|
||||
android:layout_width="0dip"
|
||||
android:layout_height="0dip"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
|
||||
<com.mogo.eagle.core.function.hmi.ui.lookaround.BezierView
|
||||
android:id="@+id/mogo_bezier_view"
|
||||
android:layout_width="0dip"
|
||||
android:layout_height="0dip"
|
||||
android:background="@android:color/transparent"
|
||||
app:layout_constraintTop_toTopOf="@+id/mogo_video_view"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/mogo_video_view"
|
||||
app:layout_constraintStart_toStartOf="@+id/mogo_video_view"
|
||||
app:layout_constraintEnd_toEndOf="@+id/mogo_video_view"/>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -261,6 +261,19 @@
|
||||
app:layout_constraintRight_toLeftOf="@id/verticalGuideLine"
|
||||
/>
|
||||
|
||||
<androidx.appcompat.widget.SwitchCompat
|
||||
android:id="@+id/tbNew360LookAround"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="360环视"
|
||||
android:paddingTop="25dp"
|
||||
android:paddingBottom="25dp"
|
||||
android:scaleY="1.2"
|
||||
android:scaleX="1.2"
|
||||
app:layout_constraintTop_toBottomOf="@id/tbIPCReport"
|
||||
app:layout_constraintLeft_toRightOf="@+id/verticalGuideLine"
|
||||
app:layout_constraintRight_toRightOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvSpeedThresholdTitle"
|
||||
android:layout_width="wrap_content"
|
||||
|
||||
Reference in New Issue
Block a user