diff --git a/app/src/main/java/org/linphone/activities/voip/views/HorizontalScrollDotsView.kt b/app/src/main/java/org/linphone/activities/voip/views/HorizontalScrollDotsView.kt
deleted file mode 100644
index 7b4cc560f..000000000
--- a/app/src/main/java/org/linphone/activities/voip/views/HorizontalScrollDotsView.kt
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (c) 2010-2021 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 .
- */
-package org.linphone.activities.voip.views
-
-import android.content.Context
-import android.graphics.Canvas
-import android.graphics.Color
-import android.graphics.Paint
-import android.graphics.Rect
-import android.util.AttributeSet
-import android.view.View
-import android.widget.HorizontalScrollView
-import java.lang.Exception
-import kotlin.math.ceil
-import kotlin.math.roundToInt
-import org.linphone.R
-import org.linphone.core.tools.Log
-import org.linphone.utils.AppUtils
-
-class HorizontalScrollDotsView : View {
- private var count = 2
- private var selected = 0
-
- private var radius: Float = 5f
- private var margin: Float = 2f
- private var screenWidth: Float = 0f
- private var itemWidth: Float = 0f
-
- private lateinit var dotPaint: Paint
- private lateinit var selectedDotPaint: Paint
-
- private var horizontalScrollViewRef = 0
- private lateinit var horizontalScrollView: HorizontalScrollView
- private val scrollListener = OnScrollChangeListener { v, scrollX, _, _, _ ->
- val childWidth: Int = (v as HorizontalScrollView).getChildAt(0).measuredWidth
- val scrollViewWidth = v.measuredWidth
- val scrollableX = childWidth - scrollViewWidth
-
- if (scrollableX > 0) {
- val percent = (scrollX.toFloat() * 100 / scrollableX).toDouble()
- if (count > 1) {
- val selectedDot = percent / (100 / (count - 1))
- val dot = selectedDot.roundToInt()
- if (dot != selected) {
- setSelectedDot(dot)
- }
- }
- }
- }
-
- constructor(context: Context) : super(context) { init(context) }
-
- constructor(context: Context, attrs: AttributeSet) : this(context, attrs, 0)
-
- constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(
- context,
- attrs,
- defStyleAttr
- ) {
- init(context)
-
- context.theme.obtainStyledAttributes(
- attrs,
- R.styleable.HorizontalScrollDot,
- defStyleAttr, 0
- ).apply {
- try {
- radius = getDimension(R.styleable.HorizontalScrollDot_dotRadius, 5f)
-
- count = getInt(R.styleable.HorizontalScrollDot_dotCount, 1)
-
- val color = getColor(R.styleable.HorizontalScrollDot_dotColor, context.resources.getColor(R.color.voip_gray_dots))
- dotPaint.color = color
- val selectedColor = getColor(R.styleable.HorizontalScrollDot_selectedDotColor, context.resources.getColor(R.color.voip_dark_gray))
- selectedDotPaint.color = selectedColor
-
- selected = getInt(R.styleable.HorizontalScrollDot_selectedDot, 1)
-
- horizontalScrollViewRef = getResourceId(R.styleable.HorizontalScrollDot_horizontalScrollView, 0)
- Log.d("[Horizontal Scroll Dots] HorizontalScrollView reference set is $horizontalScrollViewRef")
-
- invalidate()
- } catch (e: Exception) {
- Log.e("[Horizontal Scroll Dots] $e")
- } finally {
- recycle()
- }
- }
- }
-
- fun init(context: Context) {
- radius = AppUtils.dpToPixels(context, 5f)
- margin = AppUtils.dpToPixels(context, 5f)
-
- dotPaint = Paint()
- dotPaint.color = Color.parseColor("#D8D8D8")
- selectedDotPaint = Paint()
- selectedDotPaint.color = Color.parseColor("#4B5964")
-
- val screenRect = Rect()
- getWindowVisibleDisplayFrame(screenRect)
- screenWidth = screenRect.width().toFloat()
- val marginBetweenItems = context.resources.getDimension(R.dimen.voip_active_speaker_miniature_margin)
- itemWidth = context.resources.getDimension(R.dimen.voip_active_speaker_miniature_size) + marginBetweenItems
- Log.d("[Horizontal Scroll Dots] Screen width is $screenWidth and item width is $itemWidth")
- }
-
- override fun onAttachedToWindow() {
- super.onAttachedToWindow()
-
- if (horizontalScrollViewRef > 0) {
- try {
- horizontalScrollView = (parent as View).findViewById(horizontalScrollViewRef)
- horizontalScrollView.setOnScrollChangeListener(scrollListener)
- Log.d("[Horizontal Scroll Dots] HorizontalScrollView scroll listener set")
- } catch (e: Exception) {
- Log.e("[Horizontal Scroll Dots] Failed to find HorizontalScrollView from id $horizontalScrollViewRef: $e")
- }
- } else {
- Log.e("[Horizontal Scroll Dots] No HorizontalScrollView reference given")
- }
- }
-
- override fun onDraw(canvas: Canvas) {
- super.onDraw(canvas)
-
- for (i in 0 until count) {
- if (i == selected) {
- canvas.drawCircle(
- (i + 1) * margin + (i * 2 + 1) * radius,
- radius,
- radius,
- selectedDotPaint
- )
- } else {
- canvas.drawCircle(
- (i + 1) * margin + (i * 2 + 1) * radius,
- radius,
- radius,
- dotPaint
- )
- }
- }
- }
-
- override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec)
-
- val width = ((radius * 2 + margin) * count + margin).toInt()
- val height: Int = (radius * 2).toInt()
-
- setMeasuredDimension(width, height)
- }
-
- private fun setDotCount(count: Int) {
- this.count = count
- requestLayout()
- invalidate()
- }
-
- fun setItemCount(items: Int) {
- val itemsPerScreen = (screenWidth / itemWidth)
- val dots = ceil(items.toDouble() / itemsPerScreen).toInt()
-
- Log.d("[Horizontal Scroll Dots] Calculated $count for $items items ($itemsPerScreen items fit in screen width), given that screen width is $screenWidth and item width is $itemWidth")
- setDotCount(dots)
- }
-
- fun setSelectedDot(index: Int) {
- selected = index
- invalidate()
- }
-}
diff --git a/app/src/main/java/org/linphone/activities/voip/views/ScrollDotsView.kt b/app/src/main/java/org/linphone/activities/voip/views/ScrollDotsView.kt
new file mode 100644
index 000000000..c3c8e9296
--- /dev/null
+++ b/app/src/main/java/org/linphone/activities/voip/views/ScrollDotsView.kt
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 2010-2021 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 .
+ */
+package org.linphone.activities.voip.views
+
+import android.content.Context
+import android.graphics.Canvas
+import android.graphics.Color
+import android.graphics.Paint
+import android.graphics.Rect
+import android.util.AttributeSet
+import android.view.View
+import android.view.View.OnScrollChangeListener
+import android.widget.FrameLayout
+import android.widget.HorizontalScrollView
+import android.widget.ScrollView
+import kotlin.math.ceil
+import kotlin.math.roundToInt
+import org.linphone.R
+import org.linphone.core.tools.Log
+import org.linphone.utils.AppUtils
+
+class ScrollDotsView : View {
+ private var count = 2
+ private var selected = 0
+
+ private var radius: Float = 5f
+ private var margin: Float = 2f
+
+ private var screenWidth: Float = 0f
+ private var itemWidth: Float = 0f
+ private var screenHeight: Float = 0f
+ private var itemHeight: Float = 0f
+
+ private lateinit var dotPaint: Paint
+ private lateinit var selectedDotPaint: Paint
+
+ private var scrollViewRef = 0
+ private lateinit var scrollView: FrameLayout
+ private var isHorizontal = false
+
+ private val scrollListener = OnScrollChangeListener { v, scrollX, _, _, _ ->
+ if (isHorizontal) {
+ if (v !is HorizontalScrollView) {
+ Log.e("[Scoll Dots] ScrollView reference isn't a HorizontalScrollView!")
+ return@OnScrollChangeListener
+ }
+
+ val childWidth: Int = v.getChildAt(0).measuredWidth
+ val scrollViewWidth = v.measuredWidth
+ val scrollableX = childWidth - scrollViewWidth
+
+ if (scrollableX > 0) {
+ val percent = (scrollX.toFloat() * 100 / scrollableX).toDouble()
+ if (count > 1) {
+ val selectedDot = percent / (100 / (count - 1))
+ val dot = selectedDot.roundToInt()
+ if (dot != selected) {
+ setSelectedDot(dot)
+ }
+ }
+ }
+ } else {
+ if (v !is ScrollView) {
+ Log.e("[Scoll Dots] ScrollView reference isn't a ScrollView!")
+ return@OnScrollChangeListener
+ }
+
+ val childHeight: Int = v.getChildAt(0).measuredHeight
+ val scrollViewHeight = v.measuredHeight
+ val scrollableY = childHeight - scrollViewHeight
+
+ if (scrollableY > 0) {
+ val percent = (scrollY.toFloat() * 100 / scrollableY).toDouble()
+ if (count > 1) {
+ val selectedDot = percent / (100 / (count - 1))
+ val dot = selectedDot.roundToInt()
+ if (dot != selected) {
+ setSelectedDot(dot)
+ }
+ }
+ }
+ }
+ }
+
+ constructor(context: Context) : super(context) { init(context) }
+
+ constructor(context: Context, attrs: AttributeSet) : this(context, attrs, 0)
+
+ constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(
+ context,
+ attrs,
+ defStyleAttr
+ ) {
+ init(context)
+
+ context.theme.obtainStyledAttributes(
+ attrs,
+ R.styleable.ScrollDot,
+ defStyleAttr, 0
+ ).apply {
+ try {
+ radius = getDimension(R.styleable.ScrollDot_dotRadius, 5f)
+
+ count = getInt(R.styleable.ScrollDot_dotCount, 1)
+
+ val color = getColor(R.styleable.ScrollDot_dotColor, context.resources.getColor(R.color.voip_gray_dots))
+ dotPaint.color = color
+ val selectedColor = getColor(R.styleable.ScrollDot_selectedDotColor, context.resources.getColor(R.color.voip_dark_gray))
+ selectedDotPaint.color = selectedColor
+
+ selected = getInt(R.styleable.ScrollDot_selectedDot, 1)
+
+ scrollViewRef = getResourceId(R.styleable.ScrollDot_scrollView, 0)
+ Log.d("[Scroll Dots] ScrollView reference set is $scrollViewRef")
+
+ invalidate()
+ } catch (e: Exception) {
+ Log.e("[Scroll Dots] $e")
+ } finally {
+ recycle()
+ }
+ }
+ }
+
+ fun init(context: Context) {
+ radius = AppUtils.dpToPixels(context, 5f)
+ margin = AppUtils.dpToPixels(context, 5f)
+
+ dotPaint = Paint()
+ dotPaint.color = Color.parseColor("#D8D8D8")
+ selectedDotPaint = Paint()
+ selectedDotPaint.color = Color.parseColor("#4B5964")
+
+ val screenRect = Rect()
+ getWindowVisibleDisplayFrame(screenRect)
+ screenWidth = screenRect.width().toFloat()
+ screenHeight = screenRect.height().toFloat()
+
+ val marginBetweenItems = context.resources.getDimension(R.dimen.voip_active_speaker_miniature_margin)
+ itemWidth = context.resources.getDimension(R.dimen.voip_active_speaker_miniature_size) + marginBetweenItems
+ itemHeight = context.resources.getDimension(R.dimen.voip_active_speaker_miniature_size) + marginBetweenItems
+
+ Log.d("[Scroll Dots] Screen size is $screenWidth/$screenHeight and item size is $itemWidth/$itemHeight")
+ }
+
+ override fun onAttachedToWindow() {
+ super.onAttachedToWindow()
+
+ if (scrollViewRef > 0) {
+ try {
+ scrollView = (parent as View).findViewById(scrollViewRef)
+ scrollView.setOnScrollChangeListener(scrollListener)
+ Log.d("[Scroll Dots] ScrollView scroll listener set")
+
+ if (scrollView is HorizontalScrollView) {
+ isHorizontal = true
+ }
+ } catch (e: Exception) {
+ Log.e("[Scroll Dots] Failed to find ScrollView from id $scrollViewRef: $e")
+ }
+ } else {
+ Log.e("[Scroll Dots] No ScrollView reference given")
+ }
+ }
+
+ override fun onDraw(canvas: Canvas) {
+ super.onDraw(canvas)
+
+ for (i in 0 until count) {
+ if (i == selected) {
+ val position = (i + 1) * margin + (i * 2 + 1) * radius
+ canvas.drawCircle(
+ if (isHorizontal) position else radius,
+ if (isHorizontal) radius else position,
+ radius,
+ selectedDotPaint
+ )
+ } else {
+ val position = (i + 1) * margin + (i * 2 + 1) * radius
+ canvas.drawCircle(
+ if (isHorizontal) position else radius,
+ if (isHorizontal) radius else position,
+ radius,
+ dotPaint
+ )
+ }
+ }
+ }
+
+ override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec)
+
+ if (isHorizontal) {
+ val width = ((radius * 2 + margin) * count + margin).toInt()
+ val height: Int = (radius * 2).toInt()
+ setMeasuredDimension(width, height)
+ } else {
+ val height = ((radius * 2 + margin) * count + margin).toInt()
+ val width: Int = (radius * 2).toInt()
+ setMeasuredDimension(width, height)
+ }
+ }
+
+ private fun setDotCount(count: Int) {
+ this.count = count
+ requestLayout()
+ invalidate()
+ }
+
+ fun setItemCount(items: Int) {
+ if (isHorizontal) {
+ val itemsPerScreen = (screenWidth / itemWidth)
+ val dots = ceil(items.toDouble() / itemsPerScreen).toInt()
+ Log.d("[Scroll Dots] Calculated $count for $items items ($itemsPerScreen items fit in screen width), given that screen width is $screenWidth and item width is $itemWidth")
+ setDotCount(dots)
+ } else {
+ val itemsPerScreen = (screenHeight / itemHeight)
+ val dots = ceil(items.toDouble() / itemsPerScreen).toInt()
+ Log.d("[Vertical Scroll Dots] Calculated $count for $items items ($itemsPerScreen items fit in screen height), given that screen height is $screenHeight and item height is $itemHeight")
+ setDotCount(dots)
+ }
+ }
+
+ fun setSelectedDot(index: Int) {
+ selected = index
+ invalidate()
+ }
+}
diff --git a/app/src/main/java/org/linphone/utils/DataBindingUtils.kt b/app/src/main/java/org/linphone/utils/DataBindingUtils.kt
index a469dcacb..3ffca9698 100644
--- a/app/src/main/java/org/linphone/utils/DataBindingUtils.kt
+++ b/app/src/main/java/org/linphone/utils/DataBindingUtils.kt
@@ -50,7 +50,7 @@ import org.linphone.R
import org.linphone.activities.GenericActivity
import org.linphone.activities.main.settings.SettingListener
import org.linphone.activities.voip.data.ConferenceParticipantDeviceData
-import org.linphone.activities.voip.views.HorizontalScrollDotsView
+import org.linphone.activities.voip.views.ScrollDotsView
import org.linphone.contact.ContactAvatarGenerator
import org.linphone.contact.ContactDataInterface
import org.linphone.contact.getPictureUri
@@ -641,6 +641,14 @@ fun setConstraintLayoutMargins(view: View, margins: Float) {
view.layoutParams = params
}
+@BindingAdapter("android:layout_marginTop")
+fun setConstraintLayoutTopMargin(view: View, margins: Float) {
+ val params = view.layoutParams as ConstraintLayout.LayoutParams
+ val m = margins.toInt()
+ params.setMargins(params.leftMargin, m, params.rightMargin, params.bottomMargin)
+ view.layoutParams = params
+}
+
@BindingAdapter("android:onTouch")
fun View.setTouchListener(listener: View.OnTouchListener) {
setOnTouchListener(listener)
@@ -691,11 +699,11 @@ fun setParticipantTextureView(
}
@BindingAdapter("itemCount")
-fun HorizontalScrollDotsView.setItems(count: Int) {
+fun ScrollDotsView.setItems(count: Int) {
setItemCount(count)
}
@BindingAdapter("selectedDot")
-fun HorizontalScrollDotsView.setSelectedIndex(index: Int) {
+fun ScrollDotsView.setSelectedIndex(index: Int) {
setSelectedDot(index)
}
diff --git a/app/src/main/res/layout-land/voip_conference_active_speaker.xml b/app/src/main/res/layout-land/voip_conference_active_speaker.xml
new file mode 100644
index 000000000..d27dd6cf7
--- /dev/null
+++ b/app/src/main/res/layout-land/voip_conference_active_speaker.xml
@@ -0,0 +1,142 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/voip_conference_active_speaker.xml b/app/src/main/res/layout/voip_conference_active_speaker.xml
index 1b3e26c1b..b0f5c194e 100644
--- a/app/src/main/res/layout/voip_conference_active_speaker.xml
+++ b/app/src/main/res/layout/voip_conference_active_speaker.xml
@@ -25,20 +25,6 @@
android:layout_margin="@{controlsViewModel.fullScreenMode || controlsViewModel.pipMode ? @dimen/voip_remote_margin_full_screen : @dimen/voip_remote_margin, default=@dimen/voip_remote_margin}"
android:visibility="@{inflatedVisibility}">
-
-
-
-
@@ -86,7 +71,7 @@
android:contentDescription="@null"
coilVoipContact="@{conferenceViewModel.speakingParticipant}"
app:layout_constraintDimensionRatio="1:1"
- app:layout_constraintBottom_toTopOf="@id/bottom_barrier"
+ app:layout_constraintBottom_toTopOf="@id/miniatures"
app:layout_constraintEnd_toEndOf="@id/active_speaker_background"
app:layout_constraintHeight_max="@dimen/voip_contact_avatar_max_size"
app:layout_constraintStart_toStartOf="@id/active_speaker_background"
@@ -114,21 +99,13 @@
app:layout_constraintBottom_toBottomOf="@id/active_speaker_background"
app:layout_constraintStart_toStartOf="@id/active_speaker_background" />
-
-
-
diff --git a/app/src/main/res/layout/voip_conference_participant_remote_active_speaker_miniature.xml b/app/src/main/res/layout/voip_conference_participant_remote_active_speaker_miniature.xml
index f08059e08..a4d5921e9 100644
--- a/app/src/main/res/layout/voip_conference_participant_remote_active_speaker_miniature.xml
+++ b/app/src/main/res/layout/voip_conference_participant_remote_active_speaker_miniature.xml
@@ -14,8 +14,7 @@
diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml
index 7fbee54c0..c3f0bf67d 100644
--- a/app/src/main/res/values/attrs.xml
+++ b/app/src/main/res/values/attrs.xml
@@ -75,13 +75,13 @@
-
+
-
+
\ No newline at end of file
diff --git a/app/src/main/res/values/dimen.xml b/app/src/main/res/values/dimen.xml
index b655a1147..aeb8a9735 100644
--- a/app/src/main/res/values/dimen.xml
+++ b/app/src/main/res/values/dimen.xml
@@ -61,11 +61,13 @@
30dp
25dp
137dp
- 200dp
+ 180dp
80sp
60dp
80dp
40dp
1dp
280dp
+ 10dp
+ 0dp
\ No newline at end of file