Swipe spaces bottom bar
Change-Id: Ib15b3b28f5f429e73cf80130dc575ae2111a1cef
This commit is contained in:
parent
3b6821d627
commit
43d77f553e
|
@ -25,6 +25,7 @@ import android.view.ViewGroup
|
|||
import android.view.ViewTreeObserver
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import com.airbnb.mvrx.UniqueOnly
|
||||
|
@ -60,6 +61,8 @@ import im.vector.app.features.home.room.list.RoomListFragment
|
|||
import im.vector.app.features.home.room.list.RoomListParams
|
||||
import im.vector.app.features.home.room.list.RoomListSectionBuilder.Companion.SPACE_ID_FOLLOW_APP
|
||||
import im.vector.app.features.home.room.list.UnreadCounterBadgeView
|
||||
import im.vector.app.features.home.room.list.home.spacebar.SpaceBarController
|
||||
import im.vector.app.features.home.room.list.home.spacebar.SpaceBarData
|
||||
import im.vector.app.features.popup.PopupAlertManager
|
||||
import im.vector.app.features.popup.VerificationVectorAlert
|
||||
import im.vector.app.features.settings.VectorLocaleProvider
|
||||
|
@ -69,6 +72,7 @@ import im.vector.app.features.themes.ThemeUtils
|
|||
import im.vector.app.features.workers.signout.BannerState
|
||||
import im.vector.app.features.workers.signout.ServerBackupStatusAction
|
||||
import im.vector.app.features.workers.signout.ServerBackupStatusViewModel
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
import timber.log.Timber
|
||||
|
@ -90,6 +94,7 @@ class HomeDetailFragment :
|
|||
@Inject lateinit var vectorPreferences: VectorPreferences
|
||||
@Inject lateinit var spaceStateHandler: SpaceStateHandler
|
||||
@Inject lateinit var vectorLocale: VectorLocaleProvider
|
||||
@Inject lateinit var spaceBarController: SpaceBarController
|
||||
|
||||
private val DEBUG_VIEW_PAGER = DbgUtil.isDbgEnabled(DbgUtil.DBG_VIEW_PAGER)
|
||||
private val viewPagerDimber = Dimber("Home pager", DbgUtil.DBG_VIEW_PAGER)
|
||||
|
@ -145,6 +150,16 @@ class HomeDetailFragment :
|
|||
|
||||
private val currentCallsViewPresenter = CurrentCallsViewPresenter()
|
||||
|
||||
private val spaceBarListener = object: SpaceBarController.SpaceBarListener {
|
||||
override fun onSpaceBarSelectSpace(space: RoomSummary?) {
|
||||
spaceStateHandler.setCurrentSpace(space?.roomId, from = SelectSpaceFrom.SELECT)
|
||||
}
|
||||
override fun onSpaceBarLongPressSpace(space: RoomSummary?): Boolean {
|
||||
sharedActionViewModel.post(HomeActivitySharedAction.OpenDrawer)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
sharedActionViewModel = activityViewModelProvider.get(HomeSharedActionViewModel::class.java)
|
||||
|
@ -156,6 +171,12 @@ class HomeDetailFragment :
|
|||
|
||||
checkNotificationTabStatus()
|
||||
|
||||
val spaceBarAdapter = spaceBarController.also { controller ->
|
||||
controller.spaceRoomListener = spaceBarListener
|
||||
}.adapter
|
||||
views.spaceBarRecyclerView.layoutManager = LinearLayoutManager(context)
|
||||
views.spaceBarRecyclerView.adapter = spaceBarAdapter
|
||||
|
||||
// Reduce sensitivity of viewpager to avoid scrolling horizontally by accident too easily
|
||||
views.roomListContainerPager.reduceDragSensitivity(4)
|
||||
|
||||
|
@ -226,7 +247,9 @@ class HomeDetailFragment :
|
|||
highlighted = state.otherSpacesUnread.isHighlight,
|
||||
unread = state.otherSpacesUnread.unreadCount,
|
||||
markedUnread = false
|
||||
)
|
||||
).also {
|
||||
spaceBarController.submitHomeUnreadCounts(it)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -239,7 +262,7 @@ class HomeDetailFragment :
|
|||
// Uninitialized
|
||||
return@onEach
|
||||
}
|
||||
setupViewPager(selectedSpace, rootSpacesOrdered, currentTab)
|
||||
setupViewPager(selectedSpace, rootSpacesOrdered , currentTab)
|
||||
previousSelectedSpacePair = selectedSpace
|
||||
}
|
||||
|
||||
|
@ -280,6 +303,9 @@ class HomeDetailFragment :
|
|||
|
||||
override fun onDestroyView() {
|
||||
currentCallsViewPresenter.unBind()
|
||||
|
||||
spaceBarController.spaceRoomListener = null
|
||||
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
|
@ -433,6 +459,9 @@ class HomeDetailFragment :
|
|||
}
|
||||
|
||||
private fun onSpaceChange(spaceSummary: RoomSummary?) {
|
||||
if (pagerPagingEnabled) {
|
||||
spaceBarController.selectSpace(spaceSummary)
|
||||
}
|
||||
if (spaceSummary == null) {
|
||||
views.groupToolbarSpaceTitleView.isVisible = false
|
||||
} else {
|
||||
|
@ -441,6 +470,11 @@ class HomeDetailFragment :
|
|||
}
|
||||
}
|
||||
|
||||
private fun setCurrentPagerItem(index: Int, smoothScroll: Boolean) {
|
||||
views.roomListContainerPager.setCurrentItem(index, smoothScroll)
|
||||
spaceBarController.scrollToSpacePosition(index)
|
||||
}
|
||||
|
||||
private fun setupKeysBackupBanner() {
|
||||
serverBackupStatusViewModel.handle(ServerBackupStatusAction.OnBannerDisplayed)
|
||||
serverBackupStatusViewModel
|
||||
|
@ -556,6 +590,12 @@ class HomeDetailFragment :
|
|||
getPageIndexForSpaceId(selectedSpaceId, unsafeSpaces)
|
||||
}
|
||||
val pagingEnabled = pagingAllowed && unsafeSpaces.isNotEmpty() && selectedIndex != null
|
||||
if (pagingEnabled) {
|
||||
views.spaceBarRecyclerView.isVisible = true
|
||||
spaceBarController.submitData(SpaceBarData(spaces?.let { listOf<RoomSummary?>(null) + it }, selectedSpace))
|
||||
} else {
|
||||
views.spaceBarRecyclerView.isVisible = false
|
||||
}
|
||||
val safeSpaces = if (pagingEnabled) unsafeSpaces else listOf()
|
||||
// Check if we need to recreate the adapter for a new tab
|
||||
if (oldAdapter != null) {
|
||||
|
@ -582,7 +622,7 @@ class HomeDetailFragment :
|
|||
// Do not smooth scroll large distances to avoid loading unnecessary many room lists
|
||||
val diff = selectedIndex - views.roomListContainerPager.currentItem
|
||||
val smoothScroll = abs(diff) <= 1
|
||||
views.roomListContainerPager.setCurrentItem(selectedIndex, smoothScroll)
|
||||
setCurrentPagerItem(selectedIndex, smoothScroll)
|
||||
}
|
||||
}
|
||||
return
|
||||
|
@ -656,7 +696,7 @@ class HomeDetailFragment :
|
|||
}
|
||||
try {
|
||||
viewPagerDimber.i{"Home pager: set initial page $selectedIndex"}
|
||||
views.roomListContainerPager.setCurrentItem(selectedIndex ?: 0, false)
|
||||
setCurrentPagerItem(selectedIndex ?: 0, false)
|
||||
initialPageSelected = true
|
||||
} catch (e: Exception) {
|
||||
Timber.e("Home pager: Could not set initial page after creating adapter: $e")
|
||||
|
|
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* Copyright (c) 2022 New Vector Ltd
|
||||
* Copyright (c) 2022 SpiritCroc
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.features.home.room.list.home.spacebar
|
||||
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.airbnb.epoxy.Carousel
|
||||
import com.airbnb.epoxy.CarouselModelBuilder
|
||||
import com.airbnb.epoxy.EpoxyController
|
||||
import com.airbnb.epoxy.EpoxyModel
|
||||
import com.airbnb.epoxy.carousel
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
import im.vector.app.features.home.AvatarRenderer
|
||||
import im.vector.app.features.home.room.list.UnreadCounterBadgeView
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
import org.matrix.android.sdk.api.util.toMatrixItem
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
class SpaceBarController @Inject constructor(
|
||||
val stringProvider: StringProvider,
|
||||
private val avatarRenderer: AvatarRenderer,
|
||||
) : EpoxyController() {
|
||||
|
||||
private var data: SpaceBarData = SpaceBarData()
|
||||
private var topLevelUnreadCounts: UnreadCounterBadgeView.State.Count = UnreadCounterBadgeView.State.Count(0, false, 0, false)
|
||||
|
||||
interface SpaceBarListener {
|
||||
fun onSpaceBarSelectSpace(space: RoomSummary?)
|
||||
fun onSpaceBarLongPressSpace(space: RoomSummary?): Boolean
|
||||
}
|
||||
var spaceRoomListener: SpaceBarListener? = null
|
||||
|
||||
private var carousel: Carousel? = null
|
||||
|
||||
override fun buildModels() {
|
||||
val host = this
|
||||
data.spaces?.let {
|
||||
addSpaces(host, it, data.selectedSpace)
|
||||
}
|
||||
}
|
||||
|
||||
private fun addSpaces(host: SpaceBarController, spaces: List<RoomSummary?>, selectedSpace: RoomSummary?) {
|
||||
carousel {
|
||||
id("spaces_carousel")
|
||||
padding(
|
||||
Carousel.Padding(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
)
|
||||
)
|
||||
onBind { _, view, _ ->
|
||||
host.carousel = view
|
||||
host.scrollToSpace(selectedSpace?.roomId)
|
||||
}
|
||||
|
||||
onUnbind { _, _ ->
|
||||
host.carousel = null
|
||||
}
|
||||
|
||||
withModelsFrom(spaces) { spaceSummary ->
|
||||
val onClick = host.spaceRoomListener?.let { it::onSpaceBarSelectSpace }
|
||||
val onLongClick = host.spaceRoomListener?.let { it::onSpaceBarLongPressSpace }
|
||||
|
||||
if (spaceSummary == null) {
|
||||
SpaceBarItem_()
|
||||
.id("de.spiritcroc.riotx.spacebarhome")
|
||||
.avatarRenderer(host.avatarRenderer)
|
||||
.matrixItem(null)
|
||||
.unreadNotificationCount(host.topLevelUnreadCounts.count)
|
||||
.showHighlighted(host.topLevelUnreadCounts.highlighted)
|
||||
.unreadCount(host.topLevelUnreadCounts.unread)
|
||||
.markedUnread(host.topLevelUnreadCounts.markedUnread)
|
||||
.selected(selectedSpace == null)
|
||||
.itemLongClickListener { _ -> onLongClick?.invoke(null) ?: false }
|
||||
.itemClickListener { onClick?.invoke(null) }
|
||||
} else {
|
||||
SpaceBarItem_()
|
||||
.id(spaceSummary.roomId)
|
||||
.avatarRenderer(host.avatarRenderer)
|
||||
.matrixItem(spaceSummary.toMatrixItem())
|
||||
.unreadNotificationCount(spaceSummary.notificationCount)
|
||||
.showHighlighted(spaceSummary.highlightCount > 0)
|
||||
.unreadCount(spaceSummary.unreadCount ?: 0)
|
||||
.markedUnread(spaceSummary.markedUnread)
|
||||
.selected(spaceSummary.roomId == selectedSpace?.roomId)
|
||||
.itemLongClickListener { _ -> onLongClick?.invoke(spaceSummary) ?: false }
|
||||
.itemClickListener { onClick?.invoke(spaceSummary) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun submitData(data: SpaceBarData) {
|
||||
this.data = data
|
||||
requestModelBuild()
|
||||
}
|
||||
|
||||
fun submitHomeUnreadCounts(counts: UnreadCounterBadgeView.State.Count) {
|
||||
this.topLevelUnreadCounts = counts
|
||||
requestModelBuild()
|
||||
}
|
||||
|
||||
fun selectSpace(space: RoomSummary?) {
|
||||
this.data = this.data.copy(selectedSpace = space)
|
||||
requestModelBuild()
|
||||
scrollToSpace(space?.roomId)
|
||||
}
|
||||
|
||||
fun scrollToSpace(spaceId: String?) {
|
||||
val position = this.data.spaces?.indexOfFirst { spaceId == it?.roomId } ?: -1
|
||||
if (position >= 0) {
|
||||
scrollToSpacePosition(position)
|
||||
}
|
||||
}
|
||||
|
||||
fun scrollToSpacePosition(position: Int) {
|
||||
val safeCarousel = carousel ?: return
|
||||
var effectivePosition = position
|
||||
val lm = safeCarousel.layoutManager as? LinearLayoutManager
|
||||
if (lm != null) {
|
||||
// Look-ahead of 1
|
||||
if (lm.findFirstCompletelyVisibleItemPosition() >= position) {
|
||||
effectivePosition--
|
||||
} else if (lm.findLastVisibleItemPosition() <= position) {
|
||||
effectivePosition++
|
||||
}
|
||||
effectivePosition = max(0, min(effectivePosition, lm.itemCount-1))
|
||||
}
|
||||
safeCarousel.smoothScrollToPosition(effectivePosition)
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun <T> CarouselModelBuilder.withModelsFrom(
|
||||
items: List<T>,
|
||||
modelBuilder: (T) -> EpoxyModel<*>
|
||||
) {
|
||||
models(items.map { modelBuilder(it) })
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright (c) 2022 New Vector Ltd
|
||||
* Copyright (c) 2022 SpiritCroc
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.features.home.room.list.home.spacebar
|
||||
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
|
||||
data class SpaceBarData(
|
||||
val spaces: List<RoomSummary?>? = null,
|
||||
val selectedSpace: RoomSummary? = null,
|
||||
)
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Copyright (c) 2022 New Vector Ltd
|
||||
* Copyright (c) 2022 SpiritCroc
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.features.home.room.list.home.spacebar
|
||||
|
||||
import android.content.res.ColorStateList
|
||||
import android.view.HapticFeedbackConstants
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import com.airbnb.epoxy.EpoxyAttribute
|
||||
import com.airbnb.epoxy.EpoxyModelClass
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.epoxy.ClickListener
|
||||
import im.vector.app.core.epoxy.VectorEpoxyHolder
|
||||
import im.vector.app.core.epoxy.VectorEpoxyModel
|
||||
import im.vector.app.core.epoxy.onClick
|
||||
import im.vector.app.core.platform.CheckableConstraintLayout
|
||||
import im.vector.app.features.displayname.getBestName
|
||||
import im.vector.app.features.home.AvatarRenderer
|
||||
import im.vector.app.features.home.room.list.UnreadCounterBadgeView
|
||||
import im.vector.app.features.themes.ThemeUtils
|
||||
import org.matrix.android.sdk.api.util.MatrixItem
|
||||
|
||||
@EpoxyModelClass
|
||||
abstract class SpaceBarItem : VectorEpoxyModel<SpaceBarItem.Holder>(R.layout.space_bar_item) {
|
||||
|
||||
@EpoxyAttribute lateinit var avatarRenderer: AvatarRenderer
|
||||
@EpoxyAttribute var matrixItem: MatrixItem? = null
|
||||
@EpoxyAttribute var unreadNotificationCount: Int = 0
|
||||
@EpoxyAttribute var unreadCount: Int = 0
|
||||
@EpoxyAttribute var markedUnread: Boolean = false
|
||||
@EpoxyAttribute var showHighlighted: Boolean = false
|
||||
@EpoxyAttribute var selected: Boolean = false
|
||||
|
||||
@EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
|
||||
var itemLongClickListener: View.OnLongClickListener? = null
|
||||
|
||||
@EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
|
||||
var itemClickListener: ClickListener? = null
|
||||
|
||||
override fun bind(holder: Holder) {
|
||||
super.bind(holder)
|
||||
|
||||
holder.rootView.onClick(itemClickListener)
|
||||
holder.rootView.setOnLongClickListener {
|
||||
it.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
|
||||
itemLongClickListener?.onLongClick(it) ?: false
|
||||
}
|
||||
|
||||
matrixItem.let {
|
||||
if (it == null) {
|
||||
holder.avatarImageView.setImageResource(R.drawable.ic_space_home)
|
||||
holder.avatarImageView.imageTintList = ColorStateList.valueOf(ThemeUtils.getColor(holder.avatarImageView.context, R.attr.vctr_content_primary))
|
||||
holder.avatarImageView.contentDescription = holder.rootView.context.getString(R.string.group_details_home)
|
||||
} else {
|
||||
holder.avatarImageView.imageTintList = null
|
||||
avatarRenderer.render(it, holder.avatarImageView)
|
||||
holder.avatarImageView.contentDescription = it.getBestName()
|
||||
}
|
||||
}
|
||||
holder.unreadCounterBadgeView.render(UnreadCounterBadgeView.State.Count(unreadNotificationCount, showHighlighted, unreadCount, markedUnread))
|
||||
holder.rootView.isChecked = selected
|
||||
}
|
||||
|
||||
override fun unbind(holder: Holder) {
|
||||
holder.rootView.setOnClickListener(null)
|
||||
holder.rootView.setOnLongClickListener(null)
|
||||
avatarRenderer.clear(holder.avatarImageView)
|
||||
super.unbind(holder)
|
||||
}
|
||||
|
||||
class Holder : VectorEpoxyHolder() {
|
||||
val unreadCounterBadgeView by bind<UnreadCounterBadgeView>(R.id.spaceUnreadCounterBadgeView)
|
||||
val avatarImageView by bind<ImageView>(R.id.spaceImageView)
|
||||
val rootView by bind<CheckableConstraintLayout>(R.id.spaceRoot)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item android:state_checked="true">
|
||||
<layer-list>
|
||||
<item>
|
||||
<shape>
|
||||
<solid android:color="@android:color/transparent" />
|
||||
</shape>
|
||||
</item>
|
||||
<item android:gravity="center_horizontal|bottom" >
|
||||
<shape>
|
||||
<size android:width="40dp" android:height="4dp" />
|
||||
<solid android:color="?colorSecondary" />
|
||||
<corners android:topLeftRadius="8dp" android:topRightRadius="8dp" />
|
||||
</shape>
|
||||
</item>
|
||||
</layer-list>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<shape>
|
||||
<solid android:color="@android:color/transparent" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
</selector>
|
|
@ -150,7 +150,7 @@
|
|||
android:id="@+id/roomListContainerStateView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/bottomNavigationView"
|
||||
app:layout_constraintBottom_toTopOf="@+id/spaceBarRecyclerView"
|
||||
app:layout_constraintTop_toBottomOf="@+id/homeKeysBackupBanner">
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/roomListContainerPager"
|
||||
|
@ -158,6 +158,29 @@
|
|||
android:layout_height="match_parent" />
|
||||
</im.vector.app.core.platform.StateView>
|
||||
|
||||
<!-- Own view for spacebar bg in case of wrap_content of spaceBarRecyclerView is smaller than screen estate -->
|
||||
<View
|
||||
android:id="@+id/spaceBarBackground"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:background="@drawable/bg_bottom_navigation"
|
||||
android:elevation="4dp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/spaceBarRecyclerView"
|
||||
app:layout_constraintTop_toTopOf="@id/spaceBarRecyclerView"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
<!-- wrap_content -> center when fewer spaces than screen estate -->
|
||||
<!-- needs higher elevation than spaceBarBackground to be rendered above: https://stackoverflow.com/a/27554343 -->
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/spaceBarRecyclerView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
android:elevation="80dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@+id/bottomNavigationView" />
|
||||
|
||||
<com.google.android.material.bottomnavigation.BottomNavigationView
|
||||
android:id="@+id/bottomNavigationView"
|
||||
android:layout_width="0dp"
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<im.vector.app.core.platform.CheckableConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/spaceRoot"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="48dp"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:foreground="?attr/selectableItemBackground"
|
||||
android:background="@drawable/bg_bottom_space_item"
|
||||
android:padding="8dp"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
tools:viewBindingIgnore="true">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/spaceImageView"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
tools:ignore="ContentDescription"
|
||||
tools:src="@sample/room_round_avatars" />
|
||||
|
||||
<im.vector.app.features.home.room.list.UnreadCounterBadgeView
|
||||
android:id="@+id/spaceUnreadCounterBadgeView"
|
||||
style="@style/Widget.Vector.TextView.Micro"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:minWidth="18dp"
|
||||
android:minHeight="18dp"
|
||||
android:textColor="?colorOnError"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintCircle="@id/spaceImageView"
|
||||
app:layout_constraintCircleAngle="45"
|
||||
app:layout_constraintCircleRadius="21dp"
|
||||
tools:background="@drawable/bg_unread_highlight"
|
||||
tools:text="24"
|
||||
tools:visibility="visible" />
|
||||
|
||||
|
||||
<!--
|
||||
<TextView
|
||||
android:id="@+id/spaceTitle"
|
||||
style="@style/Widget.Vector.TextView.Body"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:ellipsize="end"
|
||||
android:importantForAccessibility="no"
|
||||
android:lines="1"
|
||||
android:textColor="?vctr_content_primary"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/spaceImageView"
|
||||
tools:text="Coffee" />
|
||||
-->
|
||||
|
||||
</im.vector.app.core.platform.CheckableConstraintLayout>
|
Loading…
Reference in New Issue