Skip to content

Commit cb8cb7d

Browse files
masonqiaoAbySwifter
authored andcommitted
【Room】Add screen orientation switching support for screen sharing in room scenes
1 parent 1ad02a0 commit cb8cb7d

7 files changed

Lines changed: 134 additions & 4 deletions

File tree

room/tuiroomkit/src/main/AndroidManifest.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,9 @@
3434

3535
<activity
3636
android:name=".RoomMainActivity"
37+
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
3738
android:exported="false"
38-
android:screenOrientation="portrait" />
39+
android:screenOrientation="locked" />
3940

4041
<activity
4142
android:name=".aitranscription.AITranscriptionSettingActivity"

room/tuiroomkit/src/main/java/com/trtc/uikit/roomkit/RoomMainActivity.kt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
package com.trtc.uikit.roomkit
22

3+
import android.content.res.Configuration
34
import android.os.Bundle
45
import android.view.View
56
import android.view.WindowManager
7+
import androidx.core.view.WindowCompat
8+
import androidx.core.view.WindowInsetsCompat
9+
import androidx.core.view.WindowInsetsControllerCompat
610
import com.tencent.cloud.tuikit.engine.common.ContextProvider
711
import com.trtc.uikit.roomkit.view.RoomMainView
812
import io.trtc.tuikit.atomicx.common.FullScreenActivity
@@ -57,9 +61,15 @@ class RoomMainActivity : FullScreenActivity() {
5761

5862
val roomType = if (isWebinarRoom(roomID)) RoomType.WEBINAR else RoomType.STANDARD
5963
roomMainView?.init(roomID, roomType, behavior, config)
64+
applySystemBarStyle(resources.configuration.orientation)
6065
startForegroundService()
6166
}
6267

