diff --git a/app/src/main/java/com/casic/detector/view/MainActivity.kt b/app/src/main/java/com/casic/detector/view/MainActivity.kt index a4540ca..3d12803 100644 --- a/app/src/main/java/com/casic/detector/view/MainActivity.kt +++ b/app/src/main/java/com/casic/detector/view/MainActivity.kt @@ -135,7 +135,7 @@ /***inner class 需要用到*****start*/ private val taskViewModel by lazy { ViewModelProvider(this)[TaskViewModel::class.java] } private val attr = AudioAttributes.Builder() - .setUsage(AudioAttributes.USAGE_MEDIA) + .setUsage(AudioAttributes.USAGE_ALARM) .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .build() private val soundPool = SoundPool.Builder().setMaxStreams(16).setAudioAttributes(attr).build() @@ -361,8 +361,8 @@ /** * 改为Dialog方式,避免频繁打开/关闭串口 * */ -// searchDialog.show() - searchNewDialog.show() + searchDialog.show() +// searchNewDialog.show() } //自由巡检 @@ -842,6 +842,7 @@ private val calendar by lazy { Calendar.getInstance() } private val realPaths = ArrayList() //真实图片路径 private lateinit var imageAdapter: EditableImageAdapter + private lateinit var countDownTimer: CountDownTimer var isReadMarker = false var isInstallMarker = false @@ -849,8 +850,6 @@ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) this.initDialogLayoutParams(1f) - setCancelable(false) - setCanceledOnTouchOutside(false) //初始化数据 initDefaultData() @@ -992,6 +991,25 @@ out.write('2'.code) out.flush() + + countDownTimer = object : CountDownTimer(5 * 1000, 1000) { + override fun onTick(millisUntilFinished: Long) { + + } + + override fun onFinish() { + LoadingDialogHub.dismiss() + soundPool.autoPause() + binding.readMarkerButton.isEnabled = true + + //降低串口电位 + gpioManager.setGpioLow("18") + + isReadMarker = false + "读取此标识器ID超时,请重试".show(context) + } + } + countDownTimer.start() } } @@ -1007,6 +1025,13 @@ binding.identifierInclude.identifierIdView.text = markerId } + override fun dismiss() { + //降低串口电位 + gpioManager.setGpioLow("18") + soundPool.autoPause() + super.dismiss() + } + private fun initDefaultData() { binding.titleInclude.titleView.text = "安装新标识器" binding.titleInclude.titleView.setTextColor(R.color.themeColor.convertColor(context)) diff --git a/app/src/main/java/com/casic/detector/view/MainActivity.kt b/app/src/main/java/com/casic/detector/view/MainActivity.kt index a4540ca..3d12803 100644 --- a/app/src/main/java/com/casic/detector/view/MainActivity.kt +++ b/app/src/main/java/com/casic/detector/view/MainActivity.kt @@ -135,7 +135,7 @@ /***inner class 需要用到*****start*/ private val taskViewModel by lazy { ViewModelProvider(this)[TaskViewModel::class.java] } private val attr = AudioAttributes.Builder() - .setUsage(AudioAttributes.USAGE_MEDIA) + .setUsage(AudioAttributes.USAGE_ALARM) .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .build() private val soundPool = SoundPool.Builder().setMaxStreams(16).setAudioAttributes(attr).build() @@ -361,8 +361,8 @@ /** * 改为Dialog方式,避免频繁打开/关闭串口 * */ -// searchDialog.show() - searchNewDialog.show() + searchDialog.show() +// searchNewDialog.show() } //自由巡检 @@ -842,6 +842,7 @@ private val calendar by lazy { Calendar.getInstance() } private val realPaths = ArrayList() //真实图片路径 private lateinit var imageAdapter: EditableImageAdapter + private lateinit var countDownTimer: CountDownTimer var isReadMarker = false var isInstallMarker = false @@ -849,8 +850,6 @@ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) this.initDialogLayoutParams(1f) - setCancelable(false) - setCanceledOnTouchOutside(false) //初始化数据 initDefaultData() @@ -992,6 +991,25 @@ out.write('2'.code) out.flush() + + countDownTimer = object : CountDownTimer(5 * 1000, 1000) { + override fun onTick(millisUntilFinished: Long) { + + } + + override fun onFinish() { + LoadingDialogHub.dismiss() + soundPool.autoPause() + binding.readMarkerButton.isEnabled = true + + //降低串口电位 + gpioManager.setGpioLow("18") + + isReadMarker = false + "读取此标识器ID超时,请重试".show(context) + } + } + countDownTimer.start() } } @@ -1007,6 +1025,13 @@ binding.identifierInclude.identifierIdView.text = markerId } + override fun dismiss() { + //降低串口电位 + gpioManager.setGpioLow("18") + soundPool.autoPause() + super.dismiss() + } + private fun initDefaultData() { binding.titleInclude.titleView.text = "安装新标识器" binding.titleInclude.titleView.setTextColor(R.color.themeColor.convertColor(context)) diff --git a/app/src/main/java/com/casic/detector/widgets/RadarScanView.kt b/app/src/main/java/com/casic/detector/widgets/RadarScanView.kt index ff29bdf..a4e18fe 100644 --- a/app/src/main/java/com/casic/detector/widgets/RadarScanView.kt +++ b/app/src/main/java/com/casic/detector/widgets/RadarScanView.kt @@ -5,12 +5,18 @@ import android.graphics.Color import android.graphics.Matrix import android.graphics.Paint +import android.graphics.Path import android.graphics.PointF +import android.graphics.Rect +import android.graphics.RectF import android.graphics.SweepGradient +import android.graphics.Typeface +import android.text.TextPaint import android.util.AttributeSet import android.view.View import com.casic.detector.R import com.pengxh.kt.lite.extensions.dp2px +import com.pengxh.kt.lite.extensions.sp2px import kotlin.math.cos import kotlin.math.sin @@ -31,6 +37,13 @@ //最外层圆半径 private var radius: Int + //内圆文字路径半径 + private var innerRadius: Int + + //控件边长 + private val viewSideLength: Int + private val rect: Rect + //需要渲染的数据点集合 private val points = ArrayList() @@ -43,9 +56,12 @@ //雷达扫描角度步长 private var degrees = 0f + private lateinit var tickPaint: Paint private lateinit var borderPaint: Paint private lateinit var shaderPaint: Paint private lateinit var dataPaint: Paint + private lateinit var innerPaint: TextPaint + private lateinit var innerTextPath: Path //雷达扫描线后面的渐变梯度 private lateinit var sweepGradient: SweepGradient @@ -58,9 +74,16 @@ borderColor = type.getColor(R.styleable.RadarScanView_radar_borderColor, Color.GRAY) border = type.getDimensionPixelOffset(R.styleable.RadarScanView_radar_border, 1) circleCount = type.getInt(R.styleable.RadarScanView_radar_circleCount, 4) - radius = type.getDimensionPixelOffset(R.styleable.RadarScanView_radar_radius, 150) + radius = type.getDimensionPixelOffset(R.styleable.RadarScanView_radar_radius, 300) type.recycle() + innerRadius = radius - 10.dp2px(context) + + //需要给外围刻度留位置 + viewSideLength = radius + 30.dp2px(context) + //辅助框 + rect = Rect(-viewSideLength, -viewSideLength, viewSideLength, viewSideLength) + initPaint() //控制转动 @@ -83,6 +106,12 @@ } private fun initPaint() { + tickPaint = Paint() + tickPaint.color = Color.RED + tickPaint.style = Paint.Style.STROKE + tickPaint.strokeWidth = 2f.dp2px(context) + tickPaint.isAntiAlias = true + borderPaint = Paint() borderPaint.color = borderColor borderPaint.style = Paint.Style.STROKE @@ -90,6 +119,19 @@ borderPaint.strokeCap = Paint.Cap.ROUND //圆头 borderPaint.isAntiAlias = true + innerPaint = TextPaint() + innerPaint.isAntiAlias = true + innerPaint.textAlign = Paint.Align.CENTER + innerPaint.textSize = 14f.sp2px(context) + innerTextPath = Path() + val innerRectF = RectF( + -innerRadius.toFloat(), + -innerRadius.toFloat(), + innerRadius.toFloat(), + innerRadius.toFloat() + ) + innerTextPath.addArc(innerRectF, -90f, 360f) + //扫描线画笔 shaderPaint = Paint() shaderPaint.isAntiAlias = true @@ -114,16 +156,40 @@ centerY = (h shr 1).toFloat() } + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec) + val widthSpecMode = MeasureSpec.getMode(widthMeasureSpec) + val widthSpecSize = MeasureSpec.getSize(widthMeasureSpec) + val heightSpecMode = MeasureSpec.getMode(heightMeasureSpec) + val heightSpecSize = MeasureSpec.getSize(heightMeasureSpec) + // 获取宽 + val mWidth: Int = if (widthSpecMode == MeasureSpec.EXACTLY) { + // match_parent/精确值 + widthSpecSize + } else { + // wrap_content,外边界宽 + (viewSideLength * 2) + } + // 获取高 + val mHeight: Int = if (heightSpecMode == MeasureSpec.EXACTLY) { + // match_parent/精确值 + heightSpecSize + } else { + // wrap_content,外边界高 + (viewSideLength * 2) + } + // 设置该view的宽高 + setMeasuredDimension(mWidth, mHeight) + } + override fun onDraw(canvas: Canvas) { super.onDraw(canvas) /** * 画布移到中心位置,方便绘制一系列图形 */ canvas.translate(centerX, centerY) - /** - * 上下翻转画布,因为手机等设备Y轴和生活中的坐标轴Y轴是反的 - * */ - canvas.scale(1f, -1f) + +// drawGuides(canvas) //每道同心圆的半径差 var tempR = radius @@ -137,17 +203,80 @@ canvas.drawLine(0f, -radius.toFloat(), 0f, radius.toFloat(), borderPaint) canvas.drawLine(-radius.toFloat(), 0f, radius.toFloat(), 0f, borderPaint) + //画方位 + for (angle in 0 until 360 step 90) { + //角度需要转为弧度 + val radians = (angle - 180) * (Math.PI / 180) + + val hOffset = innerRadius * radians + + var direction = "" + when (angle) { + 0 -> { + direction = "北" + innerPaint.color = Color.RED + innerPaint.typeface = Typeface.DEFAULT_BOLD + } + + 90 -> { + direction = "东" + innerPaint.color = Color.BLACK + innerPaint.typeface = Typeface.DEFAULT + } + + 180 -> { + direction = "南" + innerPaint.color = Color.BLACK + innerPaint.typeface = Typeface.DEFAULT + } + + 270 -> { + direction = "西" + innerPaint.color = Color.BLACK + innerPaint.typeface = Typeface.DEFAULT + } + } + + val fontMetrics = innerPaint.fontMetrics + val top = fontMetrics.top //基线到字体上边框的距离,即上图中的top + val bottom = fontMetrics.bottom //基线到字体下边框的距离,即上图中的bottom + val fontHeight = top + bottom + canvas.drawTextOnPath( + direction, + innerTextPath, + hOffset.toFloat(), + -fontHeight / 2, + innerPaint + ) + } + //画数据点 points.forEach { canvas.drawCircle(it.x, it.y, 10f, dataPaint) } + /** + * 上下翻转画布,否则矩阵旋转是逆时针,因为手机等设备Y轴和生活中的坐标轴Y轴是反的 + * */ + canvas.scale(1f, -1f) + //关联矩阵 canvas.concat(matrix) canvas.drawCircle(0f, 0f, radius.toFloat(), shaderPaint) } /** + * 辅助线 + * */ + private fun drawGuides(canvas: Canvas) { + //最外层方框,即自定义View的边界 + canvas.drawRect(rect, tickPaint) + + //内层表盘方向文字基准线 + canvas.drawPath(innerTextPath, tickPaint) + } + + /** * 数据点 * @param dataPoints 数据点集合 * */ diff --git a/app/src/main/java/com/casic/detector/view/MainActivity.kt b/app/src/main/java/com/casic/detector/view/MainActivity.kt index a4540ca..3d12803 100644 --- a/app/src/main/java/com/casic/detector/view/MainActivity.kt +++ b/app/src/main/java/com/casic/detector/view/MainActivity.kt @@ -135,7 +135,7 @@ /***inner class 需要用到*****start*/ private val taskViewModel by lazy { ViewModelProvider(this)[TaskViewModel::class.java] } private val attr = AudioAttributes.Builder() - .setUsage(AudioAttributes.USAGE_MEDIA) + .setUsage(AudioAttributes.USAGE_ALARM) .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .build() private val soundPool = SoundPool.Builder().setMaxStreams(16).setAudioAttributes(attr).build() @@ -361,8 +361,8 @@ /** * 改为Dialog方式,避免频繁打开/关闭串口 * */ -// searchDialog.show() - searchNewDialog.show() + searchDialog.show() +// searchNewDialog.show() } //自由巡检 @@ -842,6 +842,7 @@ private val calendar by lazy { Calendar.getInstance() } private val realPaths = ArrayList() //真实图片路径 private lateinit var imageAdapter: EditableImageAdapter + private lateinit var countDownTimer: CountDownTimer var isReadMarker = false var isInstallMarker = false @@ -849,8 +850,6 @@ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) this.initDialogLayoutParams(1f) - setCancelable(false) - setCanceledOnTouchOutside(false) //初始化数据 initDefaultData() @@ -992,6 +991,25 @@ out.write('2'.code) out.flush() + + countDownTimer = object : CountDownTimer(5 * 1000, 1000) { + override fun onTick(millisUntilFinished: Long) { + + } + + override fun onFinish() { + LoadingDialogHub.dismiss() + soundPool.autoPause() + binding.readMarkerButton.isEnabled = true + + //降低串口电位 + gpioManager.setGpioLow("18") + + isReadMarker = false + "读取此标识器ID超时,请重试".show(context) + } + } + countDownTimer.start() } } @@ -1007,6 +1025,13 @@ binding.identifierInclude.identifierIdView.text = markerId } + override fun dismiss() { + //降低串口电位 + gpioManager.setGpioLow("18") + soundPool.autoPause() + super.dismiss() + } + private fun initDefaultData() { binding.titleInclude.titleView.text = "安装新标识器" binding.titleInclude.titleView.setTextColor(R.color.themeColor.convertColor(context)) diff --git a/app/src/main/java/com/casic/detector/widgets/RadarScanView.kt b/app/src/main/java/com/casic/detector/widgets/RadarScanView.kt index ff29bdf..a4e18fe 100644 --- a/app/src/main/java/com/casic/detector/widgets/RadarScanView.kt +++ b/app/src/main/java/com/casic/detector/widgets/RadarScanView.kt @@ -5,12 +5,18 @@ import android.graphics.Color import android.graphics.Matrix import android.graphics.Paint +import android.graphics.Path import android.graphics.PointF +import android.graphics.Rect +import android.graphics.RectF import android.graphics.SweepGradient +import android.graphics.Typeface +import android.text.TextPaint import android.util.AttributeSet import android.view.View import com.casic.detector.R import com.pengxh.kt.lite.extensions.dp2px +import com.pengxh.kt.lite.extensions.sp2px import kotlin.math.cos import kotlin.math.sin @@ -31,6 +37,13 @@ //最外层圆半径 private var radius: Int + //内圆文字路径半径 + private var innerRadius: Int + + //控件边长 + private val viewSideLength: Int + private val rect: Rect + //需要渲染的数据点集合 private val points = ArrayList() @@ -43,9 +56,12 @@ //雷达扫描角度步长 private var degrees = 0f + private lateinit var tickPaint: Paint private lateinit var borderPaint: Paint private lateinit var shaderPaint: Paint private lateinit var dataPaint: Paint + private lateinit var innerPaint: TextPaint + private lateinit var innerTextPath: Path //雷达扫描线后面的渐变梯度 private lateinit var sweepGradient: SweepGradient @@ -58,9 +74,16 @@ borderColor = type.getColor(R.styleable.RadarScanView_radar_borderColor, Color.GRAY) border = type.getDimensionPixelOffset(R.styleable.RadarScanView_radar_border, 1) circleCount = type.getInt(R.styleable.RadarScanView_radar_circleCount, 4) - radius = type.getDimensionPixelOffset(R.styleable.RadarScanView_radar_radius, 150) + radius = type.getDimensionPixelOffset(R.styleable.RadarScanView_radar_radius, 300) type.recycle() + innerRadius = radius - 10.dp2px(context) + + //需要给外围刻度留位置 + viewSideLength = radius + 30.dp2px(context) + //辅助框 + rect = Rect(-viewSideLength, -viewSideLength, viewSideLength, viewSideLength) + initPaint() //控制转动 @@ -83,6 +106,12 @@ } private fun initPaint() { + tickPaint = Paint() + tickPaint.color = Color.RED + tickPaint.style = Paint.Style.STROKE + tickPaint.strokeWidth = 2f.dp2px(context) + tickPaint.isAntiAlias = true + borderPaint = Paint() borderPaint.color = borderColor borderPaint.style = Paint.Style.STROKE @@ -90,6 +119,19 @@ borderPaint.strokeCap = Paint.Cap.ROUND //圆头 borderPaint.isAntiAlias = true + innerPaint = TextPaint() + innerPaint.isAntiAlias = true + innerPaint.textAlign = Paint.Align.CENTER + innerPaint.textSize = 14f.sp2px(context) + innerTextPath = Path() + val innerRectF = RectF( + -innerRadius.toFloat(), + -innerRadius.toFloat(), + innerRadius.toFloat(), + innerRadius.toFloat() + ) + innerTextPath.addArc(innerRectF, -90f, 360f) + //扫描线画笔 shaderPaint = Paint() shaderPaint.isAntiAlias = true @@ -114,16 +156,40 @@ centerY = (h shr 1).toFloat() } + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec) + val widthSpecMode = MeasureSpec.getMode(widthMeasureSpec) + val widthSpecSize = MeasureSpec.getSize(widthMeasureSpec) + val heightSpecMode = MeasureSpec.getMode(heightMeasureSpec) + val heightSpecSize = MeasureSpec.getSize(heightMeasureSpec) + // 获取宽 + val mWidth: Int = if (widthSpecMode == MeasureSpec.EXACTLY) { + // match_parent/精确值 + widthSpecSize + } else { + // wrap_content,外边界宽 + (viewSideLength * 2) + } + // 获取高 + val mHeight: Int = if (heightSpecMode == MeasureSpec.EXACTLY) { + // match_parent/精确值 + heightSpecSize + } else { + // wrap_content,外边界高 + (viewSideLength * 2) + } + // 设置该view的宽高 + setMeasuredDimension(mWidth, mHeight) + } + override fun onDraw(canvas: Canvas) { super.onDraw(canvas) /** * 画布移到中心位置,方便绘制一系列图形 */ canvas.translate(centerX, centerY) - /** - * 上下翻转画布,因为手机等设备Y轴和生活中的坐标轴Y轴是反的 - * */ - canvas.scale(1f, -1f) + +// drawGuides(canvas) //每道同心圆的半径差 var tempR = radius @@ -137,17 +203,80 @@ canvas.drawLine(0f, -radius.toFloat(), 0f, radius.toFloat(), borderPaint) canvas.drawLine(-radius.toFloat(), 0f, radius.toFloat(), 0f, borderPaint) + //画方位 + for (angle in 0 until 360 step 90) { + //角度需要转为弧度 + val radians = (angle - 180) * (Math.PI / 180) + + val hOffset = innerRadius * radians + + var direction = "" + when (angle) { + 0 -> { + direction = "北" + innerPaint.color = Color.RED + innerPaint.typeface = Typeface.DEFAULT_BOLD + } + + 90 -> { + direction = "东" + innerPaint.color = Color.BLACK + innerPaint.typeface = Typeface.DEFAULT + } + + 180 -> { + direction = "南" + innerPaint.color = Color.BLACK + innerPaint.typeface = Typeface.DEFAULT + } + + 270 -> { + direction = "西" + innerPaint.color = Color.BLACK + innerPaint.typeface = Typeface.DEFAULT + } + } + + val fontMetrics = innerPaint.fontMetrics + val top = fontMetrics.top //基线到字体上边框的距离,即上图中的top + val bottom = fontMetrics.bottom //基线到字体下边框的距离,即上图中的bottom + val fontHeight = top + bottom + canvas.drawTextOnPath( + direction, + innerTextPath, + hOffset.toFloat(), + -fontHeight / 2, + innerPaint + ) + } + //画数据点 points.forEach { canvas.drawCircle(it.x, it.y, 10f, dataPaint) } + /** + * 上下翻转画布,否则矩阵旋转是逆时针,因为手机等设备Y轴和生活中的坐标轴Y轴是反的 + * */ + canvas.scale(1f, -1f) + //关联矩阵 canvas.concat(matrix) canvas.drawCircle(0f, 0f, radius.toFloat(), shaderPaint) } /** + * 辅助线 + * */ + private fun drawGuides(canvas: Canvas) { + //最外层方框,即自定义View的边界 + canvas.drawRect(rect, tickPaint) + + //内层表盘方向文字基准线 + canvas.drawPath(innerTextPath, tickPaint) + } + + /** * 数据点 * @param dataPoints 数据点集合 * */ diff --git a/app/src/main/res/layout/dialog_search_marker_new.xml b/app/src/main/res/layout/dialog_search_marker_new.xml index 0ea108e..ee4628a 100644 --- a/app/src/main/res/layout/dialog_search_marker_new.xml +++ b/app/src/main/res/layout/dialog_search_marker_new.xml @@ -28,7 +28,7 @@ android:layout_height="0dp" android:layout_weight="1" app:radar_border="@dimen/dp_1" - app:radar_borderColor="#BF008B00" + app:radar_borderColor="#BF8D1717" app:radar_circleCount="4" app:radar_radius="@dimen/dp_125" />