introducing confetti animation using konfetti library

pull/1743/head
Gokul K 2 years ago
parent e4d2c93a1d
commit a2ae1fdd49

@ -115,6 +115,7 @@ dependencies {
implementation("androidx.legacy:legacy-support-v4:1.0.0")
implementation("com.google.android.material:material:1.8.0")
implementation("com.opencsv:opencsv:5.7.1")
implementation("nl.dionsegijn:konfetti-xml:2.0.2")
implementation(project(":uhabits-core"))
kapt("com.google.dagger:dagger-compiler:$daggerVersion")
kaptAndroidTest("com.google.dagger:dagger-compiler:$daggerVersion")

@ -24,6 +24,7 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View.GONE
import android.view.View.VISIBLE
import android.widget.LinearLayout
import androidx.appcompat.app.AppCompatDialogFragment
import org.isoron.uhabits.HabitsApplication
import org.isoron.uhabits.R
@ -34,6 +35,7 @@ import org.isoron.uhabits.core.models.Entry.Companion.YES_MANUAL
import org.isoron.uhabits.databinding.CheckmarkPopupBinding
import org.isoron.uhabits.utils.InterfaceUtils.getFontAwesome
import org.isoron.uhabits.utils.sres
import org.isoron.uhabits.utils.showConfetti
class CheckmarkDialog : AppCompatDialogFragment() {
var onToggle: (Int, String) -> Unit = { _, _ -> }
@ -64,6 +66,10 @@ class CheckmarkDialog : AppCompatDialogFragment() {
val notes = view.notes.text.toString().trim()
onToggle(v, notes)
requireDialog().dismiss()
val konfettiView = requireActivity().findViewById<LinearLayout>(R.id.konfettiLayout)
when (v) {
YES_MANUAL -> showConfetti(konfettiView)
}
}
view.yesBtn.setOnClickListener { onClick(YES_MANUAL) }
view.noBtn.setOnClickListener { onClick(NO) }

@ -7,6 +7,7 @@ import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.widget.LinearLayout
import androidx.appcompat.app.AppCompatDialogFragment
import org.isoron.uhabits.HabitsApplication
import org.isoron.uhabits.R
@ -14,6 +15,7 @@ import org.isoron.uhabits.core.models.Entry
import org.isoron.uhabits.databinding.CheckmarkPopupBinding
import org.isoron.uhabits.utils.InterfaceUtils
import org.isoron.uhabits.utils.requestFocusWithKeyboard
import org.isoron.uhabits.utils.showConfetti
import org.isoron.uhabits.utils.sres
import java.text.DecimalFormat
import java.text.DecimalFormatSymbols
@ -100,5 +102,11 @@ class NumberDialog : AppCompatDialogFragment() {
val notes = view.notes.text.toString()
onToggle(value, notes)
requireDialog().dismiss()
val v = requireActivity().findViewById<LinearLayout>(R.id.konfettiLayout)
if (value > 0.0) {
showConfetti(v)
}
}
}

@ -44,6 +44,7 @@ import org.isoron.uhabits.utils.addAtBottom
import org.isoron.uhabits.utils.addAtTop
import org.isoron.uhabits.utils.addBelow
import org.isoron.uhabits.utils.buildToolbar
import org.isoron.uhabits.utils.buildKonfettiView
import org.isoron.uhabits.utils.currentTheme
import org.isoron.uhabits.utils.dim
import org.isoron.uhabits.utils.dp
@ -69,6 +70,7 @@ class ListHabitsRootView @Inject constructor(
val listView: HabitCardListView = habitCardListViewFactory.create()
val llEmpty = EmptyListView(context)
val tbar = buildToolbar()
val konfettiView = buildKonfettiView()
val progressBar = TaskProgressBar(context, runner)
val hintView: HintView
val header = HeaderView(context, preferences, midnightTimer)
@ -80,6 +82,7 @@ class ListHabitsRootView @Inject constructor(
val rootView = RelativeLayout(context).apply {
background = sres.getDrawable(R.attr.windowBackgroundColor)
addAtTop(konfettiView)
addAtTop(tbar)
addBelow(header, tbar)
addBelow(listView, header, height = MATCH_PARENT)

@ -39,6 +39,7 @@ import org.isoron.uhabits.core.preferences.Preferences
import org.isoron.uhabits.inject.ActivityContext
import org.isoron.uhabits.utils.drawNotesIndicator
import org.isoron.uhabits.utils.getFontAwesome
import org.isoron.uhabits.utils.showConfetti
import org.isoron.uhabits.utils.sp
import org.isoron.uhabits.utils.sres
import org.isoron.uhabits.utils.toMeasureSpec
@ -88,7 +89,7 @@ class CheckmarkButtonView(
setOnLongClickListener(this)
}
fun performToggle() {
fun performToggle(v: View) {
value = Entry.nextToggleValue(
value = value,
isSkipEnabled = preferences.isSkipEnabled,
@ -96,17 +97,20 @@ class CheckmarkButtonView(
)
onToggle(value, notes)
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
when (value) {
YES_MANUAL -> showConfetti(v.rootView)
}
invalidate()
}
override fun onClick(v: View) {
if (preferences.isShortToggleEnabled) performToggle()
if (preferences.isShortToggleEnabled) performToggle(v)
else onEdit()
}
override fun onLongClick(v: View): Boolean {
if (preferences.isShortToggleEnabled) onEdit()
else performToggle()
else performToggle(v)
return true
}

@ -36,6 +36,7 @@ import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.view.WindowManager
import android.widget.LinearLayout
import android.widget.RelativeLayout
import android.widget.RelativeLayout.ALIGN_PARENT_BOTTOM
import android.widget.RelativeLayout.ALIGN_PARENT_TOP
@ -46,6 +47,10 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import androidx.core.content.FileProvider
import com.google.android.material.snackbar.Snackbar
import nl.dionsegijn.konfetti.core.Party
import nl.dionsegijn.konfetti.core.Position
import nl.dionsegijn.konfetti.core.emitter.Emitter
import nl.dionsegijn.konfetti.xml.KonfettiView
import org.isoron.platform.gui.toInt
import org.isoron.uhabits.HabitsApplication
import org.isoron.uhabits.R
@ -53,6 +58,7 @@ import org.isoron.uhabits.activities.AndroidThemeSwitcher
import org.isoron.uhabits.core.models.PaletteColor
import org.isoron.uhabits.core.ui.views.Theme
import java.io.File
import java.util.concurrent.TimeUnit
fun RelativeLayout.addBelow(
view: View,
@ -79,7 +85,9 @@ fun RelativeLayout.addAtBottom(
view.layoutParams = RelativeLayout.LayoutParams(width, height).apply {
addRule(ALIGN_PARENT_BOTTOM)
}
if (view.id == null) {
view.id = View.generateViewId()
}
this.addView(view)
}
@ -92,7 +100,10 @@ fun RelativeLayout.addAtTop(
view.layoutParams = RelativeLayout.LayoutParams(width, height).apply {
addRule(ALIGN_PARENT_TOP)
}
if (view.id == null) {
view.id = View.generateViewId()
}
this.addView(view)
}
@ -101,6 +112,28 @@ fun ViewGroup.buildToolbar(): Toolbar {
return inflater.inflate(R.layout.toolbar, null) as Toolbar
}
fun ViewGroup.buildKonfettiView(): View {
val inflater = LayoutInflater.from(context)
return inflater.inflate(R.layout.konfetti, null) as View
}
fun showConfetti(view: View) {
val viewId = R.id.konfettttiView
val linearLayout = view.findViewById<LinearLayout>(R.id.konfettiLayout)
val kv = view.findViewById<KonfettiView>(viewId)
linearLayout.bringToFront()
val party = Party(
speed = 0f,
maxSpeed = 32f,
damping = 0.9f,
spread = 360,
colors = listOf(0xfce18a, 0xff726d, 0xf4306d, 0xb48def, 0x818181, 0x81a48c),
position = Position.Relative(0.5, 0.3),
emitter = Emitter(duration = 300, TimeUnit.MILLISECONDS).max(300)
)
kv.start(party)
}
fun View.showMessage(msg: String) {
try {
val snackbar = Snackbar.make(this, msg, Snackbar.LENGTH_SHORT)

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2013 The Android Open Source Project
~
~ 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
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/konfettiLayout"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:focusable="false"
android:orientation="vertical" >
<nl.dionsegijn.konfetti.xml.KonfettiView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/konfettttiView"/>
</LinearLayout>
Loading…
Cancel
Save