From 75d67d249c9439831f786f2ca0b7636c5495e69e Mon Sep 17 00:00:00 2001 From: masonqiao Date: Wed, 15 Jul 2026 17:37:13 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90Room=E3=80=91Add=20screen=20orientatio?= =?UTF-8?q?n=20switching=20support=20for=20screen=20sharing=20in=20room=20?= =?UTF-8?q?scenes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- room/tuiroomkit/src/main/AndroidManifest.xml | 3 +- .../trtc/uikit/roomkit/RoomMainActivity.kt | 22 +++++ .../trtc/uikit/roomkit/view/RoomMainView.kt | 87 +++++++++++++++++- .../main/roomview/PagedVideoLayoutManager.kt | 14 ++- .../roomkit_ic_switch_landscape_button.png | Bin 0 -> 2269 bytes .../roomkit_ic_switch_portrait_button.png | Bin 0 -> 2211 bytes .../src/main/res/layout/roomkit_main_view.xml | 12 +++ 7 files changed, 134 insertions(+), 4 deletions(-) create mode 100644 room/tuiroomkit/src/main/res/drawable-xxhdpi/roomkit_ic_switch_landscape_button.png create mode 100644 room/tuiroomkit/src/main/res/drawable-xxhdpi/roomkit_ic_switch_portrait_button.png diff --git a/room/tuiroomkit/src/main/AndroidManifest.xml b/room/tuiroomkit/src/main/AndroidManifest.xml index db17a847..1959f5f4 100644 --- a/room/tuiroomkit/src/main/AndroidManifest.xml +++ b/room/tuiroomkit/src/main/AndroidManifest.xml @@ -34,8 +34,9 @@ + android:screenOrientation="locked" /> createRoom(roomID, behavior.options) is RoomBehavior.Join -> joinRoom(roomID) } } + override fun onConfigurationChanged(newConfig: Configuration) { + super.onConfigurationChanged(newConfig) + updateOrientationVisibility(newConfig.orientation) + } + override fun initStore(roomID: String) { participantStore = RoomParticipantStore.create(roomID) } @@ -358,6 +374,12 @@ class RoomMainView @JvmOverloads constructor( .distinctUntilChanged() .collect { screenShareOverlayView.updateScreenStatus(it) } } + scope.launch { + participantStore.state.participantWithScreen + .map { it?.userID } + .distinctUntilChanged() + .collect(::onScreenSharerChanged) + } } override fun removeObserver() { @@ -698,6 +720,67 @@ class RoomMainView @JvmOverloads constructor( return AIMinutesActivity.getForegroundInstance() ?: context } + private fun updateOrientationVisibility(orientation: Int) { + val isLandscape = orientation == Configuration.ORIENTATION_LANDSCAPE + topBarView.visibility = if (isLandscape) GONE else VISIBLE + bottomBarView.visibility = if (isLandscape) GONE else VISIBLE + if (isLandscape) aiSubtitleView.visibility = GONE + if (roomType == RoomType.WEBINAR) { + barrageInputView.visibility = if (isLandscape) GONE else VISIBLE + barrageStreamView.visibility = if (isLandscape) GONE else VISIBLE + } + recordingFloatingView.visibility = when { + isLandscape -> GONE + roomStore.state.currentRoom.value?.recordingInfo?.status == RecordingStatus.RECORDING -> VISIBLE + else -> GONE + } + updateOrientationSwitchButtonVisibility(orientation) + } + + private fun updateOrientationSwitchButtonVisibility( + orientation: Int = resources.configuration.orientation + ) { + val hasRemoteSharer = currentScreenSharerID != null && currentScreenSharerID != localUserID + val shouldShow = roomType != RoomType.WEBINAR && hasRemoteSharer + orientationSwitchButton.visibility = if (shouldShow) VISIBLE else GONE + val isLandscape = orientation == Configuration.ORIENTATION_LANDSCAPE + orientationSwitchButton.setImageResource( + if (isLandscape) R.drawable.roomkit_ic_switch_portrait_button + else R.drawable.roomkit_ic_switch_landscape_button + ) + } + + @SuppressLint("SourceLockedOrientationActivity") + private fun switchOrientation() { + val activity = context as? Activity ?: return + val currentlyLandscape = + resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE + activity.requestedOrientation = if (currentlyLandscape) { + ActivityInfo.SCREEN_ORIENTATION_PORTRAIT + } else { + ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE + } + } + + @SuppressLint("SourceLockedOrientationActivity") + private fun forcePortraitIfLandscape() { + val activity = context as? Activity ?: return + if (resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) { + activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT + } + } + + private fun onScreenSharerChanged(newSharerID: String?) { + if (currentScreenSharerID == newSharerID) { + return + } + currentScreenSharerID = newSharerID + updateOrientationSwitchButtonVisibility() + if (newSharerID.isNullOrEmpty()) { + forcePortraitIfLandscape() + } + } + fun isAISubtitleVisible(): Boolean { return aiSubtitleView.visibility == VISIBLE } diff --git a/room/tuiroomkit/src/main/java/com/trtc/uikit/roomkit/view/main/roomview/PagedVideoLayoutManager.kt b/room/tuiroomkit/src/main/java/com/trtc/uikit/roomkit/view/main/roomview/PagedVideoLayoutManager.kt index 939e9cac..e1ce8594 100644 --- a/room/tuiroomkit/src/main/java/com/trtc/uikit/roomkit/view/main/roomview/PagedVideoLayoutManager.kt +++ b/room/tuiroomkit/src/main/java/com/trtc/uikit/roomkit/view/main/roomview/PagedVideoLayoutManager.kt @@ -1,5 +1,6 @@ package com.trtc.uikit.roomkit.view.main.roomview +import android.content.res.Configuration import android.graphics.PointF import android.view.View import android.view.ViewGroup @@ -71,6 +72,7 @@ class PagedVideoLayoutManager( private var scrollState = RecyclerView.SCROLL_STATE_IDLE private var lastSpeakerMode = false + private var attachedRecyclerView: RecyclerView? = null override fun generateDefaultLayoutParams(): RecyclerView.LayoutParams { val params = RecyclerView.LayoutParams( @@ -82,7 +84,11 @@ class PagedVideoLayoutManager( return params } - override fun canScrollHorizontally(): Boolean = true + override fun canScrollHorizontally(): Boolean { + val orientation = attachedRecyclerView?.resources?.configuration?.orientation + ?: Configuration.ORIENTATION_PORTRAIT + return orientation != Configuration.ORIENTATION_LANDSCAPE + } override fun onLayoutChildren(recycler: RecyclerView.Recycler, state: RecyclerView.State) { if (state.isPreLayout) return @@ -118,6 +124,7 @@ class PagedVideoLayoutManager( override fun onAttachedToWindow(view: RecyclerView) { super.onAttachedToWindow(view) cachedAdapter = view.adapter + attachedRecyclerView = view // Listen to scroll state changes view.addOnScrollListener(object : RecyclerView.OnScrollListener() { @@ -127,6 +134,11 @@ class PagedVideoLayoutManager( }) } + override fun onDetachedFromWindow(view: RecyclerView, recycler: RecyclerView.Recycler) { + super.onDetachedFromWindow(view, recycler) + attachedRecyclerView = null + } + /** * Check if speaker mode is active * Speaker mode is ON when first item is screen share stream diff --git a/room/tuiroomkit/src/main/res/drawable-xxhdpi/roomkit_ic_switch_landscape_button.png b/room/tuiroomkit/src/main/res/drawable-xxhdpi/roomkit_ic_switch_landscape_button.png new file mode 100644 index 0000000000000000000000000000000000000000..ab3cc42c3657ed3f3eb83e6f1a498a0ded0dde3b GIT binary patch literal 2269 zcmV<32qO21P)$~kXiO&Y4=|a;olz5YF|3U{ zHKR;23j;AIf{!pIFlYuG9s-3@ptL;Z_q*OUwX|^iqAkoX!SD9o?_TdY-#ORm2Z+3M z-`dpF)RNonUUoX2zKMwm-_p_&&n*YvUs6({HX4oD8jVI(T3VW8Hk-8t1qC@k;2p^f zNXT1^6N!?HxETC@83j~|yr9N4pGk9P0gy*jJanyb_4vgOl0{C|Ig zS^e=cA}$7;J$v>5UgSF=6FxaP>Fw$1am7n?B#;@04jsxjnM@k~_DjT_J9maejEIQ= z7cN{dV3q4}NL^1l;h})KWH&Z87M7Kj>G+$BP^;B{#3Bt*Gaz`?Js!`>^XJcs;a8;sTyE{SC)qUXr7TB&16{j8Vn>pdvI{j{q*TmCsu!1qzGeUV?NlKMT5bh z%FoZ&VH+*4t*sT^-Q5#PpP`rm=gysL!0-(X-23gwtYV8V!!`xP+&E8l{loWwtS_UyC6;qZtw10=x+y;}!WC^>xiaK-D_ zuLm}}Z&L=yD_>51fBg6{w(*ISiTq}mo10suN?_Z}h5wMJL=rY+09Ky*et^V3dGh2l zoR<}m=AcTD33j_(4^OlhlAwVkj7FLtkpZ;!7^-;;V>g-3D<29n0q^U9B;-LIN{=2r z>V5U<)l|5-VHv=E9=`YYy#D6Ro7r^K`OQFefTt)KMr_+AFyWt_ zhMeKy;f1cQuB1j|$pqgWF8MqdpphN7by&xM^XJdo7{O8R!7-P}aJ+c&!bMteXaQ}N zq1V4s0a^5E^)+y9XFq)S;1wAT`YOmr`1bAFmq%5w*=&P-eSHCAt`45;^?EDeQtG*% z_V)HJhy(*$QY)xFzC1b93`WxW5La^CL+?fC12bIz576 ztw=Ipk=-Xxp8Q?JfrW*I)@T?&PzsuwnzT5ik0UWaQUT`h{FXmeq3u?Hv@xEcq|15B zFARXUB5i2>k<#0_kF8Rzju3+5>~GGi@`wEh%-7^c_b`g0qsQ&I(TU=Sp+5OJWbt?kyOOP6{@1^|mK(aIvN%3r(;t<`O3_+5R{t`a*O z|1&`BaHv>V0bYs3x# zyHGf?ABhqmsQ|JhJ4OZAg2R!`SV*dm)8A1a1Z}AeSS14>?NK5Ieyz$Nl^F$JNxB38<*3kQ%Gl zc*#*>06Q?*WCS%(QAETx1!V^M?F*4B%sPoIt$^9N^y zpo4}-j~@Lf;sBo^q6BH<$Zj(Kxc~!ZXJ;L(m~c0U#Tde}+Lg{_LF2@U6TgTp1YLd7 zMoHJ}^#Ow$V8DY154o z_wHQ>Bw&KpvZ0~DC^8&ad86O*hij@1yTXNqg`G4OcDvnh2jZ1ip#q7O#^Jdsy!H5wcBD6^u4=uK= zQk%_|J3Kt>K^ZM0m_WU6Zf-Wwu>t2>`zdmWYNyk=oNASzuL5J2 zfAHYJd@N8FR^9>PyOiD^RT>PEFkV|*>jM)^{6d2&0dBAI%MFnNFlIS^{J05=!4Q}4 z)eGX^Me~f9QsMH~piTa|;`sRZVn;`ZYpd#uB%JYzKaEGnjlN5$m!|}A)dJX8%=WsV z0_zf6(USSuTrlC{%c^smbBGubcQJ(0Fg-o}t=wrQrJLDq$Br{LT_xhfNvqYWfmdn_ z`ihiIJ`SkgUm!j%^-EYah>Vz@pSJ`{1i^+RsEZeB;$;^K8!_065bo1iR;QrPIfzJe zn5Hi-F4hHqIx7-LxF1RTc$yNy_Pa!UJdGHhIm?l>{&+ePC>dDoVm4#3ABinFa#zZ_ r&*xdEWT_6<+!$wAvxvp8MT7qUit>0OSg`iT00000NkvXXu0mjf(ojc> literal 0 HcmV?d00001 diff --git a/room/tuiroomkit/src/main/res/drawable-xxhdpi/roomkit_ic_switch_portrait_button.png b/room/tuiroomkit/src/main/res/drawable-xxhdpi/roomkit_ic_switch_portrait_button.png new file mode 100644 index 0000000000000000000000000000000000000000..449308e423d1c058921634a704261a7bf440ff41 GIT binary patch literal 2211 zcmV;U2weAxP)3WQa=i(KjEBMl+gB;?FRdL^GPGkG`3hOrmCR zCYeMdF=z$UKn;wV0cQY#aw*aa(D}Y&Pg824*CQ>RFTs7-F-zrSQ*}m6d7DX0t}8(@Ev!<@r{tRljA+mV6-e8>tLf$V-e9 z>9UNJ6%b8u3OzJ5oNj zB?X*0b7nVw$hRUW_~hiIueY~%E>)q|0+q3U|NbJ2#iHYD#Uid>zy4MviKG;8{``3p zR=EwA^mWw*j|ALBbMWB7;);q217A}STCMhvWUL`!1%$7<$KzRk{P?l!YY85ShK7d1 z`uh4Jx(1Zs3tGdQM7~3l$Ykv9O&BP=W_Wnm-PP6Q!s;)H4Z_&im>>JhqRC{Eii(O1 zI7Ta*o12Bh;h2c`JK|Qr*|TTcG1PK{d;R+L+><9y=9iY10%C))xVRX=VtC*JfuKv+ zT3T96P{L?DpN~rcSouy2l@$Kr!-pT8PNzp?7+?uLScGTWwrvKuLRn*DW7UfnFNR`$ zE~Wy4D_==}zkmNej`4{NGx=DUpPyf$OW@cnK>Sb`k0q?D0IWRyeK&=F@ZiBm1TV`X z!$Fsz5^8E{jEF=_VF@}|!oO?HUsD0x?J+d)8k^l@Ca-)Xs09384=kY&?ofW{{Goa^!ZqzJ0Mb&H%1)W7AWEGXV0GbBIilbK8)S{2MqZm zBO{-BdU{mN#?%CVJ3{gWC_ons+`hmU3OIM}Ts1Q|`aLu@C$bz*pFW+VEV#5mwq23; zS4Dy}eXc$g0O4JIeSM!qifCy>gZ!$`T6(Z<`B?#omSo=_9UWa1n;b0F1uyOVM^*qdB5UK_yLVX^@g)k@DLJxYEsxy& zY5q9>S2nZxD+qG~BYPGS5{DArn3{6*wgbFIxc5e~}}Awac=yRi{NEkrAL^w?-rZXz@?6LBQgDFOq;#+mQQ| z(1P65K>nQZ)t+<#i!IB_CaqR!UPkun5(SRX->{GL3ze~V@7{gL?v9ESpoIFAT`SUr z!NI}4zyghLWJj{g;kBgZ;3{VV_TgY3tZp{S+ z6mTT>kfW>soCG5rckbMo5~(p8P*qhW6RSwPfXXd=m!#_H(X50)J>Qgq#Xfzr_oa0p{tJDWsG`xHF?xfg6IC0`cS&%H@gv&dW_g7_u zo7D+cXZXEU3JCVi<(?V(Zzb3;vOZm=>61;$Yx+LV{_y)>2zcYh4JXWG zg1cpVd%Ia=Ia*p;%*xImjZ__Vg<&S$bcLFl8dGa)Yu3gFWT)WVFT|xE;qUL!=0r_^ zy1TpmO-)TJxU3{K9c5%MSyv*9P+3`-4>vC3H5Rk)>eZ`Jxq@qEfDVUa5}St}!BKg2 zb#=kW$cP7Rw5(79{r!!fHy}kdCZi+7{CH)kg)r?mHh41X_ zw9xMn;=hIPj`ilptO1Z~OX4xPw^RaJXc_AcG1>G z-62VX5I!aMOIrnpida}!u!UO$K|&JT#RoU>k%dAc2Du2)9-U=(3jUmr9z{OO^rfYx zhVVycMH&THpxVRJvXBLQ2R-A|;2clxUC7vroxZ l9qzd?&ah{Z%*K`o{sX3vKn6V6p@{$h002ovPDHLkV1hWFC0+mk literal 0 HcmV?d00001 diff --git a/room/tuiroomkit/src/main/res/layout/roomkit_main_view.xml b/room/tuiroomkit/src/main/res/layout/roomkit_main_view.xml index 0ea6b93d..b3e82cff 100644 --- a/room/tuiroomkit/src/main/res/layout/roomkit_main_view.xml +++ b/room/tuiroomkit/src/main/res/layout/roomkit_main_view.xml @@ -1,6 +1,7 @@ @@ -22,6 +23,17 @@ app:layout_constraintTop_toBottomOf="@id/room_top_bar" app:layout_constraintVertical_weight="1" /> + +