Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added icon animations to upvote and downvote icons for Doubts and Answers #68

Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.doubtless.doubtless.screens.answers.viewholder

import android.view.View
import android.widget.CheckBox
import android.widget.ImageView
import android.widget.TextView
import androidx.core.view.isVisible
Expand All @@ -11,11 +12,11 @@ import com.doubtless.doubtless.R
import com.doubtless.doubtless.screens.answers.AnswerData
import com.doubtless.doubtless.screens.doubt.usecases.VotingUseCase
import com.doubtless.doubtless.utils.Utils
import com.doubtless.doubtless.utils.addStateListAnimation
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.util.Date
import kotlin.math.ceil
import java.util.*
import kotlin.math.floor


Expand All @@ -32,8 +33,8 @@ class AnswerViewHolder(itemView: View, private val interactionListener: Interact
private val ivDp: ImageView
private val tvYear: TextView
private val tvVotes: TextView
private val ivUpVote: ImageView
private val ivDownVote: ImageView
private val upVote: CheckBox
private val downVote: CheckBox

init {
authorName = itemView.findViewById(R.id.tv_author_name)
Expand All @@ -42,8 +43,8 @@ class AnswerViewHolder(itemView: View, private val interactionListener: Interact
ivDp = itemView.findViewById(R.id.iv_dp_author)
tvYear = itemView.findViewById(R.id.user_year)
tvVotes = itemView.findViewById(R.id.tv_votes)
ivUpVote = itemView.findViewById(R.id.iv_votes)
ivDownVote = itemView.findViewById(R.id.iv_downvote)
upVote = itemView.findViewById(R.id.cb_upvote)
downVote = itemView.findViewById(R.id.cb_downvote)
}

fun setData(answerData: AnswerData) {
Expand All @@ -66,8 +67,10 @@ class AnswerViewHolder(itemView: View, private val interactionListener: Interact
val votingUseCase = DoubtlessApp.getInstance().getAppCompRoot().getAnswerVotingDoubtCase(answerData.copy())
setVotesUi(answerData, votingUseCase)

ivUpVote.setOnClickListener {
upVote.setOnClickListener {
CoroutineScope(Dispatchers.Main).launch {
if (it.stateListAnimator == null)
it.addStateListAnimation(R.animator.scale_votes_icon)

val result = votingUseCase.upvoteDoubt()

Expand All @@ -81,8 +84,10 @@ class AnswerViewHolder(itemView: View, private val interactionListener: Interact
}
}

ivDownVote.setOnClickListener {
downVote.setOnClickListener {
CoroutineScope(Dispatchers.Main).launch {
if (it.stateListAnimator == null)
it.addStateListAnimation(R.animator.scale_votes_icon)

val result = votingUseCase.downVoteDoubt()

Expand All @@ -102,19 +107,22 @@ class AnswerViewHolder(itemView: View, private val interactionListener: Interact
}

private fun setVotesUi(answerData: AnswerData, votingUseCase: VotingUseCase) {
ivDownVote.setImageDrawable(itemView.context.getDrawable(R.drawable.ic_baseline_thumb_up_off_alt_24))
ivUpVote.setImageDrawable(itemView.context.getDrawable(R.drawable.ic_baseline_thumb_up_off_alt_24))
tvVotes.text = floor(answerData.netVotes).toInt().toString()

CoroutineScope(Dispatchers.Main).launch {
val currentState = votingUseCase.getUserCurrentState()

if (currentState == VotingUseCase.UPVOTED)
ivUpVote.setImageDrawable(itemView.context.getDrawable(R.drawable.ic_baseline_thumb_up_filled))

if (currentState == VotingUseCase.DOWNVOTED)
ivDownVote.setImageDrawable(itemView.context.getDrawable(R.drawable.ic_baseline_thumb_up_filled))
when (votingUseCase.getUserCurrentState()) {
VotingUseCase.UPVOTED -> {
downVote.isClickable = false
upVote.isChecked = true
}
VotingUseCase.DOWNVOTED -> {
upVote.isClickable = false
downVote.isChecked = true
}
else -> {
downVote.isClickable = true
upVote.isClickable = true
}
}
}
}

}
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
package com.doubtless.doubtless.screens.doubt.view.viewholder

import android.content.res.ColorStateList
import android.text.util.Linkify
import android.util.Log
import android.view.View
import android.widget.CheckBox
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
Expand All @@ -17,6 +14,7 @@ import com.doubtless.doubtless.screens.doubt.DoubtData
import com.doubtless.doubtless.screens.doubt.usecases.VotingUseCase
import com.doubtless.doubtless.utils.Utils
import com.doubtless.doubtless.utils.Utils.flatten
import com.doubtless.doubtless.utils.addStateListAnimation
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
Expand All @@ -40,8 +38,8 @@ class DoubtPreviewViewHolder(
private val description: TextView
private val ivDp: ImageView
private val tvNetVotes: TextView
private val ivUpvotes: ImageView
private val ivDownvotes: ImageView
private val upvotes: CheckBox
private val downvotes: CheckBox
private val tvAnswers: TextView
private val tvTags: TextView
private val tvCollege: TextView
Expand All @@ -60,11 +58,11 @@ class DoubtPreviewViewHolder(
tvAnswers = view.findViewById(R.id.tv_answers)
tvTags = view.findViewById(R.id.tv_tags)
tvCollege = view.findViewById(R.id.user_college)
ivUpvotes = view.findViewById(R.id.iv_upvotes)
ivDownvotes = view.findViewById(R.id.iv_downvote)
upvotes = view.findViewById(R.id.cb_upvotes)
downvotes = view.findViewById(R.id.cb_downvote)

ivUpvotes.isVisible = showVotingLayout
ivDownvotes.isVisible = showVotingLayout
upvotes.isVisible = showVotingLayout
downvotes.isVisible = showVotingLayout
}

fun setData(doubtData: DoubtData) {
Expand Down Expand Up @@ -114,8 +112,11 @@ class DoubtPreviewViewHolder(

setVotesUi(doubtData, votingUseCase)

ivUpvotes.setOnClickListener {

upvotes.setOnClickListener {
CoroutineScope(Dispatchers.Main).launch {
if (it.stateListAnimator == null)
it.addStateListAnimation(R.animator.scale_votes_icon)

val result = votingUseCase.upvoteDoubt()

Expand All @@ -130,8 +131,10 @@ class DoubtPreviewViewHolder(
}
}

ivDownvotes.setOnClickListener {
downvotes.setOnClickListener {
CoroutineScope(Dispatchers.Main).launch {
if (it.stateListAnimator == null)
it.addStateListAnimation(R.animator.scale_votes_icon)

val result = votingUseCase.downVoteDoubt()

Expand All @@ -148,23 +151,22 @@ class DoubtPreviewViewHolder(
}

private fun setVotesUi(doubtData: DoubtData, votingUseCase: VotingUseCase) {
ivDownvotes.setImageDrawable(itemView.context.getDrawable(R.drawable.ic_baseline_thumb_up_off_alt_24))

ivUpvotes.setImageDrawable(itemView.context.getDrawable(R.drawable.ic_baseline_thumb_up_off_alt_24))
// ivUpvotes.setColorFilter(ContextCompat.getColor(itemView.context, R.color.grey), android.graphics.PorterDuff.Mode.SRC_IN);

tvNetVotes.text = floor(doubtData.netVotes).toInt().toString()

CoroutineScope(Dispatchers.Main).launch {
val currentState = votingUseCase.getUserCurrentState()

if (currentState == VotingUseCase.UPVOTED) {
ivUpvotes.setImageDrawable(itemView.context.getDrawable(R.drawable.ic_baseline_thumb_up_filled))
// ivUpvotes.setColorFilter(ContextCompat.getColor(itemView.context, R.color.purple), android.graphics.PorterDuff.Mode.SRC_IN);
when (votingUseCase.getUserCurrentState()) {
VotingUseCase.UPVOTED -> {
downvotes.isClickable = false
upvotes.isChecked = true
}
VotingUseCase.DOWNVOTED -> {
upvotes.isClickable = false
downvotes.isChecked = true
}
else -> {
downvotes.isClickable = true
upvotes.isClickable = true
}
}

if (currentState == VotingUseCase.DOWNVOTED)
ivDownvotes.setImageDrawable(itemView.context.getDrawable(R.drawable.ic_baseline_thumb_up_filled))
}
}
}
12 changes: 12 additions & 0 deletions app/src/main/java/com/doubtless/doubtless/utils/Extensions.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.doubtless.doubtless.utils

import android.animation.AnimatorInflater
import android.view.View
import androidx.annotation.AnimatorRes

fun View.addStateListAnimation(@AnimatorRes animation: Int) {
this.stateListAnimator = AnimatorInflater.loadStateListAnimator(
this.context,
animation
)
}
86 changes: 86 additions & 0 deletions app/src/main/res/animator/scale_votes_icon.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true">
<set>
<objectAnimator
android:duration="@android:integer/config_shortAnimTime"
android:propertyName="scaleX"
android:valueTo="1.525"
android:valueType="floatType" />
<objectAnimator
android:duration="@android:integer/config_shortAnimTime"
android:propertyName="scaleY"
android:valueTo="1.525"
android:valueType="floatType" />

<objectAnimator
android:duration="@android:integer/config_shortAnimTime"
android:propertyName="translationZ"
android:valueTo="4dp"
android:valueType="floatType" />
<objectAnimator
android:duration="@android:integer/config_shortAnimTime"
android:propertyName="scaleX"
android:valueTo="1.0"
android:startOffset="@android:integer/config_shortAnimTime"
android:valueType="floatType" />

<objectAnimator
android:duration="@android:integer/config_shortAnimTime"
android:propertyName="scaleY"
android:startOffset="@android:integer/config_shortAnimTime"
android:valueTo="1.0"
android:valueType="floatType" />

<objectAnimator
android:duration="@android:integer/config_shortAnimTime"
android:propertyName="translationZ"
android:startOffset="@android:integer/config_shortAnimTime"
android:valueTo="0dp"
android:valueType="floatType" />
</set>
</item>
<item android:state_checked="false">
<set>
<set>
<objectAnimator
android:duration="@android:integer/config_shortAnimTime"
android:propertyName="scaleX"
android:valueTo="1.525"
android:valueType="floatType" />
<objectAnimator
android:duration="@android:integer/config_shortAnimTime"
android:propertyName="scaleY"
android:valueTo="1.525"
android:valueType="floatType" />

<objectAnimator
android:duration="@android:integer/config_shortAnimTime"
android:propertyName="translationZ"
android:valueTo="4dp"
android:valueType="floatType" />
<objectAnimator
android:duration="@android:integer/config_shortAnimTime"
android:propertyName="scaleX"
android:valueTo="1.0"
android:startOffset="@android:integer/config_shortAnimTime"
android:valueType="floatType" />

<objectAnimator
android:duration="@android:integer/config_shortAnimTime"
android:propertyName="scaleY"
android:startOffset="@android:integer/config_shortAnimTime"
android:valueTo="1.0"
android:valueType="floatType" />

<objectAnimator
android:duration="@android:integer/config_shortAnimTime"
android:propertyName="translationZ"
android:startOffset="@android:integer/config_shortAnimTime"
android:valueTo="0dp"
android:valueType="floatType" />
</set>
</set>
</item>

</selector>
5 changes: 5 additions & 0 deletions app/src/main/res/drawable/upvote_icon.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:drawable="@drawable/ic_baseline_thumb_up_filled"/>
<item android:drawable="@drawable/ic_baseline_thumb_up_off_alt_24"/>
</selector>
37 changes: 21 additions & 16 deletions app/src/main/res/layout/answer_layout.xml
Original file line number Diff line number Diff line change
Expand Up @@ -100,15 +100,17 @@
app:layout_constraintStart_toStartOf="@+id/tv_author_name"
app:layout_constraintTop_toBottomOf="@+id/iv_dp_author" />

<ImageView
android:id="@+id/iv_votes"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
<CheckBox
android:id="@+id/cb_upvote"
android:layout_width="24dp"
android:layout_height="24dp"
android:background="@drawable/upvote_icon"
android:backgroundTint="@color/grey"
android:padding="6dp"
android:src="@drawable/ic_baseline_thumb_up_off_alt_24"
android:button="@null"
android:checked="false"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/author_answer_description_2"
app:tint="@color/grey" />
app:layout_constraintTop_toBottomOf="@id/author_answer_description_2" />

<TextView
android:id="@+id/tv_votes"
Expand All @@ -120,20 +122,23 @@
android:text="211"
android:textColor="@color/grey"
android:textSize="14dp"
app:layout_constraintBottom_toBottomOf="@id/iv_votes"
app:layout_constraintStart_toEndOf="@id/iv_votes"
app:layout_constraintTop_toTopOf="@id/iv_votes" />
app:layout_constraintBottom_toBottomOf="@id/cb_upvote"
app:layout_constraintStart_toEndOf="@id/cb_upvote"
app:layout_constraintTop_toTopOf="@id/cb_upvote" />

<ImageView
android:id="@+id/iv_downvote"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
<CheckBox
android:id="@+id/cb_downvote"
android:layout_width="24dp"
android:layout_height="24dp"
android:background="@drawable/upvote_icon"
android:backgroundTint="@color/grey"
android:button="@null"
android:checked="false"
android:layout_marginStart="6dp"
android:padding="6dp"
android:rotation="180"
android:src="@drawable/ic_baseline_thumb_up_off_alt_24"
app:layout_constraintStart_toEndOf="@id/tv_votes"
app:layout_constraintTop_toTopOf="@id/iv_votes"
app:layout_constraintTop_toTopOf="@id/cb_upvote"
app:tint="@color/grey" />

</androidx.constraintlayout.widget.ConstraintLayout>
Expand Down
Loading