mirror of
https://github.com/nextcloud/talk-android
synced 2025-06-21 12:39:58 +01:00
Most work on search done
What remains is animation of toolbar on back button Signed-off-by: Mario Danic <mario@lovelyhq.com>
This commit is contained in:
parent
689b8e93af
commit
27829eb1d8
@ -29,6 +29,7 @@ import android.view.ViewGroup
|
|||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import butterknife.BindView
|
import butterknife.BindView
|
||||||
import butterknife.ButterKnife
|
import butterknife.ButterKnife
|
||||||
|
import butterknife.OnClick
|
||||||
import com.bluelinelabs.conductor.Conductor
|
import com.bluelinelabs.conductor.Conductor
|
||||||
import com.bluelinelabs.conductor.Router
|
import com.bluelinelabs.conductor.Router
|
||||||
import com.bluelinelabs.conductor.RouterTransaction
|
import com.bluelinelabs.conductor.RouterTransaction
|
||||||
@ -70,7 +71,6 @@ class MainActivity : BaseActivity(), ActionBarProvider {
|
|||||||
setContentView(R.layout.activity_main)
|
setContentView(R.layout.activity_main)
|
||||||
|
|
||||||
ButterKnife.bind(this)
|
ButterKnife.bind(this)
|
||||||
|
|
||||||
setSupportActionBar(toolbar)
|
setSupportActionBar(toolbar)
|
||||||
|
|
||||||
router = Conductor.attachRouter(this, container, savedInstanceState)
|
router = Conductor.attachRouter(this, container, savedInstanceState)
|
||||||
@ -107,6 +107,17 @@ class MainActivity : BaseActivity(), ActionBarProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OnClick(R.id.floatingActionButton)
|
||||||
|
fun onFloatingActionButtonClick() {
|
||||||
|
val bundle = Bundle()
|
||||||
|
bundle.putBoolean(BundleKeys.KEY_NEW_CONVERSATION, true)
|
||||||
|
router?.pushController(
|
||||||
|
RouterTransaction.with(ContactsController(bundle))
|
||||||
|
.pushChangeHandler(HorizontalChangeHandler())
|
||||||
|
.popChangeHandler(HorizontalChangeHandler()))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.M)
|
@RequiresApi(api = Build.VERSION_CODES.M)
|
||||||
fun checkIfWeAreSecure() {
|
fun checkIfWeAreSecure() {
|
||||||
val keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
|
val keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
|
||||||
|
@ -49,6 +49,8 @@ import butterknife.OnClick
|
|||||||
import coil.api.load
|
import coil.api.load
|
||||||
import coil.target.Target
|
import coil.target.Target
|
||||||
import coil.transform.CircleCropTransformation
|
import coil.transform.CircleCropTransformation
|
||||||
|
import com.bluelinelabs.conductor.ControllerChangeHandler
|
||||||
|
import com.bluelinelabs.conductor.ControllerChangeType
|
||||||
import com.bluelinelabs.conductor.RouterTransaction
|
import com.bluelinelabs.conductor.RouterTransaction
|
||||||
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
|
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
|
||||||
import com.bluelinelabs.conductor.changehandler.VerticalChangeHandler
|
import com.bluelinelabs.conductor.changehandler.VerticalChangeHandler
|
||||||
@ -710,13 +712,14 @@ class ChatController(args: Bundle) : BaseController(), MessagesListAdapter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onChangeStarted(changeHandler: ControllerChangeHandler, changeType: ControllerChangeType) {
|
||||||
|
actionBar?.setIcon(null)
|
||||||
|
super.onChangeStarted(changeHandler, changeType)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onDetach(view: View) {
|
override fun onDetach(view: View) {
|
||||||
eventBus.unregister(this)
|
eventBus.unregister(this)
|
||||||
|
|
||||||
if (actionBar != null) {
|
|
||||||
actionBar?.setIcon(null)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (activity != null) {
|
if (activity != null) {
|
||||||
activity?.findViewById<View>(R.id.toolbar)
|
activity?.findViewById<View>(R.id.toolbar)
|
||||||
?.setOnClickListener(null)
|
?.setOnClickListener(null)
|
||||||
|
@ -20,14 +20,11 @@
|
|||||||
|
|
||||||
package com.nextcloud.talk.controllers.base
|
package com.nextcloud.talk.controllers.base
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import android.content.ComponentCallbacks
|
import android.content.ComponentCallbacks
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.util.TypedValue
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
@ -37,11 +34,10 @@ import android.widget.EditText
|
|||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.appcompat.app.ActionBar
|
import androidx.appcompat.app.ActionBar
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.core.view.marginBottom
|
import com.bluelinelabs.conductor.ControllerChangeHandler
|
||||||
import androidx.core.view.updatePadding
|
import com.bluelinelabs.conductor.ControllerChangeType
|
||||||
import com.bluelinelabs.conductor.autodispose.ControllerScopeProvider
|
import com.bluelinelabs.conductor.autodispose.ControllerScopeProvider
|
||||||
import com.google.android.material.appbar.AppBarLayout
|
import com.google.android.material.appbar.AppBarLayout
|
||||||
import com.google.android.material.appbar.MaterialToolbar
|
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
import com.nextcloud.talk.activities.MainActivity
|
import com.nextcloud.talk.activities.MainActivity
|
||||||
import com.nextcloud.talk.controllers.AccountVerificationController
|
import com.nextcloud.talk.controllers.AccountVerificationController
|
||||||
@ -94,25 +90,23 @@ abstract class BaseController : ButterKnifeController(), ComponentCallbacks {
|
|||||||
activity?.let {
|
activity?.let {
|
||||||
if (it is MainActivity) {
|
if (it is MainActivity) {
|
||||||
it.searchCardView.isVisible = value
|
it.searchCardView.isVisible = value
|
||||||
|
it.floatingActionButton.isVisible = value
|
||||||
it.inputEditText.hint = getSearchHint()
|
it.inputEditText.hint = getSearchHint()
|
||||||
|
|
||||||
val layoutParams = it.toolbar.layoutParams as AppBarLayout.LayoutParams
|
val layoutParams = it.toolbar.layoutParams as AppBarLayout.LayoutParams
|
||||||
|
|
||||||
if (value) {
|
if (value) {
|
||||||
|
layoutParams.scrollFlags = AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL or AppBarLayout.LayoutParams.SCROLL_FLAG_SNAP or AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS
|
||||||
it.appBar.setBackgroundResource(R.color.transparent)
|
it.appBar.setBackgroundResource(R.color.transparent)
|
||||||
//it.toolbar.setContentInsetsAbsolute(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 16f, resources?.displayMetrics).toInt(), 0)
|
|
||||||
//layoutParams.scrollFlags = AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL or AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS or AppBarLayout.LayoutParams.SCROLL_FLAG_SNAP
|
|
||||||
it.toolbar.layoutParams = layoutParams
|
|
||||||
} else {
|
} else {
|
||||||
it.appBar.setBackgroundResource(R.color.colorPrimary)
|
|
||||||
//it.toolbar.setContentInsetsAbsolute(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 24f, resources?.displayMetrics).toInt(), 0)
|
|
||||||
layoutParams.scrollFlags = 0
|
layoutParams.scrollFlags = 0
|
||||||
it.toolbar.layoutParams = layoutParams
|
it.appBar.setBackgroundResource(R.color.colorPrimary)
|
||||||
}
|
}
|
||||||
|
it.toolbar.layoutParams = layoutParams
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun cleanTempCertPreference() {
|
private fun cleanTempCertPreference() {
|
||||||
val temporaryClassNames = ArrayList<String>()
|
val temporaryClassNames = ArrayList<String>()
|
||||||
temporaryClassNames.add(ServerSelectionController::class.java.name)
|
temporaryClassNames.add(ServerSelectionController::class.java.name)
|
||||||
@ -126,6 +120,7 @@ abstract class BaseController : ButterKnifeController(), ComponentCallbacks {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun onViewBound(view: View) {
|
override fun onViewBound(view: View) {
|
||||||
super.onViewBound(view)
|
super.onViewBound(view)
|
||||||
cleanTempCertPreference()
|
cleanTempCertPreference()
|
||||||
@ -142,11 +137,10 @@ abstract class BaseController : ButterKnifeController(), ComponentCallbacks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onAttach(view: View) {
|
override fun onAttach(view: View) {
|
||||||
super.onAttach(view)
|
showSearchOrToolbar()
|
||||||
|
|
||||||
setTitle()
|
setTitle()
|
||||||
actionBar?.setDisplayHomeAsUpEnabled(parentController != null || router.backstackSize > 1)
|
actionBar?.setDisplayHomeAsUpEnabled(parentController != null || router.backstackSize > 1)
|
||||||
showSearchOrToolbar()
|
super.onAttach(view)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDetach(view: View) {
|
override fun onDetach(view: View) {
|
||||||
|
@ -57,9 +57,9 @@ class ConversationsRepositoryImpl(val conversationsDao: ConversationsDao) :
|
|||||||
.deleteConversation(userId, conversationId)
|
.deleteConversation(userId, conversationId)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getConversationsForUser(userId: Long, filter: String?): LiveData<List<Conversation>> {
|
override fun getConversationsForUser(userId: Long, filter: CharSequence?): LiveData<List<Conversation>> {
|
||||||
filter?.let {
|
filter?.let {
|
||||||
return conversationsDao.getConversationsForUserWithFilter(userId, it).distinctUntilChanged().map { data ->
|
return conversationsDao.getConversationsForUserWithFilter(userId, it.toString()).distinctUntilChanged().map { data ->
|
||||||
data.map {conversationEntity ->
|
data.map {conversationEntity ->
|
||||||
conversationEntity.toConversation()
|
conversationEntity.toConversation()
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ import androidx.lifecycle.LiveData
|
|||||||
import com.nextcloud.talk.models.json.conversations.Conversation
|
import com.nextcloud.talk.models.json.conversations.Conversation
|
||||||
|
|
||||||
interface ConversationsRepository {
|
interface ConversationsRepository {
|
||||||
fun getConversationsForUser(userId: Long, filter: String?): LiveData<List<Conversation>>
|
fun getConversationsForUser(userId: Long, filter: CharSequence?): LiveData<List<Conversation>>
|
||||||
fun getShortcutTargetConversations(userId: Long): LiveData<List<Conversation>>
|
fun getShortcutTargetConversations(userId: Long): LiveData<List<Conversation>>
|
||||||
|
|
||||||
suspend fun getConversationForUserWithToken(userId: Long, token: String): Conversation?
|
suspend fun getConversationForUserWithToken(userId: Long, token: String): Conversation?
|
||||||
|
@ -21,17 +21,14 @@
|
|||||||
package com.nextcloud.talk.newarch.features.conversationsList
|
package com.nextcloud.talk.newarch.features.conversationsList
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.res.Configuration
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.*
|
import android.view.*
|
||||||
import androidx.appcompat.widget.SearchView
|
import androidx.core.view.isVisible
|
||||||
import androidx.lifecycle.observe
|
import androidx.lifecycle.observe
|
||||||
import butterknife.OnClick
|
import butterknife.OnClick
|
||||||
import com.afollestad.materialdialogs.LayoutMode
|
import com.afollestad.materialdialogs.LayoutMode
|
||||||
import com.afollestad.materialdialogs.MaterialDialog
|
import com.afollestad.materialdialogs.MaterialDialog
|
||||||
import com.afollestad.materialdialogs.bottomsheets.BottomSheet
|
import com.afollestad.materialdialogs.bottomsheets.BottomSheet
|
||||||
import com.bluelinelabs.conductor.ControllerChangeHandler
|
|
||||||
import com.bluelinelabs.conductor.ControllerChangeType
|
|
||||||
import com.bluelinelabs.conductor.RouterTransaction
|
import com.bluelinelabs.conductor.RouterTransaction
|
||||||
import com.bluelinelabs.conductor.autodispose.ControllerScopeProvider
|
import com.bluelinelabs.conductor.autodispose.ControllerScopeProvider
|
||||||
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
|
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
|
||||||
@ -39,7 +36,6 @@ import com.bluelinelabs.conductor.changehandler.TransitionChangeHandlerCompat
|
|||||||
import com.bluelinelabs.conductor.changehandler.VerticalChangeHandler
|
import com.bluelinelabs.conductor.changehandler.VerticalChangeHandler
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
import com.nextcloud.talk.R.drawable
|
import com.nextcloud.talk.R.drawable
|
||||||
import com.nextcloud.talk.activities.MainActivity
|
|
||||||
import com.nextcloud.talk.controllers.ContactsController
|
import com.nextcloud.talk.controllers.ContactsController
|
||||||
import com.nextcloud.talk.controllers.SettingsController
|
import com.nextcloud.talk.controllers.SettingsController
|
||||||
import com.nextcloud.talk.controllers.bottomsheet.items.BasicListItemWithImage
|
import com.nextcloud.talk.controllers.bottomsheet.items.BasicListItemWithImage
|
||||||
@ -47,6 +43,7 @@ import com.nextcloud.talk.controllers.bottomsheet.items.listItemsWithImage
|
|||||||
import com.nextcloud.talk.models.json.conversations.Conversation
|
import com.nextcloud.talk.models.json.conversations.Conversation
|
||||||
import com.nextcloud.talk.newarch.conversationsList.mvp.BaseView
|
import com.nextcloud.talk.newarch.conversationsList.mvp.BaseView
|
||||||
import com.nextcloud.talk.newarch.data.presenters.AdvancedEmptyPresenter
|
import com.nextcloud.talk.newarch.data.presenters.AdvancedEmptyPresenter
|
||||||
|
import com.nextcloud.talk.newarch.features.search.DebouncingTextWatcher
|
||||||
import com.nextcloud.talk.newarch.mvvm.ext.initRecyclerView
|
import com.nextcloud.talk.newarch.mvvm.ext.initRecyclerView
|
||||||
import com.nextcloud.talk.utils.ConductorRemapping
|
import com.nextcloud.talk.utils.ConductorRemapping
|
||||||
import com.nextcloud.talk.utils.DisplayUtils
|
import com.nextcloud.talk.utils.DisplayUtils
|
||||||
@ -55,15 +52,11 @@ import com.nextcloud.talk.utils.bundle.BundleKeys
|
|||||||
import com.otaliastudios.elements.*
|
import com.otaliastudios.elements.*
|
||||||
import com.uber.autodispose.lifecycle.LifecycleScopeProvider
|
import com.uber.autodispose.lifecycle.LifecycleScopeProvider
|
||||||
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
|
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
|
||||||
import kotlinx.android.synthetic.main.activity_main.*
|
|
||||||
import kotlinx.android.synthetic.main.activity_main.view.*
|
|
||||||
import kotlinx.android.synthetic.main.controller_conversations_rv.view.*
|
import kotlinx.android.synthetic.main.controller_conversations_rv.view.*
|
||||||
import kotlinx.android.synthetic.main.message_state.view.*
|
import kotlinx.android.synthetic.main.message_state.view.*
|
||||||
import kotlinx.android.synthetic.main.search_layout.*
|
import kotlinx.android.synthetic.main.search_layout.*
|
||||||
import kotlinx.android.synthetic.main.search_layout.view.*
|
|
||||||
import org.koin.android.ext.android.inject
|
import org.koin.android.ext.android.inject
|
||||||
import org.parceler.Parcels
|
import org.parceler.Parcels
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
class ConversationsListView : BaseView() {
|
class ConversationsListView : BaseView() {
|
||||||
|
|
||||||
@ -72,34 +65,6 @@ class ConversationsListView : BaseView() {
|
|||||||
private lateinit var viewModel: ConversationsListViewModel
|
private lateinit var viewModel: ConversationsListViewModel
|
||||||
val factory: ConversationListViewModelFactory by inject()
|
val factory: ConversationListViewModelFactory by inject()
|
||||||
|
|
||||||
/*private fun initSearchView() {
|
|
||||||
val searchManager = activity!!.getSystemService(Context.SEARCH_SERVICE) as SearchManager
|
|
||||||
searchView = MenuItemCompat.getActionView(searchItem) as SearchView
|
|
||||||
searchView!!.maxWidth = Integer.MAX_VALUE
|
|
||||||
searchView!!.inputType = InputType.TYPE_TEXT_VARIATION_FILTER
|
|
||||||
var imeOptions = EditorInfo.IME_ACTION_DONE or EditorInfo.IME_FLAG_NO_FULLSCREEN
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && appPreferences.isKeyboardIncognito) {
|
|
||||||
imeOptions = imeOptions or EditorInfo.IME_FLAG_NO_PERSONALIZED_LEARNING
|
|
||||||
}
|
|
||||||
searchView!!.imeOptions = imeOptions
|
|
||||||
searchView!!.queryHint = resources?.getString(R.string.nc_search)
|
|
||||||
searchView!!.setSearchableInfo(searchManager.getSearchableInfo(activity!!.componentName))
|
|
||||||
searchView!!.setOnQueryTextListener(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
override fun onQueryTextSubmit(query: String?): Boolean {
|
|
||||||
if (!viewModel.searchQuery.value.equals(query)) {
|
|
||||||
viewModel.searchQuery.value = query
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onQueryTextChange(newText: String?): Boolean {
|
|
||||||
return onQueryTextSubmit(newText)
|
|
||||||
}*/
|
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup
|
container: ViewGroup
|
||||||
@ -131,7 +96,11 @@ class ConversationsListView : BaseView() {
|
|||||||
swipeRefreshLayoutView.setColorSchemeResources(R.color.colorPrimary)
|
swipeRefreshLayoutView.setColorSchemeResources(R.color.colorPrimary)
|
||||||
}
|
}
|
||||||
|
|
||||||
activity?.rightButton?.setOnClickListener {
|
activity?.inputEditText?.addTextChangedListener(DebouncingTextWatcher(lifecycle, ::setSearchQuery))
|
||||||
|
activity?.clearButton?.setOnClickListener {
|
||||||
|
activity?.inputEditText?.text = null
|
||||||
|
}
|
||||||
|
activity?.settingsButton?.setOnClickListener {
|
||||||
val settingsTransitionName = "userAvatar.transitionTag"
|
val settingsTransitionName = "userAvatar.transitionTag"
|
||||||
router.pushController(
|
router.pushController(
|
||||||
RouterTransaction.with(SettingsController())
|
RouterTransaction.with(SettingsController())
|
||||||
@ -150,12 +119,20 @@ class ConversationsListView : BaseView() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
viewModel.avatar.observe(this@ConversationsListView) { avatar ->
|
viewModel.avatar.observe(this@ConversationsListView) { avatar ->
|
||||||
activity?.rightButton?.setImageDrawable(avatar)
|
activity?.settingsButton?.setImageDrawable(avatar)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
viewModel.filterLiveData.observe(this@ConversationsListView) {query ->
|
||||||
|
activity?.settingsButton?.isVisible = query.isNullOrEmpty()
|
||||||
|
activity?.clearButton?.isVisible = !query.isNullOrEmpty()
|
||||||
|
}
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun setSearchQuery(query: CharSequence?) {
|
||||||
|
viewModel.filterLiveData.value = query
|
||||||
|
}
|
||||||
|
|
||||||
private fun onElementClick(page: Page, holder: Presenter.Holder, element: Element<Conversation>) {
|
private fun onElementClick(page: Page, holder: Presenter.Holder, element: Element<Conversation>) {
|
||||||
val conversation = element.data
|
val conversation = element.data
|
||||||
val user = viewModel.globalService.currentUserLiveData.value
|
val user = viewModel.globalService.currentUserLiveData.value
|
||||||
@ -234,10 +211,10 @@ class ConversationsListView : BaseView() {
|
|||||||
return R.layout.controller_conversations_rv
|
return R.layout.controller_conversations_rv
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnClick(R.id.floatingActionButton)
|
/*@OnClick(R.id.floatingActionButton)
|
||||||
fun onFloatingActionButtonClick() {
|
fun onFloatingActionButtonClick() {
|
||||||
openNewConversationScreen()
|
openNewConversationScreen()
|
||||||
}
|
}*/
|
||||||
|
|
||||||
private fun openNewConversationScreen() {
|
private fun openNewConversationScreen() {
|
||||||
val bundle = Bundle()
|
val bundle = Bundle()
|
||||||
|
@ -66,7 +66,7 @@ class ConversationsListViewModel constructor(
|
|||||||
var messageData: String? = null
|
var messageData: String? = null
|
||||||
val networkStateLiveData: MutableLiveData<ConversationsListViewNetworkState> = MutableLiveData(ConversationsListViewNetworkState.LOADING)
|
val networkStateLiveData: MutableLiveData<ConversationsListViewNetworkState> = MutableLiveData(ConversationsListViewNetworkState.LOADING)
|
||||||
val avatar: MutableLiveData<Drawable> = MutableLiveData(DisplayUtils.getRoundedDrawable(context.getDrawable(R.drawable.ic_settings_white_24dp)))
|
val avatar: MutableLiveData<Drawable> = MutableLiveData(DisplayUtils.getRoundedDrawable(context.getDrawable(R.drawable.ic_settings_white_24dp)))
|
||||||
val filterLiveData: MutableLiveData<String?> = MutableLiveData(null)
|
val filterLiveData: MutableLiveData<CharSequence?> = MutableLiveData(null)
|
||||||
val conversationsLiveData = Transformations.switchMap(globalService.currentUserLiveData) { user ->
|
val conversationsLiveData = Transformations.switchMap(globalService.currentUserLiveData) { user ->
|
||||||
if (networkStateLiveData.value != ConversationsListViewNetworkState.LOADING) {
|
if (networkStateLiveData.value != ConversationsListViewNetworkState.LOADING) {
|
||||||
networkStateLiveData.postValue(ConversationsListViewNetworkState.LOADING)
|
networkStateLiveData.postValue(ConversationsListViewNetworkState.LOADING)
|
||||||
@ -75,7 +75,7 @@ class ConversationsListViewModel constructor(
|
|||||||
loadAvatar()
|
loadAvatar()
|
||||||
|
|
||||||
filterLiveData.value = null
|
filterLiveData.value = null
|
||||||
Transformations.switchMap(filterLiveData.distinctUntilChanged()) { filter ->
|
Transformations.switchMap(filterLiveData) { filter ->
|
||||||
conversationsRepository.getConversationsForUser(user.id!!, filter)
|
conversationsRepository.getConversationsForUser(user.id!!, filter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,35 +22,38 @@
|
|||||||
|
|
||||||
package com.nextcloud.talk.newarch.features.search
|
package com.nextcloud.talk.newarch.features.search
|
||||||
|
|
||||||
import androidx.appcompat.widget.SearchView.OnQueryTextListener
|
import android.text.Editable
|
||||||
|
import android.text.TextWatcher
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.lifecycle.coroutineScope
|
import androidx.lifecycle.coroutineScope
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class DebouncingQueryTextListener(
|
class DebouncingTextWatcher(
|
||||||
lifecycle: Lifecycle,
|
lifecycle: Lifecycle,
|
||||||
private val onDebouncingQueryTextChange: (String?) -> Unit
|
private val onDebouncingTextWatcherChange: (CharSequence?) -> Unit
|
||||||
) : OnQueryTextListener {
|
) : TextWatcher {
|
||||||
private var debouncePeriod: Long = 500
|
private var debouncePeriod: Long = 500
|
||||||
|
|
||||||
private val coroutineScope = lifecycle.coroutineScope
|
private val coroutineScope = lifecycle.coroutineScope
|
||||||
|
|
||||||
private var searchJob: Job? = null
|
private var searchJob: Job? = null
|
||||||
|
|
||||||
override fun onQueryTextSubmit(query: String?): Boolean {
|
override fun afterTextChanged(s: Editable?) {
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onQueryTextChange(newText: String?): Boolean {
|
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
|
||||||
searchJob?.cancel()
|
searchJob?.cancel()
|
||||||
searchJob = coroutineScope.launch {
|
searchJob = coroutineScope.launch {
|
||||||
newText?.let {
|
s.let {
|
||||||
delay(debouncePeriod)
|
delay(debouncePeriod)
|
||||||
onDebouncingQueryTextChange(newText)
|
onDebouncingTextWatcherChange(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* * Nextcloud Talk application
|
||||||
|
* *
|
||||||
|
* * @author Mario Danic
|
||||||
|
* * Copyright (C) 2017-2020 Mario Danic <mario@lovelyhq.com>
|
||||||
|
* *
|
||||||
|
* * 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 com.nextcloud.talk.newarch.utils
|
||||||
|
|
||||||
|
import android.annotation.TargetApi
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Build
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.MotionEvent
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.view.WindowInsets
|
||||||
|
import androidx.annotation.AttrRes
|
||||||
|
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
|
import com.bluelinelabs.conductor.Controller
|
||||||
|
import com.bluelinelabs.conductor.ControllerChangeHandler
|
||||||
|
import com.bluelinelabs.conductor.ControllerChangeHandler.ControllerChangeListener
|
||||||
|
import com.nextcloud.talk.activities.MainActivity
|
||||||
|
import com.nextcloud.talk.newarch.features.conversationsList.ConversationsListView
|
||||||
|
|
||||||
|
class ChangeHandlerCoordinatorLayout : CoordinatorLayout, ControllerChangeListener {
|
||||||
|
private var inProgressTransactionCount = 0
|
||||||
|
|
||||||
|
constructor(context: Context) : super(context) {}
|
||||||
|
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {}
|
||||||
|
constructor(context: Context, attrs: AttributeSet?, @AttrRes defStyleAttr: Int) : super(context, attrs, defStyleAttr) {}
|
||||||
|
|
||||||
|
override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
|
||||||
|
return inProgressTransactionCount > 0 || super.onInterceptTouchEvent(ev)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onChangeStarted(to: Controller?, from: Controller?, isPush: Boolean, container: ViewGroup, handler: ControllerChangeHandler) {
|
||||||
|
inProgressTransactionCount++
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onChangeCompleted(to: Controller?, from: Controller?, isPush: Boolean, container: ViewGroup, handler: ControllerChangeHandler) {
|
||||||
|
inProgressTransactionCount--
|
||||||
|
}
|
||||||
|
|
||||||
|
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||||
|
override fun onApplyWindowInsets(insets: WindowInsets): WindowInsets {
|
||||||
|
for (i in 0 until childCount) {
|
||||||
|
getChildAt(i).dispatchApplyWindowInsets(insets)
|
||||||
|
}
|
||||||
|
return super.onApplyWindowInsets(insets)
|
||||||
|
}
|
||||||
|
}
|
@ -21,39 +21,50 @@
|
|||||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/mainActivityCoordinatorLayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
tools:context=".activities.MainActivity">
|
tools:context=".activities.MainActivity">
|
||||||
|
|
||||||
<com.bluelinelabs.conductor.ChangeHandlerFrameLayout
|
|
||||||
android:id="@+id/controller_container"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
|
|
||||||
|
|
||||||
<com.google.android.material.appbar.AppBarLayout
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="0dp"
|
|
||||||
android:id="@+id/appBar"
|
android:id="@+id/appBar"
|
||||||
app:elevation="0dp"
|
android:layout_width="match_parent"
|
||||||
>
|
android:layout_height="56dp"
|
||||||
|
android:background="@color/transparent"
|
||||||
|
app:elevation="0dp">
|
||||||
|
|
||||||
<com.google.android.material.appbar.MaterialToolbar
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
android:id="@+id/toolbar"
|
android:id="@+id/toolbar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
android:theme="@style/ThemeOverlay.MaterialComponents.Dark.ActionBar"
|
android:theme="@style/ThemeOverlay.MaterialComponents.Dark.ActionBar"
|
||||||
android:layout_height="?android:attr/actionBarSize"
|
|
||||||
android:background="@color/transparent"
|
|
||||||
app:elevation="0dp"
|
|
||||||
app:contentInsetEnd="12dp"
|
app:contentInsetEnd="12dp"
|
||||||
app:contentInsetStart="12dp"
|
app:contentInsetStart="12dp"
|
||||||
|
app:contentInsetStartWithNavigation="0dp"
|
||||||
|
app:elevation="0dp"
|
||||||
|
app:layout_scrollFlags="scroll|enterAlways|snap"
|
||||||
app:popupTheme="@style/appActionBarPopupMenu">
|
app:popupTheme="@style/appActionBarPopupMenu">
|
||||||
|
|
||||||
<include layout="@layout/search_layout"/>
|
<include layout="@layout/search_layout"/>
|
||||||
|
</com.google.android.material.appbar.MaterialToolbar>
|
||||||
</com.google.android.material.appbar.MaterialToolbar>>
|
|
||||||
|
|
||||||
|
|
||||||
</com.google.android.material.appbar.AppBarLayout>
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
|
<com.nextcloud.talk.newarch.utils.ChangeHandlerCoordinatorLayout
|
||||||
|
android:id="@+id/controller_container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_behavior="com.nextcloud.talk.utils.FABAwareScrollingViewBehavior"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
|
android:id="@+id/floatingActionButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="bottom|end"
|
||||||
|
android:layout_margin="16dp"
|
||||||
|
app:backgroundTint="@color/colorPrimary"
|
||||||
|
app:srcCompat="@drawable/ic_add_white_24px"
|
||||||
|
app:tint="@color/white" />
|
||||||
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
45
app/src/main/res/layout/complete_search_layout.xml
Normal file
45
app/src/main/res/layout/complete_search_layout.xml
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ /*
|
||||||
|
~ * Nextcloud Talk application
|
||||||
|
~ *
|
||||||
|
~ * @author Mario Danic
|
||||||
|
~ * Copyright (C) 2017-2020 Mario Danic <mario@lovelyhq.com>
|
||||||
|
~ *
|
||||||
|
~ * 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/>.
|
||||||
|
~ */
|
||||||
|
-->
|
||||||
|
|
||||||
|
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
|
android:id="@+id/appBarToolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:elevation="0dp">
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_scrollFlags="enterAlways|scroll|snap"
|
||||||
|
>
|
||||||
|
|
||||||
|
<include layout="@layout/search_layout"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_width="64dp"
|
||||||
|
/>
|
||||||
|
</com.google.android.material.appbar.MaterialToolbar>
|
||||||
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
</merge>
|
@ -30,8 +30,7 @@
|
|||||||
android:id="@+id/swipeRefreshLayoutView"
|
android:id="@+id/swipeRefreshLayoutView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:visibility="visible"
|
android:visibility="visible">
|
||||||
app:layout_behavior="com.nextcloud.talk.utils.FABAwareScrollingViewBehavior">
|
|
||||||
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
@ -44,14 +43,4 @@
|
|||||||
|
|
||||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||||
|
|
||||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
|
||||||
android:id="@+id/floatingActionButton"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="bottom|end"
|
|
||||||
android:layout_margin="16dp"
|
|
||||||
app:backgroundTint="@color/colorPrimary"
|
|
||||||
app:srcCompat="@drawable/ic_add_white_24px"
|
|
||||||
app:tint="@color/white" />
|
|
||||||
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
@ -22,43 +22,40 @@
|
|||||||
|
|
||||||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
>
|
|
||||||
|
|
||||||
<androidx.cardview.widget.CardView
|
<androidx.cardview.widget.CardView
|
||||||
android:id="@+id/searchCardView"
|
android:id="@+id/searchCardView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="48dp"
|
android:layout_height="48dp"
|
||||||
android:clickable="true"
|
android:layout_centerHorizontal="true"
|
||||||
android:focusable="true"
|
android:layout_marginHorizontal="12dp"
|
||||||
android:layout_marginVertical="8dp"
|
|
||||||
android:background="@color/transparent"
|
android:background="@color/transparent"
|
||||||
app:cardUseCompatPadding="false"
|
android:clickable="true"
|
||||||
app:cardBackgroundColor="@color/transparent"
|
|
||||||
app:cardElevation="0dp"
|
|
||||||
android:elevation="0dp"
|
android:elevation="0dp"
|
||||||
|
android:focusable="true"
|
||||||
|
app:cardBackgroundColor="@color/transparent"
|
||||||
app:cardCornerRadius="4dp"
|
app:cardCornerRadius="4dp"
|
||||||
|
app:cardElevation="0dp"
|
||||||
|
app:cardUseCompatPadding="false"
|
||||||
tools:cardCornerRadius="4dp"
|
tools:cardCornerRadius="4dp"
|
||||||
tools:cardElevation="0dp"
|
tools:cardElevation="0dp"
|
||||||
android:clipToPadding="true"
|
>
|
||||||
android:clipChildren="true"
|
|
||||||
android:animateLayoutChanges="true"
|
|
||||||
android:layout_centerHorizontal="true">
|
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:clipToPadding="true"
|
android:layout_height="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:background="@color/colorPrimary"
|
||||||
android:background="@color/colorPrimary">
|
android:clipToPadding="true">
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/leftContainer"
|
android:id="@+id/leftContainer"
|
||||||
android:visibility="gone"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
android:layout_marginStart="16dp"
|
android:layout_marginStart="16dp"
|
||||||
android:layout_centerVertical="true">
|
android:visibility="gone">
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/leftButton"
|
android:id="@+id/leftButton"
|
||||||
@ -67,8 +64,8 @@
|
|||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:background="?attr/selectableItemBackgroundBorderless"
|
android:background="?attr/selectableItemBackgroundBorderless"
|
||||||
android:scaleType="fitCenter"
|
android:scaleType="fitCenter"
|
||||||
android:tint="@color/fg_inverse"
|
|
||||||
android:src="@drawable/ic_arrow_back_black_24dp"
|
android:src="@drawable/ic_arrow_back_black_24dp"
|
||||||
|
android:tint="@color/fg_inverse"
|
||||||
android:visibility="visible"
|
android:visibility="visible"
|
||||||
tools:src="@drawable/ic_arrow_back_black_24dp" />
|
tools:src="@drawable/ic_arrow_back_black_24dp" />
|
||||||
|
|
||||||
@ -85,38 +82,58 @@
|
|||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/inputEditText"
|
android:id="@+id/inputEditText"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="start|center"
|
|
||||||
android:layout_toEndOf="@id/leftContainer"
|
|
||||||
android:layout_alignWithParentIfMissing="true"
|
android:layout_alignWithParentIfMissing="true"
|
||||||
android:inputType="textNoSuggestions"
|
|
||||||
android:layout_marginStart="16dp"
|
android:layout_marginStart="16dp"
|
||||||
android:imeOptions="actionSearch|flagNoExtractUi"
|
|
||||||
android:lines="1"
|
|
||||||
android:layout_marginEnd="16dp"
|
android:layout_marginEnd="16dp"
|
||||||
android:maxLines="1"
|
android:layout_toStartOf="@id/rightContainer"
|
||||||
|
android:layout_toEndOf="@id/leftContainer"
|
||||||
android:background="@null"
|
android:background="@null"
|
||||||
android:textSize="16sp"
|
|
||||||
tools:hint="Search"
|
|
||||||
android:layout_toStartOf="@id/rightButton"/>
|
|
||||||
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/rightButton"
|
|
||||||
android:layout_width="32dp"
|
|
||||||
android:layout_height="32dp"
|
|
||||||
android:layout_marginEnd="16dp"
|
|
||||||
android:layout_alignParentEnd="true"
|
|
||||||
android:transitionName="userAvatar.transitionTag"
|
|
||||||
android:layout_centerVertical="true"
|
android:layout_centerVertical="true"
|
||||||
android:scaleType="fitCenter"
|
android:imeOptions="actionSearch|flagNoExtractUi"
|
||||||
|
android:inputType="textNoSuggestions"
|
||||||
|
android:lines="1"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:textCursorDrawable="@null"
|
||||||
|
android:textSize="16sp"
|
||||||
|
tools:hint="Search" />
|
||||||
|
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/rightContainer"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:layout_marginEnd="16dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/clearButton"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:background="?attr/selectableItemBackgroundBorderless"
|
||||||
|
android:scaleType="fitCenter"
|
||||||
|
android:src="@drawable/ic_baseline_clear_24"
|
||||||
|
android:tint="@color/white"
|
||||||
|
android:transitionName="userAvatar.transitionTag"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:src="@tools:sample/avatars[0]" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/settingsButton"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_gravity="center"
|
||||||
android:background="?attr/selectableItemBackgroundBorderless"
|
android:background="?attr/selectableItemBackgroundBorderless"
|
||||||
|
android:scaleType="fitCenter"
|
||||||
android:src="@drawable/ic_settings_white_24dp"
|
android:src="@drawable/ic_settings_white_24dp"
|
||||||
tools:src="@tools:sample/avatars[0]"
|
android:transitionName="userAvatar.transitionTag"
|
||||||
android:visibility="visible" />
|
android:visibility="visible"
|
||||||
|
tools:src="@tools:sample/avatars[0]" />
|
||||||
|
|
||||||
</RelativeLayout>
|
</FrameLayout>
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
</androidx.cardview.widget.CardView>
|
</androidx.cardview.widget.CardView></merge>
|
||||||
</merge>
|
|
Loading…
Reference in New Issue
Block a user