<lambda>null1 package `fun`.upup.musicfree.lyricUtil
2
3 import android.app.Activity
4 import android.content.Context
5 import android.graphics.Color
6 import android.graphics.PixelFormat
7 import android.graphics.drawable.ColorDrawable
8 import android.hardware.SensorManager
9 import android.os.Build
10 import android.util.DisplayMetrics
11 import android.util.Log
12 import android.view.Gravity
13 import android.view.MotionEvent
14 import android.view.OrientationEventListener
15 import android.view.View
16 import android.view.WindowManager
17 import android.widget.TextView
18 import com.facebook.react.bridge.ReactContext
19
20
21
22 class LyricView(private val reactContext: ReactContext) : Activity(), View.OnTouchListener {
23
24 private var windowManager: WindowManager? = null
25 private var orientationEventListener: OrientationEventListener? = null
26 private var layoutParams: WindowManager.LayoutParams? = null
27 private var tv: TextView? = null
28
29 // 窗口信息
30 private var windowWidth = 0.0
31 private var windowHeight = 0.0
32 private var widthPercent = 0.0
33 private var leftPercent = 0.0
34 private var topPercent = 0.0
35
36 override fun onTouch(view: View, motionEvent: MotionEvent): Boolean {
37 Log.d("touch", "Desktop Touch")
38 return false
39 }
40
41 // 展示歌词窗口
42 fun showLyricWindow(initText: String?, options: Map<String, Any>) {
43 try {
44 if (windowManager == null) {
45 windowManager = reactContext.getSystemService(WINDOW_SERVICE) as WindowManager
46 layoutParams = WindowManager.LayoutParams()
47
48 val outMetrics = DisplayMetrics()
49 windowManager?.defaultDisplay?.getMetrics(outMetrics)
50 windowWidth = outMetrics.widthPixels.toDouble()
51 windowHeight = outMetrics.heightPixels.toDouble()
52
53 layoutParams?.type = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
54 WindowManager.LayoutParams.TYPE_SYSTEM_ALERT
55 else
56 WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
57
58 /*
59 * topPercent: number;
60 * leftPercent: number;
61 * align: number;
62 * color: string;
63 * backgroundColor: string;
64 * widthPercent: number;
65 * fontSize: number;
66 */
67 val topPercent = options["topPercent"]
68 val leftPercent = options["leftPercent"]
69 val align = options["align"]
70 val color = options["color"]
71 val backgroundColor = options["backgroundColor"]
72 val widthPercent = options["widthPercent"]
73 val fontSize = options["fontSize"]
74
75 this.widthPercent = widthPercent?.toString()?.toDouble() ?: 0.5
76
77 layoutParams?.width = (this.widthPercent * windowWidth).toInt()
78 layoutParams?.height = WindowManager.LayoutParams.WRAP_CONTENT
79 layoutParams?.gravity = Gravity.TOP or Gravity.START
80
81 this.leftPercent = leftPercent?.toString()?.toDouble() ?: 0.5
82 layoutParams?.x = (this.leftPercent * (windowWidth - layoutParams!!.width)).toInt()
83 layoutParams?.y = 0
84
85 layoutParams?.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or
86 WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or
87 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN or
88 WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS or
89 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
90
91 layoutParams?.format = PixelFormat.TRANSPARENT
92
93 tv = TextView(reactContext).apply {
94 text = initText ?: ""
95 textSize = fontSize?.toString()?.toFloat() ?: 14f
96 setBackgroundColor(Color.parseColor(rgba2argb(backgroundColor?.toString() ?: "#84888153")))
97 setTextColor(Color.parseColor(rgba2argb(color?.toString() ?: "#FFE9D2")))
98 setPadding(12, 6, 12, 6)
99 gravity = align?.toString()?.toInt() ?: Gravity.CENTER
100 }
101 windowManager?.addView(tv, layoutParams)
102
103 topPercent?.toString()?.toDouble()?.let { setTopPercent(it) }
104
105 listenOrientationChange()
106 }
107 } catch (e: Exception) {
108 hideLyricWindow()
109 throw e
110 }
111 }
112
113 private fun listenOrientationChange() {
114 if (windowManager == null) return
115
116 if (orientationEventListener == null) {
117 orientationEventListener = object : OrientationEventListener(reactContext, SensorManager.SENSOR_DELAY_NORMAL) {
118 override fun onOrientationChanged(orientation: Int) {
119 if (windowManager != null) {
120 val outMetrics = DisplayMetrics()
121 windowManager?.defaultDisplay?.getMetrics(outMetrics)
122 windowWidth = outMetrics.widthPixels.toDouble()
123 windowHeight = outMetrics.heightPixels.toDouble()
124 layoutParams?.width = (widthPercent * windowWidth).toInt()
125 layoutParams?.x = (leftPercent * (windowWidth - layoutParams!!.width)).toInt()
126 layoutParams?.y = (topPercent * (windowHeight - tv!!.height)).toInt()
127 windowManager?.updateViewLayout(tv, layoutParams)
128 }
129 }
130 }
131 }
132
133 if (orientationEventListener?.canDetectOrientation() == true) {
134 orientationEventListener?.enable()
135 }
136 }
137
138 private fun unlistenOrientationChange() {
139 orientationEventListener?.disable()
140 }
141
142 private fun rgba2argb(color: String): String {
143 return if (color.length == 9) {
144 color[0] + color.substring(7, 9) + color.substring(1, 7)
145 } else {
146 color
147 }
148 }
149
150 // 隐藏歌词窗口
151 fun hideLyricWindow() {
152 if (windowManager != null) {
153 tv?.let {
154 try {
155 windowManager?.removeView(it)
156 } catch (e: Exception) {
157 // Handle exception
158 }
159 tv = null
160 }
161 windowManager = null
162 layoutParams = null
163 unlistenOrientationChange()
164 }
165 }
166
167 // 设置歌词内容
168 fun setText(text: String) {
169 tv?.text = text
170 }
171
172 fun setAlign(gravity: Int) {
173 tv?.gravity = gravity
174 }
175
176 fun setTopPercent(pct: Double) {
177 var percent = pct.coerceIn(0.0, 1.0)
178 tv?.let {
179 layoutParams?.y = (percent * (windowHeight - it.height)).toInt()
180 windowManager?.updateViewLayout(it, layoutParams)
181 }
182 this.topPercent = percent
183 }
184
185 fun setLeftPercent(pct: Double) {
186 var percent = pct.coerceIn(0.0, 1.0)
187 tv?.let {
188 layoutParams?.x = (percent * (windowWidth - layoutParams!!.width)).toInt()
189 windowManager?.updateViewLayout(it, layoutParams)
190 }
191 this.leftPercent = percent
192 }
193
194 fun setColors(textColor: String?, backgroundColor: String?) {
195 tv?.let {
196 textColor?.let { color -> it.setTextColor(Color.parseColor(rgba2argb(color))) }
197 backgroundColor?.let { color ->
198 it.background = ColorDrawable(Color.parseColor(rgba2argb(color)))
199 }
200 }
201 }
202
203 fun setWidth(pct: Double) {
204 var percent = pct.coerceIn(0.3, 1.0)
205 tv?.let {
206 val width = (percent * windowWidth).toInt()
207 val originalWidth = layoutParams?.width ?: 0
208 layoutParams?.x = if (width <= originalWidth) {
209 layoutParams!!.x + (originalWidth - width) / 2
210 } else {
211 layoutParams!!.x - (width - originalWidth) / 2
212 }.coerceAtLeast(0).coerceAtMost((windowWidth - width).toInt())
213 layoutParams?.width = width
214 windowManager?.updateViewLayout(it, layoutParams)
215 }
216 this.widthPercent = percent
217 }
218
219 fun setFontSize(fontSize: Float) {
220 tv?.textSize = fontSize
221 }
222 }