mirror of
https://github.com/nextcloud/talk-android
synced 2025-07-10 22:34:15 +01:00
wip: view poll results
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
This commit is contained in:
parent
7d8aebe234
commit
5a070f5e1b
@ -25,6 +25,7 @@ import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.nextcloud.talk.remotefilebrowser.viewmodels.RemoteFileBrowserItemsViewModel
|
||||
import com.nextcloud.talk.messagesearch.MessageSearchViewModel
|
||||
import com.nextcloud.talk.polls.viewmodels.PollResultsViewModel
|
||||
import com.nextcloud.talk.polls.viewmodels.PollViewModel
|
||||
import com.nextcloud.talk.polls.viewmodels.PollVoteViewModel
|
||||
import com.nextcloud.talk.shareditems.viewmodels.SharedItemsViewModel
|
||||
@ -73,6 +74,11 @@ abstract class ViewModelModule {
|
||||
@ViewModelKey(PollVoteViewModel::class)
|
||||
abstract fun pollVoteViewModel(viewModel: PollVoteViewModel): ViewModel
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ViewModelKey(PollResultsViewModel::class)
|
||||
abstract fun pollResultsViewModel(viewModel: PollResultsViewModel): ViewModel
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ViewModelKey(RemoteFileBrowserItemsViewModel::class)
|
||||
|
@ -0,0 +1,8 @@
|
||||
package com.nextcloud.talk.polls.adapters
|
||||
|
||||
class PollResultItem(
|
||||
val pollOption: String,
|
||||
val pollPercent: Int
|
||||
|
||||
// val voters....
|
||||
)
|
@ -0,0 +1,5 @@
|
||||
package com.nextcloud.talk.polls.adapters
|
||||
|
||||
interface PollResultItemClickListener {
|
||||
fun onClick(pollResultItem: PollResultItem)
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package com.nextcloud.talk.polls.adapters
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.nextcloud.talk.databinding.PollResultItemBinding
|
||||
|
||||
class PollResultViewHolder(
|
||||
private val binding: PollResultItemBinding
|
||||
) : RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
fun bind(pollResultItem: PollResultItem, clickListener: PollResultItemClickListener) {
|
||||
binding.root.setOnClickListener { clickListener.onClick(pollResultItem) }
|
||||
binding.pollOptionText.text = pollResultItem.pollOption
|
||||
binding.pollOptionPercentText.text = pollResultItem.pollPercent.toString() + "%"
|
||||
binding.pollOptionBar.progress = pollResultItem.pollPercent
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package com.nextcloud.talk.polls.adapters
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.nextcloud.talk.databinding.PollResultItemBinding
|
||||
|
||||
class PollResultsAdapter(
|
||||
private val clickListener: PollResultItemClickListener
|
||||
) : RecyclerView.Adapter<PollResultViewHolder>() {
|
||||
internal var list: MutableList<PollResultItem> = ArrayList<PollResultItem>()
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PollResultViewHolder {
|
||||
val itemBinding = PollResultItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
return PollResultViewHolder(itemBinding)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: PollResultViewHolder, position: Int) {
|
||||
holder.bind(list[position], clickListener)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return list.size
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@ data class Poll(
|
||||
val id: String,
|
||||
val question: String?,
|
||||
val options: List<String>?,
|
||||
val votes: List<Int>?,
|
||||
val votes: Map<String, Int>?,
|
||||
val actorType: String?,
|
||||
val actorId: String?,
|
||||
val actorDisplayName: String?,
|
||||
|
@ -49,7 +49,6 @@ class PollRepositoryImpl(private val ncApi: NcApi, private val currentUserProvid
|
||||
),
|
||||
).map { mapToPoll(it.ocs?.data!!) }
|
||||
|
||||
// // // TODO actual api call
|
||||
// return Observable.just(
|
||||
// Poll(
|
||||
// id = "aaa",
|
||||
|
@ -37,7 +37,7 @@ data class PollResponse(
|
||||
var options: ArrayList<String>? = null,
|
||||
|
||||
@JsonField(name = ["votes"])
|
||||
var votes: ArrayList<Int>? = null,
|
||||
var votes: Map<String, Int>? = null,
|
||||
|
||||
@JsonField(name = ["actorType"])
|
||||
var actorType: String? = null,
|
||||
|
@ -12,6 +12,7 @@ import androidx.lifecycle.ViewModelProvider
|
||||
import autodagger.AutoInjector
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||
import com.nextcloud.talk.databinding.DialogPollMainBinding
|
||||
import com.nextcloud.talk.polls.model.Poll
|
||||
import com.nextcloud.talk.polls.viewmodels.PollViewModel
|
||||
import javax.inject.Inject
|
||||
|
||||
@ -58,16 +59,21 @@ class PollMainDialogFragment(
|
||||
viewModel.viewState.observe(viewLifecycleOwner) { state ->
|
||||
when (state) {
|
||||
PollViewModel.InitialState -> {}
|
||||
is PollViewModel.PollClosedState -> TODO()
|
||||
is PollViewModel.PollOpenState -> {
|
||||
val contentFragment = PollVoteFragment(
|
||||
viewModel,
|
||||
roomToken,
|
||||
pollId
|
||||
)
|
||||
val transaction = childFragmentManager.beginTransaction()
|
||||
transaction.replace(binding.messagePollContentFragment.id, contentFragment)
|
||||
transaction.commit()
|
||||
|
||||
is PollViewModel.PollVotedState -> {
|
||||
if (state.poll.resultMode == Poll.RESULT_MODE_HIDDEN) {
|
||||
showVoteFragment()
|
||||
} else {
|
||||
showResultsFragment()
|
||||
}
|
||||
}
|
||||
|
||||
is PollViewModel.PollUnvotedState -> {
|
||||
if (state.poll.status == Poll.STATUS_CLOSED) {
|
||||
showResultsFragment()
|
||||
} else {
|
||||
showVoteFragment()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -75,6 +81,28 @@ class PollMainDialogFragment(
|
||||
viewModel.initialize(roomToken, pollId)
|
||||
}
|
||||
|
||||
private fun showVoteFragment() {
|
||||
val contentFragment = PollVoteFragment(
|
||||
viewModel,
|
||||
roomToken,
|
||||
pollId
|
||||
)
|
||||
val transaction = childFragmentManager.beginTransaction()
|
||||
transaction.replace(binding.messagePollContentFragment.id, contentFragment)
|
||||
transaction.commit()
|
||||
}
|
||||
|
||||
private fun showResultsFragment() {
|
||||
val contentFragment = PollResultsFragment(
|
||||
viewModel,
|
||||
roomToken,
|
||||
pollId
|
||||
)
|
||||
val transaction = childFragmentManager.beginTransaction()
|
||||
transaction.replace(binding.messagePollContentFragment.id, contentFragment)
|
||||
transaction.commit()
|
||||
}
|
||||
|
||||
/**
|
||||
* Fragment creator
|
||||
*/
|
||||
|
@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Nextcloud Talk application
|
||||
*
|
||||
* @author Álvaro Brey
|
||||
* Copyright (C) 2022 Álvaro Brey
|
||||
* Copyright (C) 2022 Nextcloud GmbH
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.nextcloud.talk.polls.ui
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import autodagger.AutoInjector
|
||||
import com.nextcloud.talk.R
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||
import com.nextcloud.talk.databinding.DialogPollResultsBinding
|
||||
import com.nextcloud.talk.polls.adapters.PollResultItem
|
||||
import com.nextcloud.talk.polls.adapters.PollResultItemClickListener
|
||||
import com.nextcloud.talk.polls.adapters.PollResultsAdapter
|
||||
import com.nextcloud.talk.polls.model.Poll
|
||||
import com.nextcloud.talk.polls.viewmodels.PollResultsViewModel
|
||||
import com.nextcloud.talk.polls.viewmodels.PollViewModel
|
||||
import javax.inject.Inject
|
||||
|
||||
@AutoInjector(NextcloudTalkApplication::class)
|
||||
class PollResultsFragment(
|
||||
private val parentViewModel: PollViewModel,
|
||||
private val roomToken: String,
|
||||
private val pollId: String
|
||||
) : Fragment(), PollResultItemClickListener {
|
||||
|
||||
@Inject
|
||||
lateinit var viewModelFactory: ViewModelProvider.Factory
|
||||
|
||||
lateinit var viewModel: PollResultsViewModel
|
||||
|
||||
var _binding: DialogPollResultsBinding? = null
|
||||
val binding: DialogPollResultsBinding
|
||||
get() = _binding!!
|
||||
|
||||
private var adapter: PollResultsAdapter? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
|
||||
viewModel = ViewModelProvider(this, viewModelFactory)[PollResultsViewModel::class.java]
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = DialogPollResultsBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
adapter = PollResultsAdapter(this)
|
||||
_binding?.pollResultsList?.adapter = adapter
|
||||
_binding?.pollResultsList?.layoutManager = LinearLayoutManager(context)
|
||||
|
||||
parentViewModel.viewState.observe(viewLifecycleOwner) { state ->
|
||||
if (state is PollViewModel.PollVotedState &&
|
||||
state.poll.resultMode == Poll.RESULT_MODE_PUBLIC
|
||||
) {
|
||||
|
||||
initPollResults(state.poll)
|
||||
initAmountVotersInfo(state)
|
||||
initEditButton(state)
|
||||
} else if (state is PollViewModel.PollUnvotedState &&
|
||||
state.poll.status == Poll.STATUS_CLOSED
|
||||
) {
|
||||
Log.d(TAG, "show results also if self never voted")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private fun initPollResults(poll: Poll) {
|
||||
if (poll.details != null) {
|
||||
val votersAmount = poll.details.size
|
||||
val oneVoteInPercent = 100 / votersAmount // TODO: poll.numVoters when fixed on api
|
||||
|
||||
poll.options?.forEachIndexed { index, option ->
|
||||
val votersForThisOption = poll.details.filter { it.optionId == index }.size
|
||||
val optionsPercent = oneVoteInPercent * votersForThisOption
|
||||
|
||||
val pollResultItem = PollResultItem(option, optionsPercent) // TODO add participants to PollResultItem
|
||||
adapter?.list?.add(pollResultItem)
|
||||
}
|
||||
} else if (poll.votes != null) {
|
||||
val votersAmount = poll.numVoters
|
||||
val oneVoteInPercent = 100 / votersAmount
|
||||
|
||||
poll.options?.forEachIndexed { index, option ->
|
||||
val votersForThisOption = poll.votes?.filter { it.value == index }?.size!!
|
||||
val optionsPercent = oneVoteInPercent * votersForThisOption
|
||||
|
||||
val pollResultItem = PollResultItem(option, optionsPercent)
|
||||
adapter?.list?.add(pollResultItem)
|
||||
}
|
||||
} else {
|
||||
Log.e(TAG, "failed to get data to show poll results")
|
||||
}
|
||||
}
|
||||
|
||||
private fun initAmountVotersInfo(state: PollViewModel.PollVotedState) {
|
||||
_binding?.pollAmountVoters?.text = String.format(
|
||||
resources.getString(R.string.polls_amount_voters),
|
||||
state.poll.numVoters
|
||||
)
|
||||
}
|
||||
|
||||
private fun initEditButton(state: PollViewModel.PollVotedState) {
|
||||
if (state.poll.status == Poll.STATUS_OPEN && state.poll.resultMode == Poll.RESULT_MODE_PUBLIC) {
|
||||
_binding?.editVoteButton?.visibility = View.VISIBLE
|
||||
_binding?.editVoteButton?.setOnClickListener {
|
||||
parentViewModel.edit()
|
||||
}
|
||||
} else {
|
||||
_binding?.editVoteButton?.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val TAG = PollResultsFragment::class.java.simpleName
|
||||
}
|
||||
|
||||
override fun onClick(pollResultItem: PollResultItem) {
|
||||
Log.d(TAG, "click..")
|
||||
}
|
||||
}
|
@ -32,6 +32,7 @@ import androidx.lifecycle.ViewModelProvider
|
||||
import autodagger.AutoInjector
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||
import com.nextcloud.talk.databinding.DialogPollVoteBinding
|
||||
import com.nextcloud.talk.polls.model.Poll
|
||||
import com.nextcloud.talk.polls.viewmodels.PollViewModel
|
||||
import com.nextcloud.talk.polls.viewmodels.PollVoteViewModel
|
||||
import javax.inject.Inject
|
||||
@ -70,7 +71,7 @@ class PollVoteFragment(
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
parentViewModel.viewState.observe(viewLifecycleOwner) { state ->
|
||||
if (state is PollViewModel.PollOpenState) {
|
||||
if (state is PollViewModel.PollUnvotedState) {
|
||||
val poll = state.poll
|
||||
binding.radioGroup.removeAllViews()
|
||||
poll.options?.map { option ->
|
||||
@ -79,6 +80,9 @@ class PollVoteFragment(
|
||||
radioButton.id = index
|
||||
binding.radioGroup.addView(radioButton)
|
||||
}
|
||||
} else if (state is PollViewModel.PollVotedState && state.poll.resultMode == Poll.RESULT_MODE_HIDDEN) {
|
||||
Log.d(TAG, "show vote screen also for resultMode hidden poll when already voted")
|
||||
// TODO: other text for submit button
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Nextcloud Talk application
|
||||
*
|
||||
* @author Álvaro Brey
|
||||
* Copyright (C) 2022 Álvaro Brey
|
||||
* Copyright (C) 2022 Nextcloud GmbH
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.nextcloud.talk.polls.viewmodels
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.nextcloud.talk.polls.repositories.PollRepository
|
||||
import io.reactivex.disposables.Disposable
|
||||
import javax.inject.Inject
|
||||
|
||||
class PollResultsViewModel @Inject constructor(private val repository: PollRepository) : ViewModel() {
|
||||
|
||||
sealed interface ViewState
|
||||
object InitialState : ViewState
|
||||
|
||||
private val _viewState: MutableLiveData<ViewState> = MutableLiveData(InitialState)
|
||||
val viewState: LiveData<ViewState>
|
||||
get() = _viewState
|
||||
|
||||
private var disposable: Disposable? = null
|
||||
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
disposable?.dispose()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val TAG = PollResultsViewModel::class.java.simpleName
|
||||
}
|
||||
}
|
@ -28,11 +28,12 @@ class PollViewModel @Inject constructor(private val repository: PollRepository)
|
||||
private lateinit var roomToken: String
|
||||
private lateinit var pollId: String
|
||||
|
||||
private var editPoll: Boolean = false
|
||||
|
||||
sealed interface ViewState
|
||||
object InitialState : ViewState
|
||||
open class PollOpenState(val poll: Poll) : ViewState
|
||||
open class PollUnvotedState(val poll: Poll) : ViewState
|
||||
open class PollVotedState(val poll: Poll) : ViewState
|
||||
open class PollClosedState(val poll: Poll) : ViewState
|
||||
|
||||
private val _viewState: MutableLiveData<ViewState> = MutableLiveData(InitialState)
|
||||
val viewState: LiveData<ViewState>
|
||||
@ -51,6 +52,11 @@ class PollViewModel @Inject constructor(private val repository: PollRepository)
|
||||
loadPoll() // TODO load other view
|
||||
}
|
||||
|
||||
fun edit() {
|
||||
editPoll = true
|
||||
loadPoll()
|
||||
}
|
||||
|
||||
private fun loadPoll() {
|
||||
repository.getPoll(roomToken, pollId)
|
||||
?.doOnSubscribe { disposable = it }
|
||||
@ -79,11 +85,13 @@ class PollViewModel @Inject constructor(private val repository: PollRepository)
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
// TODO check attributes and decide if poll is open/closed/selfvoted...
|
||||
|
||||
when (poll.status) {
|
||||
Poll.STATUS_OPEN -> _viewState.value = PollOpenState(poll)
|
||||
Poll.STATUS_CLOSED -> _viewState.value = PollClosedState(poll)
|
||||
if (editPoll) {
|
||||
_viewState.value = PollUnvotedState(poll)
|
||||
editPoll = false
|
||||
} else if (poll.votedSelf.isNullOrEmpty()) {
|
||||
_viewState.value = PollUnvotedState(poll)
|
||||
} else {
|
||||
_viewState.value = PollVotedState(poll)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,9 +38,8 @@
|
||||
<androidx.emoji.widget.EmojiTextView
|
||||
android:id="@+id/message_poll_title"
|
||||
android:layout_width="257dp"
|
||||
android:layout_height="55dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:textAlignment="viewStart"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintStart_toEndOf="@id/message_poll_icon"
|
||||
app:layout_constraintTop_toTopOf="@+id/message_poll_icon"
|
||||
@ -50,6 +49,7 @@
|
||||
android:id="@+id/message_poll_content_fragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/message_poll_title"
|
||||
tools:layout_height="400dp" />
|
||||
|
||||
|
62
app/src/main/res/layout/dialog_poll_results.xml
Normal file
62
app/src/main/res/layout/dialog_poll_results.xml
Normal file
@ -0,0 +1,62 @@
|
||||
<!--
|
||||
Nextcloud Android client application
|
||||
|
||||
@author Marcel Hibbe
|
||||
Copyright (C) 2021 Marcel Hibbe <dev@mhibbe.de>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
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/>.
|
||||
-->
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:padding="@dimen/standard_padding"
|
||||
tools:background="@color/white">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/poll_results_list_wrapper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="288dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/poll_results_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
tools:listitem="@layout/poll_result_item" />
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/poll_amount_voters"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:textColor="@color/low_emphasis_text"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/poll_results_list_wrapper"
|
||||
tools:text="Poll results - 93 votes" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/edit_vote_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/edit"
|
||||
android:theme="@style/Button.Primary"
|
||||
app:cornerRadius="@dimen/button_corner_radius"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/poll_results_list_wrapper" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -28,9 +28,9 @@
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
android:layout_width="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
</RadioGroup>
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:layout_height="400dp"
|
||||
tools:layout_width="match_parent"></RadioGroup>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/submitVote"
|
||||
|
33
app/src/main/res/layout/poll_result_item.xml
Normal file
33
app/src/main/res/layout/poll_result_item.xml
Normal file
@ -0,0 +1,33 @@
|
||||
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/standard_padding"
|
||||
tools:background="@color/white">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/poll_option_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Option Number One" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/poll_option_percent_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="25 %" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/poll_option_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintStart_toStartOf="@+id/poll_option_text"
|
||||
app:layout_constraintTop_toBottomOf="@+id/poll_option_text"
|
||||
style="?android:attr/progressBarStyleHorizontal" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -534,6 +534,9 @@
|
||||
<string name="message_search_begin_typing">Start typing to search …</string>
|
||||
<string name="message_search_begin_empty">No search results</string>
|
||||
|
||||
<!-- Polls -->
|
||||
<string name="polls_amount_voters">Poll results - %1$s votes</string>
|
||||
|
||||
<string name="title_attachments">Attachments</string>
|
||||
|
||||
<string name="reactions_tab_all">All</string>
|
||||
|
Loading…
Reference in New Issue
Block a user