Factorized code to handle local video preview moving (with camera switch)
This commit is contained in:
parent
1bb294acf1
commit
30d6e556c1
11 changed files with 173 additions and 56 deletions
|
@ -27,21 +27,21 @@ import android.view.View
|
|||
import android.widget.PopupWindow
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.navigation.navGraphViewModels
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.R
|
||||
import org.linphone.activities.GenericFragment
|
||||
import org.linphone.activities.main.MainActivity
|
||||
import org.linphone.activities.voip.ConferenceDisplayMode
|
||||
import org.linphone.activities.voip.data.CallData
|
||||
import org.linphone.activities.voip.viewmodels.CallsViewModel
|
||||
import org.linphone.activities.voip.viewmodels.ConferenceViewModel
|
||||
import org.linphone.activities.voip.viewmodels.ControlsViewModel
|
||||
import org.linphone.databinding.VoipCallContextMenuBindingImpl
|
||||
import org.linphone.databinding.VoipCallsListFragmentBinding
|
||||
import org.linphone.utils.AppUtils
|
||||
|
||||
class CallsListFragment : GenericFragment<VoipCallsListFragmentBinding>() {
|
||||
class CallsListFragment : GenericVideoPreviewFragment<VoipCallsListFragmentBinding>() {
|
||||
private val callsViewModel: CallsViewModel by navGraphViewModels(R.id.call_nav_graph)
|
||||
private val conferenceViewModel: ConferenceViewModel by navGraphViewModels(R.id.call_nav_graph)
|
||||
private val controlsViewModel: ControlsViewModel by navGraphViewModels(R.id.call_nav_graph)
|
||||
|
||||
override fun getLayoutId(): Int = R.layout.voip_calls_list_fragment
|
||||
|
||||
|
@ -57,8 +57,13 @@ class CallsListFragment : GenericFragment<VoipCallsListFragmentBinding>() {
|
|||
binding.lifecycleOwner = viewLifecycleOwner
|
||||
|
||||
binding.callsViewModel = callsViewModel
|
||||
|
||||
binding.conferenceViewModel = conferenceViewModel
|
||||
|
||||
binding.controlsViewModel = controlsViewModel
|
||||
|
||||
setupLocalViewPreview(binding.localPreviewVideoSurface, binding.switchCamera)
|
||||
|
||||
binding.setCancelClickListener {
|
||||
goBack()
|
||||
}
|
||||
|
@ -91,12 +96,6 @@ class CallsListFragment : GenericFragment<VoipCallsListFragmentBinding>() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
|
||||
coreContext.core.nativePreviewWindowId = binding.localPreviewVideoSurface
|
||||
}
|
||||
|
||||
private fun showCallMenu(anchor: View, callData: CallData) {
|
||||
val popupView: VoipCallContextMenuBindingImpl = DataBindingUtil.inflate(
|
||||
LayoutInflater.from(requireContext()),
|
||||
|
|
|
@ -25,13 +25,14 @@ import androidx.constraintlayout.widget.ConstraintLayout
|
|||
import androidx.navigation.navGraphViewModels
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.R
|
||||
import org.linphone.activities.GenericFragment
|
||||
import org.linphone.activities.voip.ConferenceDisplayMode
|
||||
import org.linphone.activities.voip.viewmodels.ConferenceViewModel
|
||||
import org.linphone.activities.voip.viewmodels.ControlsViewModel
|
||||
import org.linphone.databinding.VoipConferenceLayoutFragmentBinding
|
||||
|
||||
class ConferenceLayoutFragment : GenericFragment<VoipConferenceLayoutFragmentBinding>() {
|
||||
class ConferenceLayoutFragment : GenericVideoPreviewFragment<VoipConferenceLayoutFragmentBinding>() {
|
||||
private val conferenceViewModel: ConferenceViewModel by navGraphViewModels(R.id.call_nav_graph)
|
||||
private val controlsViewModel: ControlsViewModel by navGraphViewModels(R.id.call_nav_graph)
|
||||
|
||||
override fun getLayoutId(): Int = R.layout.voip_conference_layout_fragment
|
||||
|
||||
|
@ -42,6 +43,10 @@ class ConferenceLayoutFragment : GenericFragment<VoipConferenceLayoutFragmentBin
|
|||
|
||||
binding.conferenceViewModel = conferenceViewModel
|
||||
|
||||
binding.controlsViewModel = controlsViewModel
|
||||
|
||||
setupLocalViewPreview(binding.localPreviewVideoSurface, binding.switchCamera)
|
||||
|
||||
binding.setCancelClickListener {
|
||||
goBack()
|
||||
}
|
||||
|
|
|
@ -25,14 +25,15 @@ import android.widget.Toast
|
|||
import androidx.navigation.navGraphViewModels
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.R
|
||||
import org.linphone.activities.GenericFragment
|
||||
import org.linphone.activities.navigateToAddParticipants
|
||||
import org.linphone.activities.voip.viewmodels.ConferenceViewModel
|
||||
import org.linphone.activities.voip.viewmodels.ControlsViewModel
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.databinding.VoipConferenceParticipantsFragmentBinding
|
||||
|
||||
class ConferenceParticipantsFragment : GenericFragment<VoipConferenceParticipantsFragmentBinding>() {
|
||||
class ConferenceParticipantsFragment : GenericVideoPreviewFragment<VoipConferenceParticipantsFragmentBinding>() {
|
||||
private val conferenceViewModel: ConferenceViewModel by navGraphViewModels(R.id.call_nav_graph)
|
||||
private val controlsViewModel: ControlsViewModel by navGraphViewModels(R.id.call_nav_graph)
|
||||
|
||||
// Only display events happening during while this fragment is visible
|
||||
private var skipEvents = true
|
||||
|
@ -46,6 +47,10 @@ class ConferenceParticipantsFragment : GenericFragment<VoipConferenceParticipant
|
|||
|
||||
binding.conferenceViewModel = conferenceViewModel
|
||||
|
||||
binding.controlsViewModel = controlsViewModel
|
||||
|
||||
setupLocalViewPreview(binding.localPreviewVideoSurface, binding.switchCamera)
|
||||
|
||||
conferenceViewModel.conferenceExists.observe(
|
||||
viewLifecycleOwner
|
||||
) { exists ->
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2022 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-android
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.linphone.activities.voip.fragments
|
||||
|
||||
import android.view.MotionEvent
|
||||
import android.view.TextureView
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import androidx.databinding.ViewDataBinding
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.activities.GenericFragment
|
||||
|
||||
abstract class GenericVideoPreviewFragment<T : ViewDataBinding> : GenericFragment<T>() {
|
||||
private var previewX: Float = 0f
|
||||
private var previewY: Float = 0f
|
||||
private var switchX: Float = 0f
|
||||
private var switchY: Float = 0f
|
||||
|
||||
private var switchCameraImageView: ImageView? = null
|
||||
private lateinit var videoPreviewTextureView: TextureView
|
||||
|
||||
private val previewTouchListener = View.OnTouchListener { view, event ->
|
||||
when (event.action) {
|
||||
MotionEvent.ACTION_DOWN -> {
|
||||
previewX = view.x - event.rawX
|
||||
previewY = view.y - event.rawY
|
||||
switchX = (switchCameraImageView?.x ?: 0f) - event.rawX
|
||||
switchY = (switchCameraImageView?.y ?: 0f) - event.rawY
|
||||
true
|
||||
}
|
||||
MotionEvent.ACTION_MOVE -> {
|
||||
view.animate()
|
||||
.x(event.rawX + previewX)
|
||||
.y(event.rawY + previewY)
|
||||
.setDuration(0)
|
||||
.start()
|
||||
switchCameraImageView?.apply {
|
||||
animate()
|
||||
.x(event.rawX + switchX)
|
||||
.y(event.rawY + switchY)
|
||||
.setDuration(0)
|
||||
.start()
|
||||
}
|
||||
true
|
||||
}
|
||||
else -> {
|
||||
view.performClick()
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected fun setupLocalViewPreview(localVideoPreview: TextureView, switchCamera: ImageView?) {
|
||||
videoPreviewTextureView = localVideoPreview
|
||||
switchCameraImageView = switchCamera
|
||||
videoPreviewTextureView.setOnTouchListener(previewTouchListener)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
|
||||
if (::videoPreviewTextureView.isInitialized) {
|
||||
coreContext.core.nativePreviewWindowId = videoPreviewTextureView
|
||||
}
|
||||
}
|
||||
}
|
|
@ -28,13 +28,12 @@ import androidx.databinding.ViewDataBinding
|
|||
import androidx.navigation.navGraphViewModels
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.R
|
||||
import org.linphone.activities.GenericFragment
|
||||
import org.linphone.activities.navigateToActiveCall
|
||||
import org.linphone.activities.voip.viewmodels.CallsViewModel
|
||||
import org.linphone.activities.voip.viewmodels.ControlsViewModel
|
||||
import org.linphone.databinding.VoipCallOutgoingFragmentBinding
|
||||
|
||||
class OutgoingCallFragment : GenericFragment<VoipCallOutgoingFragmentBinding>() {
|
||||
class OutgoingCallFragment : GenericVideoPreviewFragment<VoipCallOutgoingFragmentBinding>() {
|
||||
private val controlsViewModel: ControlsViewModel by navGraphViewModels(R.id.call_nav_graph)
|
||||
private val callsViewModel: CallsViewModel by navGraphViewModels(R.id.call_nav_graph)
|
||||
|
||||
|
@ -49,6 +48,8 @@ class OutgoingCallFragment : GenericFragment<VoipCallOutgoingFragmentBinding>()
|
|||
|
||||
binding.callsViewModel = callsViewModel
|
||||
|
||||
setupLocalViewPreview(binding.localPreviewVideoSurface, binding.switchCamera)
|
||||
|
||||
callsViewModel.callConnectedEvent.observe(
|
||||
viewLifecycleOwner
|
||||
) {
|
||||
|
|
|
@ -23,7 +23,6 @@ import android.app.Dialog
|
|||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.os.SystemClock
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.widget.Chronometer
|
||||
import androidx.constraintlayout.widget.ConstraintSet
|
||||
|
@ -46,7 +45,7 @@ import org.linphone.databinding.VoipSingleCallFragmentBinding
|
|||
import org.linphone.utils.AppUtils
|
||||
import org.linphone.utils.DialogUtils
|
||||
|
||||
class SingleCallFragment : GenericFragment<VoipSingleCallFragmentBinding>() {
|
||||
class SingleCallFragment : GenericVideoPreviewFragment<VoipSingleCallFragmentBinding>() {
|
||||
private val controlsViewModel: ControlsViewModel by navGraphViewModels(R.id.call_nav_graph)
|
||||
private val callsViewModel: CallsViewModel by navGraphViewModels(R.id.call_nav_graph)
|
||||
private val conferenceViewModel: ConferenceViewModel by navGraphViewModels(R.id.call_nav_graph)
|
||||
|
@ -54,39 +53,6 @@ class SingleCallFragment : GenericFragment<VoipSingleCallFragmentBinding>() {
|
|||
|
||||
private var dialog: Dialog? = null
|
||||
|
||||
private var previewX: Float = 0f
|
||||
private var previewY: Float = 0f
|
||||
private var switchX: Float = 0f
|
||||
private var switchY: Float = 0f
|
||||
private val previewTouchListener = View.OnTouchListener { view, event ->
|
||||
when (event.action) {
|
||||
MotionEvent.ACTION_DOWN -> {
|
||||
previewX = view.x - event.rawX
|
||||
previewY = view.y - event.rawY
|
||||
switchX = binding.switchCamera.x - event.rawX
|
||||
switchY = binding.switchCamera.y - event.rawY
|
||||
true
|
||||
}
|
||||
MotionEvent.ACTION_MOVE -> {
|
||||
view.animate()
|
||||
.x(event.rawX + previewX)
|
||||
.y(event.rawY + previewY)
|
||||
.setDuration(0)
|
||||
.start()
|
||||
binding.switchCamera.animate()
|
||||
.x(event.rawX + switchX)
|
||||
.y(event.rawY + switchY)
|
||||
.setDuration(0)
|
||||
.start()
|
||||
true
|
||||
}
|
||||
else -> {
|
||||
view.performClick()
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getLayoutId(): Int = R.layout.voip_single_call_fragment
|
||||
|
||||
override fun onStart() {
|
||||
|
@ -102,7 +68,7 @@ class SingleCallFragment : GenericFragment<VoipSingleCallFragmentBinding>() {
|
|||
|
||||
binding.lifecycleOwner = viewLifecycleOwner
|
||||
|
||||
binding.previewTouchListener = previewTouchListener
|
||||
setupLocalViewPreview(binding.localPreviewVideoSurface, binding.switchCamera)
|
||||
|
||||
binding.controlsViewModel = controlsViewModel
|
||||
|
||||
|
|
|
@ -140,6 +140,19 @@
|
|||
app:layout_constraintHeight_max="200dp"
|
||||
app:layout_constraintWidth_max="200dp" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/switch_camera"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="5dp"
|
||||
android:contentDescription="@string/content_description_switch_camera"
|
||||
android:onClick="@{() -> controlsViewModel.switchCamera()}"
|
||||
android:padding="10dp"
|
||||
android:src="@drawable/icon_call_camera_switch"
|
||||
android:visibility="@{controlsViewModel.isSwitchCameraAvailable && !controlsViewModel.pipMode ? View.VISIBLE : View.GONE, default=gone}"
|
||||
app:layout_constraintEnd_toEndOf="@id/local_preview_video_surface"
|
||||
app:layout_constraintTop_toTopOf="@id/local_preview_video_surface" />
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/stub_numpad"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
<variable
|
||||
name="conferenceViewModel"
|
||||
type="org.linphone.activities.voip.viewmodels.ConferenceViewModel" />
|
||||
<variable
|
||||
name="controlsViewModel"
|
||||
type="org.linphone.activities.voip.viewmodels.ControlsViewModel" />
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
|
@ -123,6 +126,19 @@
|
|||
app:layout_constraintHeight_max="200dp"
|
||||
app:layout_constraintWidth_max="200dp" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/switch_camera"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="5dp"
|
||||
android:contentDescription="@string/content_description_switch_camera"
|
||||
android:onClick="@{() -> controlsViewModel.switchCamera()}"
|
||||
android:padding="10dp"
|
||||
android:src="@drawable/icon_call_camera_switch"
|
||||
android:visibility="@{controlsViewModel.isSwitchCameraAvailable && !controlsViewModel.pipMode ? View.VISIBLE : View.GONE, default=gone}"
|
||||
app:layout_constraintEnd_toEndOf="@id/local_preview_video_surface"
|
||||
app:layout_constraintTop_toTopOf="@id/local_preview_video_surface" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</layout>
|
|
@ -19,6 +19,10 @@
|
|||
<variable
|
||||
name="conferenceViewModel"
|
||||
type="org.linphone.activities.voip.viewmodels.ConferenceViewModel" />
|
||||
|
||||
<variable
|
||||
name="controlsViewModel"
|
||||
type="org.linphone.activities.voip.viewmodels.ControlsViewModel" />
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
|
@ -136,6 +140,19 @@
|
|||
app:layout_constraintHeight_max="200dp"
|
||||
app:layout_constraintWidth_max="200dp" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/switch_camera"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="5dp"
|
||||
android:contentDescription="@string/content_description_switch_camera"
|
||||
android:onClick="@{() -> controlsViewModel.switchCamera()}"
|
||||
android:padding="10dp"
|
||||
android:src="@drawable/icon_call_camera_switch"
|
||||
android:visibility="@{controlsViewModel.isSwitchCameraAvailable && !controlsViewModel.pipMode ? View.VISIBLE : View.GONE, default=gone}"
|
||||
app:layout_constraintEnd_toEndOf="@id/local_preview_video_surface"
|
||||
app:layout_constraintTop_toTopOf="@id/local_preview_video_surface" />
|
||||
|
||||
<include
|
||||
android:id="@+id/too_many_participants_dialog"
|
||||
layout="@layout/voip_dialog_info"
|
||||
|
|
|
@ -17,6 +17,10 @@
|
|||
<variable
|
||||
name="conferenceViewModel"
|
||||
type="org.linphone.activities.voip.viewmodels.ConferenceViewModel" />
|
||||
|
||||
<variable
|
||||
name="controlsViewModel"
|
||||
type="org.linphone.activities.voip.viewmodels.ControlsViewModel" />
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
|
@ -99,6 +103,19 @@
|
|||
app:layout_constraintHeight_max="200dp"
|
||||
app:layout_constraintWidth_max="200dp" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/switch_camera"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="5dp"
|
||||
android:contentDescription="@string/content_description_switch_camera"
|
||||
android:onClick="@{() -> controlsViewModel.switchCamera()}"
|
||||
android:padding="10dp"
|
||||
android:src="@drawable/icon_call_camera_switch"
|
||||
android:visibility="@{controlsViewModel.isSwitchCameraAvailable && !controlsViewModel.pipMode ? View.VISIBLE : View.GONE, default=gone}"
|
||||
app:layout_constraintEnd_toEndOf="@id/local_preview_video_surface"
|
||||
app:layout_constraintTop_toTopOf="@id/local_preview_video_surface" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</layout>
|
|
@ -9,10 +9,6 @@
|
|||
|
||||
<import type="com.google.android.flexbox.FlexDirection" />
|
||||
|
||||
<variable
|
||||
name="previewTouchListener"
|
||||
type="android.view.View.OnTouchListener" />
|
||||
|
||||
<variable
|
||||
name="controlsViewModel"
|
||||
type="org.linphone.activities.voip.viewmodels.ControlsViewModel" />
|
||||
|
@ -234,7 +230,6 @@
|
|||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_size="@{controlsViewModel.pipMode ? @dimen/video_preview_pip_max_size : @dimen/video_preview_max_size}"
|
||||
android:onTouch="@{previewTouchListener}"
|
||||
app:alignTopRight="true"
|
||||
app:displayMode="black_bars"
|
||||
app:layout_constraintBottom_toTopOf="@id/bottom_barrier"
|
||||
|
|
Loading…
Reference in a new issue