Added active speaker landscape layout changes
This commit is contained in:
parent
e2a70c33e8
commit
eb634c74e7
8 changed files with 410 additions and 227 deletions
|
@ -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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
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()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
}
|
|
@ -50,7 +50,7 @@ import org.linphone.R
|
||||||
import org.linphone.activities.GenericActivity
|
import org.linphone.activities.GenericActivity
|
||||||
import org.linphone.activities.main.settings.SettingListener
|
import org.linphone.activities.main.settings.SettingListener
|
||||||
import org.linphone.activities.voip.data.ConferenceParticipantDeviceData
|
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.ContactAvatarGenerator
|
||||||
import org.linphone.contact.ContactDataInterface
|
import org.linphone.contact.ContactDataInterface
|
||||||
import org.linphone.contact.getPictureUri
|
import org.linphone.contact.getPictureUri
|
||||||
|
@ -641,6 +641,14 @@ fun setConstraintLayoutMargins(view: View, margins: Float) {
|
||||||
view.layoutParams = params
|
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")
|
@BindingAdapter("android:onTouch")
|
||||||
fun View.setTouchListener(listener: View.OnTouchListener) {
|
fun View.setTouchListener(listener: View.OnTouchListener) {
|
||||||
setOnTouchListener(listener)
|
setOnTouchListener(listener)
|
||||||
|
@ -691,11 +699,11 @@ fun setParticipantTextureView(
|
||||||
}
|
}
|
||||||
|
|
||||||
@BindingAdapter("itemCount")
|
@BindingAdapter("itemCount")
|
||||||
fun HorizontalScrollDotsView.setItems(count: Int) {
|
fun ScrollDotsView.setItems(count: Int) {
|
||||||
setItemCount(count)
|
setItemCount(count)
|
||||||
}
|
}
|
||||||
|
|
||||||
@BindingAdapter("selectedDot")
|
@BindingAdapter("selectedDot")
|
||||||
fun HorizontalScrollDotsView.setSelectedIndex(index: Int) {
|
fun ScrollDotsView.setSelectedIndex(index: Int) {
|
||||||
setSelectedDot(index)
|
setSelectedDot(index)
|
||||||
}
|
}
|
||||||
|
|
142
app/src/main/res/layout-land/voip_conference_active_speaker.xml
Normal file
142
app/src/main/res/layout-land/voip_conference_active_speaker.xml
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<data>
|
||||||
|
|
||||||
|
<import type="android.view.View" />
|
||||||
|
|
||||||
|
<variable
|
||||||
|
name="conferenceViewModel"
|
||||||
|
type="org.linphone.activities.voip.viewmodels.ConferenceViewModel" />
|
||||||
|
|
||||||
|
<variable
|
||||||
|
name="controlsViewModel"
|
||||||
|
type="org.linphone.activities.voip.viewmodels.ControlsViewModel" />
|
||||||
|
|
||||||
|
<variable
|
||||||
|
name="inflatedVisibility"
|
||||||
|
type="Integer" />
|
||||||
|
</data>
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
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}">
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/header"
|
||||||
|
layout="@layout/voip_conference_header"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
android:visibility="@{controlsViewModel.fullScreenMode || controlsViewModel.pipMode ? View.GONE : View.VISIBLE}"
|
||||||
|
app:conferenceViewModel="@{conferenceViewModel}" />
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/remote_recording"
|
||||||
|
layout="@layout/voip_remote_recording"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/header"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
android:visibility="@{conferenceViewModel.isRemotelyRecorded ? View.VISIBLE : View.GONE, default=gone}" />
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.Barrier
|
||||||
|
android:id="@+id/top_barrier"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:barrierDirection="bottom"
|
||||||
|
app:constraint_referenced_ids="header, remote_recording"/>
|
||||||
|
|
||||||
|
<org.linphone.activities.voip.views.ScrollDotsView
|
||||||
|
android:id="@+id/scroll_indicator"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="@{controlsViewModel.pipMode ? View.GONE : View.VISIBLE}"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/top_barrier"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
android:layout_marginEnd="5dp"
|
||||||
|
app:dotColor="@color/voip_gray_dots"
|
||||||
|
app:dotRadius="5dp"
|
||||||
|
app:scrollView="@id/miniatures"
|
||||||
|
app:itemCount="@{conferenceViewModel.conferenceParticipantDevices.size()}"
|
||||||
|
app:selectedDot="@{0}"
|
||||||
|
app:selectedDotColor="@color/voip_dark_gray" />
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
android:id="@+id/miniatures"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginTop="5dp"
|
||||||
|
android:layout_marginBottom="5dp"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/top_barrier"
|
||||||
|
app:layout_constraintEnd_toStartOf="@id/scroll_indicator"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
android:scrollbars="none">
|
||||||
|
|
||||||
|
<com.google.android.flexbox.FlexboxLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:alignItems="stretch"
|
||||||
|
app:entries="@{conferenceViewModel.conferenceParticipantDevices}"
|
||||||
|
app:flexDirection="column"
|
||||||
|
app:flexWrap="nowrap"
|
||||||
|
app:justifyContent="flex_start"
|
||||||
|
app:layout="@{@layout/voip_conference_participant_remote_active_speaker_miniature}" />
|
||||||
|
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/active_speaker_background"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/top_barrier"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toStartOf="@id/miniatures"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
android:layout_marginTop="@{controlsViewModel.fullScreenMode ? @dimen/margin_0dp : @dimen/voip_active_speaker_top_margin, default=@dimen/voip_active_speaker_top_margin}"
|
||||||
|
android:background="@drawable/shape_remote_background"
|
||||||
|
android:onClick="@{() -> controlsViewModel.toggleFullScreen()}"/>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/speaking_participant_avatar"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:contentDescription="@null"
|
||||||
|
coilVoipContact="@{conferenceViewModel.speakingParticipant}"
|
||||||
|
app:layout_constraintDimensionRatio="1:1"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/active_speaker_background"
|
||||||
|
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"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/active_speaker_background"
|
||||||
|
app:layout_constraintWidth_max="@dimen/voip_contact_avatar_max_size" />
|
||||||
|
|
||||||
|
<org.linphone.activities.voip.views.RoundCornersTextureView
|
||||||
|
android:id="@+id/conference_active_speaker_remote_video"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:visibility="@{!conferenceViewModel.isConferenceLocallyPaused && conferenceViewModel.speakingParticipant.videoEnabled ? View.VISIBLE : View.GONE}"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/active_speaker_background"
|
||||||
|
app:layout_constraintEnd_toEndOf="@id/active_speaker_background"
|
||||||
|
app:layout_constraintStart_toStartOf="@id/active_speaker_background"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/active_speaker_background" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/speaking_participant_name"
|
||||||
|
style="@style/call_remote_name_font"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:layout_marginBottom="10dp"
|
||||||
|
android:text="@{conferenceViewModel.speakingParticipant.contact.name ?? conferenceViewModel.speakingParticipant.displayName}"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/active_speaker_background"
|
||||||
|
app:layout_constraintStart_toStartOf="@id/active_speaker_background" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
</layout>
|
|
@ -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:layout_margin="@{controlsViewModel.fullScreenMode || controlsViewModel.pipMode ? @dimen/voip_remote_margin_full_screen : @dimen/voip_remote_margin, default=@dimen/voip_remote_margin}"
|
||||||
android:visibility="@{inflatedVisibility}">
|
android:visibility="@{inflatedVisibility}">
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.Guideline
|
|
||||||
android:id="@+id/hinge_top"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
app:layout_constraintGuide_percent="0" />
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.Guideline
|
|
||||||
android:id="@+id/hinge_bottom"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
app:layout_constraintGuide_percent="1" />
|
|
||||||
|
|
||||||
<include
|
<include
|
||||||
android:id="@+id/header"
|
android:id="@+id/header"
|
||||||
layout="@layout/voip_conference_header"
|
layout="@layout/voip_conference_header"
|
||||||
|
@ -72,9 +58,8 @@
|
||||||
app:layout_constraintTop_toBottomOf="@id/top_barrier"
|
app:layout_constraintTop_toBottomOf="@id/top_barrier"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintBottom_toTopOf="@id/bottom_barrier"
|
app:layout_constraintBottom_toTopOf="@id/miniatures"
|
||||||
android:layout_marginTop="10dp"
|
android:layout_marginTop="@{controlsViewModel.fullScreenMode ? @dimen/margin_0dp : @dimen/voip_active_speaker_top_margin, default=@dimen/voip_active_speaker_top_margin}"
|
||||||
android:layout_marginBottom="10dp"
|
|
||||||
android:background="@drawable/shape_remote_background"
|
android:background="@drawable/shape_remote_background"
|
||||||
android:onClick="@{() -> controlsViewModel.toggleFullScreen()}"/>
|
android:onClick="@{() -> controlsViewModel.toggleFullScreen()}"/>
|
||||||
|
|
||||||
|
@ -86,7 +71,7 @@
|
||||||
android:contentDescription="@null"
|
android:contentDescription="@null"
|
||||||
coilVoipContact="@{conferenceViewModel.speakingParticipant}"
|
coilVoipContact="@{conferenceViewModel.speakingParticipant}"
|
||||||
app:layout_constraintDimensionRatio="1:1"
|
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_constraintEnd_toEndOf="@id/active_speaker_background"
|
||||||
app:layout_constraintHeight_max="@dimen/voip_contact_avatar_max_size"
|
app:layout_constraintHeight_max="@dimen/voip_contact_avatar_max_size"
|
||||||
app:layout_constraintStart_toStartOf="@id/active_speaker_background"
|
app:layout_constraintStart_toStartOf="@id/active_speaker_background"
|
||||||
|
@ -114,21 +99,13 @@
|
||||||
app:layout_constraintBottom_toBottomOf="@id/active_speaker_background"
|
app:layout_constraintBottom_toBottomOf="@id/active_speaker_background"
|
||||||
app:layout_constraintStart_toStartOf="@id/active_speaker_background" />
|
app:layout_constraintStart_toStartOf="@id/active_speaker_background" />
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.Barrier
|
|
||||||
android:id="@+id/bottom_barrier"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
app:barrierDirection="top"
|
|
||||||
app:constraint_referenced_ids="hinge_bottom, miniatures" />
|
|
||||||
|
|
||||||
<HorizontalScrollView
|
<HorizontalScrollView
|
||||||
android:id="@+id/miniatures"
|
android:id="@+id/miniatures"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="@dimen/voip_active_speaker_miniature_size"
|
android:layout_height="wrap_content"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintBottom_toTopOf="@id/scroll_indicator"
|
app:layout_constraintBottom_toTopOf="@id/scroll_indicator"
|
||||||
android:layout_marginBottom="5dp"
|
|
||||||
android:scrollbars="none">
|
android:scrollbars="none">
|
||||||
|
|
||||||
<com.google.android.flexbox.FlexboxLayout
|
<com.google.android.flexbox.FlexboxLayout
|
||||||
|
@ -143,7 +120,7 @@
|
||||||
|
|
||||||
</HorizontalScrollView>
|
</HorizontalScrollView>
|
||||||
|
|
||||||
<org.linphone.activities.voip.views.HorizontalScrollDotsView
|
<org.linphone.activities.voip.views.ScrollDotsView
|
||||||
android:id="@+id/scroll_indicator"
|
android:id="@+id/scroll_indicator"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -154,7 +131,7 @@
|
||||||
android:layout_marginBottom="5dp"
|
android:layout_marginBottom="5dp"
|
||||||
app:dotColor="@color/voip_gray_dots"
|
app:dotColor="@color/voip_gray_dots"
|
||||||
app:dotRadius="5dp"
|
app:dotRadius="5dp"
|
||||||
app:horizontalScrollView="@id/miniatures"
|
app:scrollView="@id/miniatures"
|
||||||
app:itemCount="@{conferenceViewModel.conferenceParticipantDevices.size()}"
|
app:itemCount="@{conferenceViewModel.conferenceParticipantDevices.size()}"
|
||||||
app:selectedDot="@{0}"
|
app:selectedDot="@{0}"
|
||||||
app:selectedDotColor="@color/voip_dark_gray" />
|
app:selectedDotColor="@color/voip_dark_gray" />
|
||||||
|
|
|
@ -14,8 +14,7 @@
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:layout_width="@dimen/voip_active_speaker_miniature_size"
|
android:layout_width="@dimen/voip_active_speaker_miniature_size"
|
||||||
android:layout_height="@dimen/voip_active_speaker_miniature_size"
|
android:layout_height="@dimen/voip_active_speaker_miniature_size"
|
||||||
android:layout_marginStart="5dp"
|
android:layout_margin="5dp"
|
||||||
android:layout_marginEnd="5dp"
|
|
||||||
android:background="@{!data.isInConference ? @drawable/shape_remote_paused_background : data.videoEnabled ? @drawable/shape_remote_video_background : @drawable/shape_remote_background, default=@drawable/shape_remote_background}"
|
android:background="@{!data.isInConference ? @drawable/shape_remote_paused_background : data.videoEnabled ? @drawable/shape_remote_video_background : @drawable/shape_remote_background, default=@drawable/shape_remote_background}"
|
||||||
app:layout_alignSelf="flex_end"
|
app:layout_alignSelf="flex_end"
|
||||||
app:layout_flexShrink="0">
|
app:layout_flexShrink="0">
|
||||||
|
|
|
@ -75,13 +75,13 @@
|
||||||
</attr>
|
</attr>
|
||||||
</declare-styleable>
|
</declare-styleable>
|
||||||
|
|
||||||
<declare-styleable name="HorizontalScrollDot">
|
<declare-styleable name="ScrollDot">
|
||||||
<attr name="dotCount" format="integer" />
|
<attr name="dotCount" format="integer" />
|
||||||
<attr name="itemCount" format="integer" />
|
<attr name="itemCount" format="integer" />
|
||||||
<attr name="dotColor" format="color" />
|
<attr name="dotColor" format="color" />
|
||||||
<attr name="selectedDotColor" format="color" />
|
<attr name="selectedDotColor" format="color" />
|
||||||
<attr name="selectedDot" format="integer" />
|
<attr name="selectedDot" format="integer" />
|
||||||
<attr name="dotRadius" format="dimension" />
|
<attr name="dotRadius" format="dimension" />
|
||||||
<attr name="horizontalScrollView" format="reference" />
|
<attr name="scrollView" format="reference" />
|
||||||
</declare-styleable>
|
</declare-styleable>
|
||||||
</resources>
|
</resources>
|
|
@ -61,11 +61,13 @@
|
||||||
<dimen name="voip_conference_participant_mic_muted_icon_size_grid">30dp</dimen>
|
<dimen name="voip_conference_participant_mic_muted_icon_size_grid">30dp</dimen>
|
||||||
<dimen name="voip_conference_participant_mic_muted_icon_size_active_speaker">25dp</dimen>
|
<dimen name="voip_conference_participant_mic_muted_icon_size_active_speaker">25dp</dimen>
|
||||||
<dimen name="voip_dialog_button_max_width">137dp</dimen>
|
<dimen name="voip_dialog_button_max_width">137dp</dimen>
|
||||||
<dimen name="voip_contact_avatar_max_size">200dp</dimen>
|
<dimen name="voip_contact_avatar_max_size">180dp</dimen>
|
||||||
<dimen name="voip_contact_avatar_text_size">80sp</dimen>
|
<dimen name="voip_contact_avatar_text_size">80sp</dimen>
|
||||||
<dimen name="voip_numpad_button_max_size">60dp</dimen>
|
<dimen name="voip_numpad_button_max_size">60dp</dimen>
|
||||||
<dimen name="voip_conference_audio_only_participant_cell_height">80dp</dimen>
|
<dimen name="voip_conference_audio_only_participant_cell_height">80dp</dimen>
|
||||||
<dimen name="voip_conference_audio_only_participant_avatar_size">40dp</dimen>
|
<dimen name="voip_conference_audio_only_participant_avatar_size">40dp</dimen>
|
||||||
<dimen name="conference_schedule_form_field_border_thickness">1dp</dimen>
|
<dimen name="conference_schedule_form_field_border_thickness">1dp</dimen>
|
||||||
<dimen name="master_fragment_width">280dp</dimen>
|
<dimen name="master_fragment_width">280dp</dimen>
|
||||||
|
<dimen name="voip_active_speaker_top_margin">10dp</dimen>
|
||||||
|
<dimen name="margin_0dp">0dp</dimen>
|
||||||
</resources>
|
</resources>
|
Loading…
Reference in a new issue