68+
override fun onConfigurationChanged(newConfig: Configuration) {
69+
super.onConfigurationChanged(newConfig)
70+
applySystemBarStyle(newConfig.orientation)
71+
}
72+
6373
override fun onDestroy() {
6474
super.onDestroy()
6575
stopForegroundService()
@@ -70,6 +80,18 @@ class RoomMainActivity : FullScreenActivity() {
7080
override fun onBackPressed() {
7181
}
7282

83+
private fun applySystemBarStyle(orientation: Int) {
84+
val controller = WindowInsetsControllerCompat(window, window.decorView)
85+
WindowCompat.setDecorFitsSystemWindows(window, false)
86+
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
87+
controller.systemBarsBehavior =
88+
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
89+
controller.hide(WindowInsetsCompat.Type.systemBars())
90+
} else {
91+
controller.show(WindowInsetsCompat.Type.systemBars())
92+
}
93+
}
94+
7395
private fun startForegroundService() {
7496
val context = ContextProvider.getApplicationContext()
7597
VideoForegroundService.start(

room/tuiroomkit/src/main/java/com/trtc/uikit/roomkit/view/RoomMainView.kt

Lines changed: 85 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
package com.trtc.uikit.roomkit.view
22

3+
import android.annotation.SuppressLint
34
import android.app.Activity
45
import android.app.Dialog
56
import android.content.Context
67
import android.content.Intent
8+
import android.content.pm.ActivityInfo
9+
import android.content.res.Configuration
710
import android.util.AttributeSet
811
import android.view.LayoutInflater
12+
import android.widget.ImageView
913
import androidx.core.content.ContextCompat
1014
import com.trtc.uikit.roomkit.R
1115
import com.trtc.uikit.roomkit.aitranscription.AIMinutesActivity
@@ -29,8 +33,8 @@ import com.trtc.uikit.roomkit.base.ui.RoomAlertDialog
2933
import com.trtc.uikit.roomkit.view.main.ParticipantManagerView
3034
import com.trtc.uikit.roomkit.view.main.RoomBottomBarView
3135
import com.trtc.uikit.roomkit.view.main.RoomBottomBarViewListener
32-
import com.trtc.uikit.roomkit.view.main.RoomTopBarView
3336
import com.trtc.uikit.roomkit.view.main.RoomRecordingFloatingView
37+
import com.trtc.uikit.roomkit.view.main.RoomTopBarView
3438
import com.trtc.uikit.roomkit.view.main.RoomView
3539
import com.trtc.uikit.roomkit.view.main.screenshare.ScreenShareOverlayView
3640
import io.trtc.tuikit.atomicx.widget.basicwidget.toast.AtomicToast
@@ -46,12 +50,13 @@ import io.trtc.tuikit.atomicxcore.api.room.CreateRoomOptions
4650
import io.trtc.tuikit.atomicxcore.api.room.DeviceRequestInfo
4751
import io.trtc.tuikit.atomicxcore.api.room.KickedOutOfRoomReason
4852
import io.trtc.tuikit.atomicxcore.api.room.ParticipantRole
53+
import io.trtc.tuikit.atomicxcore.api.room.RecordingStatus
54+
import io.trtc.tuikit.atomicxcore.api.room.RecordingStopReason
4955
import io.trtc.tuikit.atomicxcore.api.room.RoomInfo
5056
import io.trtc.tuikit.atomicxcore.api.room.RoomListener
5157
import io.trtc.tuikit.atomicxcore.api.room.RoomParticipant
5258
import io.trtc.tuikit.atomicxcore.api.room.RoomParticipantListener
5359
import io.trtc.tuikit.atomicxcore.api.room.RoomParticipantStore
54-
import io.trtc.tuikit.atomicxcore.api.room.RecordingStopReason
5560
import io.trtc.tuikit.atomicxcore.api.room.RoomStore
5661
import io.trtc.tuikit.atomicxcore.api.room.RoomType
5762
import io.trtc.tuikit.atomicxcore.api.room.RoomUser
@@ -105,6 +110,8 @@ class RoomMainView @JvmOverloads constructor(
105110
private val barrageStreamView: BarrageStreamView by lazy { findViewById(R.id.barrage_stream_view) }
106111
private val screenShareOverlayView: ScreenShareOverlayView by lazy { findViewById(R.id.screen_share_overlay_view) }
107112
private val recordingFloatingView: RoomRecordingFloatingView by lazy { findViewById(R.id.recording_floating_view) }
113+
private val orientationSwitchButton: ImageView by lazy { findViewById(R.id.orientation_switch_button) }
114+
private var currentScreenSharerID: String? = null
108115

109116
private var roomType = RoomType.STANDARD
110117
private val roomStore = RoomStore.shared()
@@ -337,12 +344,21 @@ class RoomMainView @JvmOverloads constructor(
337344
barrageStreamView.visibility = GONE
338345
}
339346
RoomDataReporter.reportComponent()
347+
orientationSwitchButton.setOnClickListener {
348+
switchOrientation()
349+
}
350+
updateOrientationVisibility(resources.configuration.orientation)
340351
when (behavior) {
341352
is RoomBehavior.Create -> createRoom(roomID, behavior.options)
342353
is RoomBehavior.Join -> joinRoom(roomID)
343354
}
344355
}
345356

357+
override fun onConfigurationChanged(newConfig: Configuration) {
358+
super.onConfigurationChanged(newConfig)
359+
updateOrientationVisibility(newConfig.orientation)
360+
}
361+
346362
override fun initStore(roomID: String) {
347363
participantStore = RoomParticipantStore.create(roomID)
348364
}
@@ -358,6 +374,12 @@ class RoomMainView @JvmOverloads constructor(
358374
.distinctUntilChanged()
359375
.collect { screenShareOverlayView.updateScreenStatus(it) }
360376
}
377+
scope.launch {
378+
participantStore.state.participantWithScreen
379+
.map { it?.userID }
380+
.distinctUntilChanged()
381+
.collect(::onScreenSharerChanged)
382+
}
361383
}
362384

363385
override fun removeObserver() {
@@ -698,6 +720,67 @@ class RoomMainView @JvmOverloads constructor(
698720
return AIMinutesActivity.getForegroundInstance() ?: context
699721
}
700722

723+
private fun updateOrientationVisibility(orientation: Int) {
724+
val isLandscape = orientation == Configuration.ORIENTATION_LANDSCAPE
725+
topBarView.visibility = if (isLandscape) GONE else VISIBLE
726+
bottomBarView.visibility = if (isLandscape) GONE else VISIBLE
727+
if (isLandscape) aiSubtitleView.visibility = GONE
728+
if (roomType == RoomType.WEBINAR) {
729+
barrageInputView.visibility = if (isLandscape) GONE else VISIBLE
730+
barrageStreamView.visibility = if (isLandscape) GONE else VISIBLE
731+
}
732+
recordingFloatingView.visibility = when {
733+
isLandscape -> GONE
734+
roomStore.state.currentRoom.value?.recordingInfo?.status == RecordingStatus.RECORDING -> VISIBLE
735+
else -> GONE
736+
}
737+
updateOrientationSwitchButtonVisibility(orientation)
738+
}
739+
740+
private fun updateOrientationSwitchButtonVisibility(
741+
orientation: Int = resources.configuration.orientation
742+
) {
743+
val hasRemoteSharer = currentScreenSharerID != null && currentScreenSharerID != localUserID
744+
val shouldShow = roomType != RoomType.WEBINAR && hasRemoteSharer
745+
orientationSwitchButton.visibility = if (shouldShow) VISIBLE else GONE
746+
val isLandscape = orientation == Configuration.ORIENTATION_LANDSCAPE
747+
orientationSwitchButton.setImageResource(
748+
if (isLandscape) R.drawable.roomkit_ic_switch_portrait_button
749+
else R.drawable.roomkit_ic_switch_landscape_button
750+
)
751+
}
752+
753+
@SuppressLint("SourceLockedOrientationActivity")
754+
private fun switchOrientation() {
755+
val activity = context as? Activity ?: return
756+
val currentlyLandscape =
757+
resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
758+
activity.requestedOrientation = if (currentlyLandscape) {
759+
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
760+
} else {
761+
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
762+
}
763+
}
764+
765+
@SuppressLint("SourceLockedOrientationActivity")
766+
private fun forcePortraitIfLandscape() {
767+
val activity = context as? Activity ?: return
768+
if (resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {
769+
activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
770+
}
771+
}
772+
773+
private fun onScreenSharerChanged(newSharerID: String?) {
774+
if (currentScreenSharerID == newSharerID) {
775+
return
776+
}
777+
currentScreenSharerID = newSharerID
778+
updateOrientationSwitchButtonVisibility()
779+
if (newSharerID.isNullOrEmpty()) {
780+
forcePortraitIfLandscape()
781+
}
782+
}
783+
701784
fun isAISubtitleVisible(): Boolean {
702785
return aiSubtitleView.visibility == VISIBLE
703786
}

room/tuiroomkit/src/main/java/com/trtc/uikit/roomkit/view/main/roomview/PagedVideoLayoutManager.kt

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.trtc.uikit.roomkit.view.main.roomview
22

3+
import android.content.res.Configuration
34
import android.graphics.PointF
45
import android.view.View
56
import android.view.ViewGroup
@@ -71,6 +72,7 @@ class PagedVideoLayoutManager(
7172

7273
private var scrollState = RecyclerView.SCROLL_STATE_IDLE
7374
private var lastSpeakerMode = false
75+
private var attachedRecyclerView: RecyclerView? = null
7476

7577
override fun generateDefaultLayoutParams(): RecyclerView.LayoutParams {
7678
val params = RecyclerView.LayoutParams(
@@ -82,7 +84,11 @@ class PagedVideoLayoutManager(
8284
return params
8385
}
8486

85-
override fun canScrollHorizontally(): Boolean = true
87+
override fun canScrollHorizontally(): Boolean {
88+
val orientation = attachedRecyclerView?.resources?.configuration?.orientation
89+
?: Configuration.ORIENTATION_PORTRAIT
90+
return orientation != Configuration.ORIENTATION_LANDSCAPE
91+
}
8692

8793
override fun onLayoutChildren(recycler: RecyclerView.Recycler, state: RecyclerView.State) {
8894
if (state.isPreLayout) return
@@ -118,6 +124,7 @@ class PagedVideoLayoutManager(
118124
override fun onAttachedToWindow(view: RecyclerView) {
119125
super.onAttachedToWindow(view)
120126
cachedAdapter = view.adapter
127+
attachedRecyclerView = view
121128

122129
// Listen to scroll state changes
123130
view.addOnScrollListener(object : RecyclerView.OnScrollListener() {
@@ -127,6 +134,11 @@ class PagedVideoLayoutManager(
127134
})
128135
}
129136

137+
override fun onDetachedFromWindow(view: RecyclerView, recycler: RecyclerView.Recycler) {
138+
super.onDetachedFromWindow(view, recycler)
139+
attachedRecyclerView = null
140+
}
141+
130142
/**
131143
* Check if speaker mode is active
132144
* Speaker mode is ON when first item is screen share stream
2.22 KB
Loading
2.16 KB
Loading

room/tuiroomkit/src/main/res/layout/roomkit_main_view.xml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
33
xmlns:app="http://schemas.android.com/apk/res-auto"
4+
xmlns:tools="http://schemas.android.com/tools"
45
android:layout_width="match_parent"
56
android:layout_height="match_parent"
67
android:background="@color/roomkit_color_room_background">
@@ -22,6 +23,17 @@
2223
app:layout_constraintTop_toBottomOf="@id/room_top_bar"
2324
app:layout_constraintVertical_weight="1" />
2425

26+
<ImageView
27+
android:id="@+id/orientation_switch_button"
28+
android:layout_width="32dp"
29+
android:layout_height="32dp"
30+
android:layout_marginEnd="12dp"
31+
android:layout_marginBottom="12dp"
32+
android:src="@drawable/roomkit_ic_switch_landscape_button"
33+
app:layout_constraintBottom_toBottomOf="@+id/room_view"
34+
app:layout_constraintEnd_toEndOf="@+id/room_view"
35+
tools:ignore="ContentDescription" />
36+
2537
<com.trtc.uikit.roomkit.aitranscription.subtitleview.AISubtitleView
2638
android:id="@+id/ai_subtitle_view"
2739
android:layout_width="0dp"

0 commit comments

Comments
 (0)