diff --git a/Demo/app/build.gradle b/Demo/app/build.gradle
index 389b864..4961430 100644
--- a/Demo/app/build.gradle
+++ b/Demo/app/build.gradle
@@ -1,6 +1,7 @@
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
+ id 'kotlin-kapt'
}
android {
@@ -32,13 +33,25 @@ android {
kotlinOptions {
jvmTarget = '17'
}
+
+ buildFeatures {
+ viewBinding true
+ dataBinding true
+ }
}
dependencies {
-
+ def lifecycle_version = "2.6.1"
implementation 'androidx.core:core-ktx:1.10.1'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.9.0'
+ implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
+ implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
+ implementation 'androidx.fragment:fragment-ktx:1.5.7'
+ implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
+ implementation "androidx.core:core-splashscreen:1.0.1"
+ implementation "androidx.preference:preference-ktx:1.2.0"
+
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
diff --git a/Demo/app/src/main/AndroidManifest.xml b/Demo/app/src/main/AndroidManifest.xml
index 3495777..9ee8eb5 100644
--- a/Demo/app/src/main/AndroidManifest.xml
+++ b/Demo/app/src/main/AndroidManifest.xml
@@ -3,6 +3,7 @@
xmlns:tools="http://schemas.android.com/tools">
+ android:theme="@style/Theme.App.Starting"
+ tools:targetApi="31">
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/DemoApplication.kt b/Demo/app/src/main/java/com/krunal/demo/DemoApplication.kt
new file mode 100644
index 0000000..45e7964
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/DemoApplication.kt
@@ -0,0 +1,22 @@
+package com.krunal.demo
+
+import android.app.Application
+import com.krunal.demo.uicomponents.helpers.PreferenceHelper
+
+class DemoApplication: Application() {
+
+ override fun onCreate() {
+ super.onCreate()
+
+ instance = this
+
+ /**
+ * Initialize [PreferenceHelper]
+ */
+ PreferenceHelper.initialize(applicationContext)
+ }
+
+ companion object {
+ lateinit var instance: Application
+ }
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/UIComponentsActivity.kt b/Demo/app/src/main/java/com/krunal/demo/UIComponentsActivity.kt
new file mode 100644
index 0000000..d03fa42
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/UIComponentsActivity.kt
@@ -0,0 +1,31 @@
+package com.krunal.demo
+
+import android.os.Bundle
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
+import com.krunal.demo.uicomponents.ButtonFragment
+import com.krunal.demo.uicomponents.CoordinatorLayoutFragment
+import com.krunal.demo.uicomponents.ThemeFragment
+import com.krunal.demo.uicomponents.cardscreen.CardFragment
+import com.krunal.demo.uicomponents.helpers.ThemeHelper
+
+class UIComponentsActivity : AppCompatActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ installSplashScreen()
+ setupTheme()
+ setContentView(R.layout.activity_uicomponents)
+ setupFragment()
+ }
+
+ private fun setupTheme() {
+ setTheme(ThemeHelper.getThemeResource(ThemeHelper.getThemeAccent()))
+ }
+
+ private fun setupFragment() {
+ supportFragmentManager.beginTransaction()
+ .replace(R.id.uiComponentsFragment, CoordinatorLayoutFragment())
+ .commit()
+ }
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/AppBarFragment.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/AppBarFragment.kt
new file mode 100644
index 0000000..c7fe0e0
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/AppBarFragment.kt
@@ -0,0 +1,36 @@
+package com.krunal.demo.uicomponents
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.appcompat.widget.SearchView
+import androidx.fragment.app.Fragment
+import com.google.android.material.color.MaterialColors
+import com.krunal.demo.R
+import com.krunal.demo.databinding.FragmentAppBarBinding
+import com.krunal.demo.uicomponents.extentions.getThemeColor
+
+class AppBarFragment : Fragment(R.layout.fragment_app_bar) {
+
+ private lateinit var binding: FragmentAppBarBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
+ ): View {
+ binding = FragmentAppBarBinding.inflate(layoutInflater)
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ setupAppBars()
+ }
+
+ private fun setupAppBars() {
+ binding.tbItems.inflateMenu(R.menu.toolbar_menu)
+ val searchItem = binding.tbSearch.menu.findItem(R.id.miSearch)
+ val searchView = searchItem.actionView as SearchView
+ searchView.isIconified = false
+ }
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/ButtonFragment.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/ButtonFragment.kt
new file mode 100644
index 0000000..9d3dd7f
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/ButtonFragment.kt
@@ -0,0 +1,57 @@
+package com.krunal.demo.uicomponents
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.View.OnClickListener
+import android.view.ViewGroup
+import android.widget.Toast
+import androidx.core.view.children
+import androidx.fragment.app.Fragment
+import com.google.android.material.button.MaterialButton
+import com.krunal.demo.R
+import com.krunal.demo.databinding.FragmentButtonBinding
+
+class ButtonFragment : Fragment(R.layout.fragment_button), OnClickListener {
+
+ private lateinit var binding: FragmentButtonBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
+ ): View {
+ binding = FragmentButtonBinding.inflate(layoutInflater)
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ setupClickListener()
+ }
+
+ override fun onClick(view: View?) {
+ (view as? MaterialButton)?.let {
+ Toast.makeText(requireContext(), "${it.text} clicked", Toast.LENGTH_SHORT).show()
+ }
+ }
+
+ private fun setupClickListener() {
+
+ binding.btnNormal.setOnClickListener(this)
+ binding.btnBordered.setOnClickListener(this)
+ binding.appCompatButton.setOnClickListener(this)
+ binding.btnDisabled.setOnClickListener(this)
+ binding.btnOutlined.setOnClickListener(this)
+ binding.btnText.setOnClickListener(this)
+ binding.imgBtnImage.setOnClickListener(this)
+ binding.btnInfo.setOnClickListener(this)
+ binding.btnGradient.setOnClickListener(this)
+
+ binding.switchEnable.setOnCheckedChangeListener { btn, checked ->
+ binding.root.children
+ .filterNot { it == binding.switchEnable }
+ .forEach { it.isEnabled = checked }
+ btn.text =
+ if (checked) getString(R.string.enabled_switch) else getString(R.string.disabled_switch)
+ }
+ }
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/CheckboxFragment.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/CheckboxFragment.kt
new file mode 100644
index 0000000..329c6dd
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/CheckboxFragment.kt
@@ -0,0 +1,58 @@
+package com.krunal.demo.uicomponents
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.CompoundButton
+import android.widget.CompoundButton.OnCheckedChangeListener
+import android.widget.Toast
+import androidx.fragment.app.Fragment
+import com.krunal.demo.R
+import com.krunal.demo.databinding.FragmentCheckboxBinding
+
+class CheckboxFragment : Fragment(R.layout.fragment_checkbox), OnCheckedChangeListener {
+
+ private lateinit var binding: FragmentCheckboxBinding
+ private var selectedLanguages = mutableListOf()
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
+ ): View {
+ binding = FragmentCheckboxBinding.inflate(layoutInflater)
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ setupListeners()
+ }
+
+ private fun setupListeners() {
+ selectedLanguages.add("English")
+ selectedLanguages.add("Hindi")
+ binding.cbEnglish.setOnCheckedChangeListener(this)
+ binding.cbHindi.setOnCheckedChangeListener(this)
+ binding.cbGujarati.setOnCheckedChangeListener(this)
+ binding.cbSpanish.setOnCheckedChangeListener(this)
+ binding.btnSaveChanges.setOnClickListener {
+ Toast.makeText(requireContext(), selectedLanguages.joinToString(), Toast.LENGTH_SHORT)
+ .show()
+ }
+ }
+
+ override fun onCheckedChanged(btn: CompoundButton?, isChecked: Boolean) {
+ val language = when (btn) {
+ binding.cbEnglish -> "English"
+ binding.cbHindi -> "Hindi"
+ binding.cbGujarati -> "Gujarati"
+ binding.cbSpanish -> "Spanish"
+ else -> ""
+ }
+ if (isChecked) {
+ selectedLanguages.add(language)
+ } else {
+ selectedLanguages.remove(language)
+ }
+ }
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/ChipFragment.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/ChipFragment.kt
new file mode 100644
index 0000000..e1986a4
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/ChipFragment.kt
@@ -0,0 +1,55 @@
+package com.krunal.demo.uicomponents
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.core.widget.addTextChangedListener
+import androidx.fragment.app.Fragment
+import com.google.android.material.chip.Chip
+import com.krunal.demo.R
+import com.krunal.demo.databinding.FragmentChipBinding
+
+class ChipFragment : Fragment(R.layout.fragment_chip) {
+
+ private lateinit var binding: FragmentChipBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ binding = FragmentChipBinding.inflate(layoutInflater)
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ setupChips()
+ }
+
+ private fun setupChips() {
+ binding.etChip.addTextChangedListener {
+ binding.tilChip.isEndIconVisible = binding.etChip.text.isNullOrEmpty().not()
+ }
+
+ binding.etChip.setOnEditorActionListener { _, _, _ ->
+ addChip()
+ true
+ }
+
+ binding.tilChip.setEndIconOnClickListener {
+ addChip()
+ }
+ }
+
+ private fun addChip() {
+ val chip = Chip(requireContext())
+ chip.text = binding.etChip.text
+ chip.setOnCloseIconClickListener { binding.cgProgrammatically.removeView(it) }
+ chip.setCloseIconResource(R.drawable.ic_cross)
+ chip.isCloseIconVisible = true
+ binding.cgProgrammatically.addView(chip)
+ binding.etChip.text?.clear()
+ }
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/CoordinatorLayoutFragment.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/CoordinatorLayoutFragment.kt
new file mode 100644
index 0000000..246e9ba
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/CoordinatorLayoutFragment.kt
@@ -0,0 +1,45 @@
+package com.krunal.demo.uicomponents
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Button
+import androidx.fragment.app.Fragment
+import com.google.android.material.behavior.SwipeDismissBehavior
+import com.google.android.material.snackbar.BaseTransientBottomBar
+import com.google.android.material.snackbar.Snackbar
+import com.krunal.demo.databinding.FragmentCoordinatorLayoutBinding
+
+class CoordinatorLayoutFragment : Fragment() {
+
+ private lateinit var binding: FragmentCoordinatorLayoutBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
+ ): View {
+ binding = FragmentCoordinatorLayoutBinding.inflate(layoutInflater)
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ setupUI()
+ }
+
+ private fun setupUI() {
+ setupSnackBar()
+ }
+
+ private fun setupSnackBar() {
+ binding.btnSwipeableSnackBar.setOnClickListener {
+ Snackbar.make(requireView(), (it as Button).text, Snackbar.LENGTH_LONG).apply {
+ behavior = BaseTransientBottomBar.Behavior()
+ animationMode = BaseTransientBottomBar.ANIMATION_MODE_SLIDE
+ behavior.setSwipeDirection(SwipeDismissBehavior.SWIPE_DIRECTION_ANY)
+ show()
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/CustomViewFragment.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/CustomViewFragment.kt
new file mode 100644
index 0000000..04fd5cf
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/CustomViewFragment.kt
@@ -0,0 +1,6 @@
+package com.krunal.demo.uicomponents
+
+import androidx.fragment.app.Fragment
+import com.krunal.demo.R
+
+class CustomViewFragment : Fragment(R.layout.fragment_custom_view)
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/EditTextFragment.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/EditTextFragment.kt
new file mode 100644
index 0000000..a2eca4f
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/EditTextFragment.kt
@@ -0,0 +1,67 @@
+package com.krunal.demo.uicomponents
+
+import android.os.Bundle
+import android.util.Patterns
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.EditText
+import androidx.core.view.children
+import androidx.core.widget.addTextChangedListener
+import androidx.fragment.app.Fragment
+import com.google.android.material.textfield.TextInputLayout
+import com.krunal.demo.R
+import com.krunal.demo.databinding.FragmentEditTextBinding
+import com.krunal.demo.uicomponents.extentions.hideKeyboard
+
+
+class EditTextFragment : Fragment(R.layout.fragment_edit_text) {
+
+ private lateinit var binding: FragmentEditTextBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
+ ): View {
+ binding = FragmentEditTextBinding.inflate(layoutInflater)
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ setupListeners()
+ }
+
+ private fun setupListeners() {
+ binding.root.setOnFocusChangeListener { view, isFocused ->
+ if (isFocused) view.hideKeyboard()
+ }
+
+ binding.etEmail.setOnFocusChangeListener { emailView, isFocused ->
+ val email = binding.etEmail.text.toString()
+ binding.emailContainer.error = if (!isFocused && !isValidEmail(email)) {
+ "Invalid email address"
+ } else {
+ null
+ }
+ }
+
+ binding.etEmail.addTextChangedListener {
+ if (it?.length == 0) binding.emailContainer.error = null
+ }
+
+ binding.btnClear.setOnClickListener {
+ binding.root.children.forEach {
+ if (it is EditText) {
+ it.text.clear()
+ } else if (it is TextInputLayout) {
+ it.editText?.text?.clear()
+ }
+ }
+ }
+ }
+
+ private fun isValidEmail(email: String): Boolean {
+ val pattern = Patterns.EMAIL_ADDRESS
+ return pattern.matcher(email).matches()
+ }
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/FabFragment.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/FabFragment.kt
new file mode 100644
index 0000000..e935178
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/FabFragment.kt
@@ -0,0 +1,69 @@
+package com.krunal.demo.uicomponents
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import com.google.android.material.snackbar.Snackbar
+import com.krunal.demo.R
+import com.krunal.demo.databinding.FragmentFabBinding
+
+class FabFragment : Fragment(R.layout.fragment_fab) {
+
+ private lateinit var binding: FragmentFabBinding
+ private var visible: Boolean = false
+ private lateinit var snackBar: Snackbar
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
+ ): View {
+ binding = FragmentFabBinding.inflate(layoutInflater)
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ binding.fabAdd.setOnClickListener {
+ changeVisibility()
+ if (visible) snackBar.show()
+ }
+ setupExpandableFab()
+ setupSnackBar()
+ }
+
+ private fun changeVisibility() {
+ visible = visible.not()
+ binding.fabAdd.setImageResource(
+ if (visible) R.drawable.ic_cross
+ else R.drawable.ic_add
+ )
+ binding.fabEdit.visibility = if (visible) View.VISIBLE else View.INVISIBLE
+ binding.fabImage.visibility = if (visible) View.VISIBLE else View.INVISIBLE
+ }
+
+ private fun setupExpandableFab() {
+ binding.fabExtended1.isChecked = true
+ binding.fabExtended2.isChecked = true
+
+ binding.fabExtended1.addOnCheckedChangeListener { _, isChecked ->
+ binding.fabExtended1.isExtended = isChecked
+ }
+
+ binding.fabExtended2.addOnCheckedChangeListener { _, isChecked ->
+ binding.fabExtended2.isExtended = isChecked
+ }
+
+ binding.fabExtended3.setOnClickListener {
+ binding.fabExtended3.isExtended = binding.fabExtended3.isExtended.not()
+ }
+ }
+
+ private fun setupSnackBar() {
+ snackBar = Snackbar.make(binding.root, "Fab button opened", Snackbar.LENGTH_SHORT)
+ snackBar.anchorView = binding.fabImage
+ snackBar.setAction("Close") {
+ changeVisibility()
+ }
+ }
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/FrameLayoutFragment.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/FrameLayoutFragment.kt
new file mode 100644
index 0000000..c833914
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/FrameLayoutFragment.kt
@@ -0,0 +1,8 @@
+package com.krunal.demo.uicomponents
+
+import androidx.fragment.app.Fragment
+import com.krunal.demo.R
+
+class FrameLayoutFragment : Fragment(R.layout.fragment_frame_layout) {
+
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/LinearLayoutFragment.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/LinearLayoutFragment.kt
new file mode 100644
index 0000000..00d1a6b
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/LinearLayoutFragment.kt
@@ -0,0 +1,8 @@
+package com.krunal.demo.uicomponents
+
+import androidx.fragment.app.Fragment
+import com.krunal.demo.R
+
+class LinearLayoutFragment : Fragment(R.layout.fragment_linear_layout) {
+
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/ProgressBarFragment.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/ProgressBarFragment.kt
new file mode 100644
index 0000000..3c6a3cd
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/ProgressBarFragment.kt
@@ -0,0 +1,41 @@
+package com.krunal.demo.uicomponents
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import com.krunal.demo.databinding.FragmentProgressBarBinding
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+
+class ProgressBarFragment : Fragment() {
+
+ private lateinit var binding: FragmentProgressBarBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
+ ): View {
+ binding = FragmentProgressBarBinding.inflate(layoutInflater)
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ setupProgress()
+ }
+
+ private fun setupProgress() {
+ CoroutineScope(Dispatchers.Main).launch {
+ repeat(10) {
+ delay(1000)
+ binding.pbCircularDeterminate.incrementProgressBy(5)
+ binding.pbCircularIndeterminate1.incrementProgressBy(5)
+ binding.pbCircularIndeterminate2.incrementProgressBy(5)
+ binding.pbHorizontalDeterminate.incrementProgressBy(-5)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/RadioFragment.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/RadioFragment.kt
new file mode 100644
index 0000000..2b1e07c
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/RadioFragment.kt
@@ -0,0 +1,52 @@
+package com.krunal.demo.uicomponents
+
+import android.os.Bundle
+import android.view.Gravity
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Toast
+import androidx.fragment.app.Fragment
+import com.google.android.material.radiobutton.MaterialRadioButton
+import com.krunal.demo.R
+import com.krunal.demo.databinding.FragmentRadioBinding
+
+class RadioFragment : Fragment(R.layout.fragment_radio) {
+
+ private lateinit var binding: FragmentRadioBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
+ ): View {
+ binding = FragmentRadioBinding.inflate(layoutInflater)
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ showSelected()
+ }
+
+ private fun showSelected() {
+ val toast = Toast(requireContext())
+ toast.duration = Toast.LENGTH_SHORT
+ toast.setGravity(Gravity.CENTER_HORIZONTAL, 0, 0)
+
+ binding.rgGender.setOnCheckedChangeListener { _, id ->
+ toast.setText(
+ when (id) {
+ binding.radioMale.id -> "Male"
+ binding.radioFemale.id -> "Female"
+ else -> "Other"
+ }
+ )
+ toast.show()
+ }
+ binding.rgHouse.setOnCheckedChangeListener { _, id ->
+ toast.setText(
+ binding.root.findViewById(id).text
+ )
+ toast.show()
+ }
+ }
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/RelativeLayoutFragment.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/RelativeLayoutFragment.kt
new file mode 100644
index 0000000..871b5cf
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/RelativeLayoutFragment.kt
@@ -0,0 +1,8 @@
+package com.krunal.demo.uicomponents
+
+import androidx.fragment.app.Fragment
+import com.krunal.demo.R
+
+class RelativeLayoutFragment : Fragment(R.layout.fragment_relative_layout) {
+
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/SliderFragment.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/SliderFragment.kt
new file mode 100644
index 0000000..e79bbf7
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/SliderFragment.kt
@@ -0,0 +1,50 @@
+package com.krunal.demo.uicomponents
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import com.krunal.demo.R
+import com.krunal.demo.databinding.FragmentSliderBinding
+
+class SliderFragment : Fragment(R.layout.fragment_slider) {
+
+ private lateinit var binding: FragmentSliderBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
+ ): View {
+ binding = FragmentSliderBinding.inflate(layoutInflater)
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ setupBars()
+ }
+
+ private fun setupBars() {
+ binding.sliderNormal.addOnChangeListener { _, value, _ ->
+ binding.tvSliderNormal.text = getString(R.string.slider_value, value)
+ }
+
+ binding.sliderDiscrete.addOnChangeListener { _, value, _ ->
+ binding.tvSliderDiscrete.text = getString(R.string.slider_value, value)
+ }
+
+ binding.sliderRange.addOnChangeListener { _, _, _ ->
+ val values = binding.sliderRange.values
+ binding.tvSliderRange.text = getString(
+ R.string.slider_range_value, values[0], values[1]
+ )
+ }
+
+ binding.sliderRangeDiscrete.addOnChangeListener { _, _, _ ->
+ val values = binding.sliderRangeDiscrete.values
+ binding.tvSliderRangeDiscrete.text = getString(
+ R.string.slider_range_value, values[0], values[1]
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/SnackBarFragment.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/SnackBarFragment.kt
new file mode 100644
index 0000000..269a034
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/SnackBarFragment.kt
@@ -0,0 +1,69 @@
+package com.krunal.demo.uicomponents
+
+import android.graphics.Color
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Button
+import androidx.fragment.app.Fragment
+import com.google.android.material.behavior.SwipeDismissBehavior
+import com.google.android.material.snackbar.BaseTransientBottomBar.ANIMATION_MODE_SLIDE
+import com.google.android.material.snackbar.BaseTransientBottomBar.Behavior
+import com.google.android.material.snackbar.Snackbar
+import com.krunal.demo.R
+import com.krunal.demo.databinding.FragmentSnackbarBinding
+
+class SnackBarFragment : Fragment(R.layout.fragment_snackbar) {
+
+ private lateinit var binding: FragmentSnackbarBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
+ ): View {
+ binding = FragmentSnackbarBinding.inflate(layoutInflater)
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ setupSnackBars()
+ }
+
+ private fun setupSnackBars() {
+ binding.btnShortSnackBar.setOnClickListener {
+ Snackbar.make(requireView(), (it as Button).text, Snackbar.LENGTH_SHORT).show()
+ }
+
+ binding.btnLongSnackBar.setOnClickListener {
+ Snackbar.make(requireView(), (it as Button).text, Snackbar.LENGTH_LONG).show()
+ }
+
+ binding.btnMultiLineSnackBar.setOnClickListener {
+ Snackbar.make(requireView(), (it as Button).text, Snackbar.LENGTH_SHORT).show()
+ }
+
+ binding.btnActionSnackBar.setOnClickListener {
+ val snackBar = Snackbar.make(requireView(), (it as Button).text, Snackbar.LENGTH_LONG)
+ .setBackgroundTint(Color.GRAY).setActionTextColor(Color.GREEN)
+ snackBar.setAction("Red") {
+ snackBar.setBackgroundTint(Color.RED)
+ }
+ snackBar.show()
+ }
+
+ binding.btnAnchorSnackBar.setOnClickListener {
+ Snackbar.make(requireView(), (it as Button).text, Snackbar.LENGTH_LONG)
+ .setAnchorView(binding.btnShortSnackBar).show()
+ }
+
+ binding.btnSwipeableSnackBar.setOnClickListener {
+ Snackbar.make(requireView(), (it as Button).text, Snackbar.LENGTH_LONG).apply {
+ behavior = Behavior()
+ animationMode = ANIMATION_MODE_SLIDE
+ behavior.setSwipeDirection(SwipeDismissBehavior.SWIPE_DIRECTION_ANY)
+ show()
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/SpanFragment.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/SpanFragment.kt
new file mode 100644
index 0000000..c392e46
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/SpanFragment.kt
@@ -0,0 +1,103 @@
+package com.krunal.demo.uicomponents
+
+import android.graphics.Color
+import android.os.Bundle
+import android.text.Spannable
+import android.text.SpannableStringBuilder
+import android.text.method.LinkMovementMethod
+import android.text.style.ForegroundColorSpan
+import android.text.style.StrikethroughSpan
+import android.text.style.URLSpan
+import android.text.style.UnderlineSpan
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Toast
+import androidx.core.text.bold
+import androidx.core.text.italic
+import androidx.core.text.toSpannable
+import androidx.fragment.app.Fragment
+import com.krunal.demo.R
+import com.krunal.demo.databinding.FragmentSpanBinding
+import com.krunal.demo.uicomponents.extentions.addTextView
+import com.krunal.demo.uicomponents.views.MyClickableSpan
+
+class SpanFragment : Fragment() {
+
+ private lateinit var binding: FragmentSpanBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
+ ): View {
+ binding = FragmentSpanBinding.inflate(layoutInflater)
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ setupSpans()
+ }
+
+ private fun setupSpans() {
+ // Normal foreground color span
+ val textNormal = binding.tvColorSpan.text
+ val spanNormal = textNormal.toSpannable().apply {
+ setSpan(
+ ForegroundColorSpan(Color.RED), 8, 11, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
+ )
+ setSpan(
+ ForegroundColorSpan(Color.GREEN), 16, 21, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
+ )
+ }
+ binding.tvColorSpan.text = spanNormal
+
+ // Underlined and LineThrough
+ val textUnderlineLineThrough = binding.tvUnderlineLineThroughSpan.text
+ val spanUnderlineLineThrough = textUnderlineLineThrough.toSpannable().apply {
+ setSpan(
+ UnderlineSpan(), 8, 18, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
+ )
+ setSpan(
+ StrikethroughSpan(), 23, 34, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
+ )
+ }
+ binding.tvUnderlineLineThroughSpan.text = spanUnderlineLineThrough
+
+ // Clickable Link
+ val spanLink = SpannableStringBuilder("This is my ").bold {
+ italic {
+ append(
+ "Portfolio",
+ URLSpan("https://krunalpatel.me"),
+ Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
+ )
+ }
+ }.append(" or you can visit my ").bold {
+ italic {
+ append(
+ "Blog",
+ URLSpan("https://blog.krunalpatel.me"),
+ Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
+ )
+ }
+ }
+ binding.tvLink.text = spanLink
+ binding.tvLink.movementMethod = LinkMovementMethod.getInstance()
+
+ // Clickable span
+ val clickableText = "You can click on any word"
+
+ SpannableStringBuilder().also { spanBuilder ->
+ clickableText.split(" ").forEach { word ->
+ spanBuilder.append("$word ", MyClickableSpan {
+ Toast.makeText(
+ requireContext(),
+ getString(R.string.click_toast_text, word),
+ Toast.LENGTH_SHORT
+ ).show()
+ }, Spannable.SPAN_INCLUSIVE_EXCLUSIVE)
+ }
+ binding.root.addTextView(spanBuilder)
+ }
+ }
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/SpinnerFragment.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/SpinnerFragment.kt
new file mode 100644
index 0000000..3f4b669
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/SpinnerFragment.kt
@@ -0,0 +1,64 @@
+package com.krunal.demo.uicomponents
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.AdapterView
+import android.widget.ArrayAdapter
+import android.widget.Toast
+import androidx.fragment.app.Fragment
+import com.krunal.demo.R
+import com.krunal.demo.databinding.FragmentSpinnerBinding
+import com.krunal.demo.uicomponents.adapters.TimezoneAdapter
+
+class SpinnerFragment : Fragment(), AdapterView.OnItemSelectedListener {
+
+ private lateinit var binding: FragmentSpinnerBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
+ ): View {
+ binding = FragmentSpinnerBinding.inflate(layoutInflater)
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ setupSpinners()
+ }
+
+ private fun setupSpinners() {
+ ArrayAdapter.createFromResource(
+ requireContext(), R.array.timezones, android.R.layout.simple_spinner_item
+ ).also { adapter ->
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
+ binding.spinnerNormal.adapter = adapter
+ binding.spinnerDialog.adapter = adapter
+ binding.spinnerUnderlined.adapter = adapter
+ binding.spinnerBordered.adapter = adapter
+ binding.autoCompleteTimezone.setAdapter(adapter)
+ binding.spinnerDisabled.adapter = adapter
+ }
+
+ binding.spinnerBordered.setSelection(4, true)
+ binding.spinnerNormal.onItemSelectedListener = this
+ binding.spinnerDisabled.isEnabled = false
+
+ val adapter = TimezoneAdapter(requireContext(), resources.getStringArray(R.array.timezones))
+ binding.spinnerCustom.adapter = adapter
+ }
+
+ override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
+ Toast.makeText(
+ requireContext(),
+ binding.spinnerNormal.selectedItem.toString(),
+ Toast.LENGTH_SHORT
+ ).show()
+ }
+
+ override fun onNothingSelected(parent: AdapterView<*>?) {
+ Toast.makeText(requireContext(), getString(R.string.nothing_selected), Toast.LENGTH_SHORT)
+ .show()
+ }
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/TabLayoutFragment.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/TabLayoutFragment.kt
new file mode 100644
index 0000000..838a944
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/TabLayoutFragment.kt
@@ -0,0 +1,41 @@
+package com.krunal.demo.uicomponents
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import com.google.android.material.tabs.TabLayout
+import com.google.android.material.tabs.TabLayoutMediator
+import com.krunal.demo.R
+import com.krunal.demo.databinding.FragmentTabLayoutBinding
+import com.krunal.demo.uicomponents.adapters.ViewPagerAdapter
+
+class TabLayoutFragment : Fragment(R.layout.fragment_tab_layout) {
+
+ private lateinit var binding: FragmentTabLayoutBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
+ ): View {
+ binding = FragmentTabLayoutBinding.inflate(layoutInflater)
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ setupTabsWithPager()
+ }
+
+ private fun setupTabsWithPager() {
+ val viewPagerAdapter = ViewPagerAdapter(requireActivity())
+ binding.viewPager.adapter = viewPagerAdapter
+ TabLayoutMediator(binding.tabLayout, binding.viewPager) { tab, position ->
+ tab.text = when (position) {
+ 0 -> "Home"
+ 1 -> "Chat"
+ else -> "Call"
+ }
+ }.attach()
+ }
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/ThemeFragment.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/ThemeFragment.kt
new file mode 100644
index 0000000..7fc27ed
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/ThemeFragment.kt
@@ -0,0 +1,57 @@
+package com.krunal.demo.uicomponents
+
+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.lifecycleScope
+import com.krunal.demo.databinding.FragmentThemeBinding
+import com.krunal.demo.uicomponents.adapters.ThemeAdapter
+import com.krunal.demo.uicomponents.extentions.isDarkMode
+import com.krunal.demo.uicomponents.helpers.ThemeHelper
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+
+class ThemeFragment : Fragment() {
+
+ private lateinit var binding: FragmentThemeBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
+ ): View {
+ binding = FragmentThemeBinding.inflate(layoutInflater)
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ setupTheme()
+ }
+
+ private fun setupTheme() {
+ val themes = ThemeHelper.getThemes(requireContext(), requireActivity().isDarkMode)
+ val themeAdapter = ThemeAdapter(
+ requireContext(), themes
+ )
+
+ binding.gvTheme.adapter = themeAdapter
+ binding.gvTheme.setItemChecked(ThemeHelper.getThemeAccent().ordinal, true)
+ lifecycleScope.launch {
+ delay(100)
+
+ binding.gvTheme.setItemChecked(ThemeHelper.getThemeAccent().ordinal, true)
+ binding.gvTheme.setSelection(ThemeHelper.getThemeAccent().ordinal)
+ Log.d("Tag", ThemeHelper.getThemeAccent().ordinal.toString())
+ Log.d("Tag", binding.gvTheme.selectedItemPosition.toString())
+ }
+ // binding.gvTheme.selectedView.performClick() // selectedView is null
+
+ binding.gvTheme.setOnItemClickListener { _, _, position, _ ->
+ ThemeHelper.setThemeAccent(themes[position].accentColor)
+ // TODO: Restart activity
+// activity?.recreate()
+ }
+ }
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/ToastFragment.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/ToastFragment.kt
new file mode 100644
index 0000000..b6822f5
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/ToastFragment.kt
@@ -0,0 +1,74 @@
+package com.krunal.demo.uicomponents
+
+import android.graphics.Color
+import android.os.Bundle
+import android.view.Gravity
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.TextView
+import android.widget.Toast
+import androidx.core.content.res.ResourcesCompat
+import androidx.fragment.app.Fragment
+import com.krunal.demo.R
+import com.krunal.demo.databinding.FragmentToastBinding
+
+class ToastFragment : Fragment(R.layout.fragment_toast) {
+ private lateinit var binding: FragmentToastBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ binding = FragmentToastBinding.inflate(layoutInflater)
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ setupButtons()
+ }
+
+ // Set click listeners for buttons to show toast
+ private fun setupButtons() {
+ // Short toast
+ binding.btnShortToast.setOnClickListener {
+ Toast.makeText(requireContext(), "This is short Toast", Toast.LENGTH_SHORT).show()
+ }
+
+ // Long toast
+ binding.btnLongToast.setOnClickListener {
+ Toast.makeText(requireContext(), "This is long Toast", Toast.LENGTH_LONG).show()
+ }
+
+ // Custom short success toast
+ binding.btnSuccessToast.setOnClickListener {
+ showToast(R.drawable.ic_check, "Custom success toast", backgroundColor = Color.GREEN)
+ }
+
+ // Custom long error toast
+ binding.btnErrorToast.setOnClickListener {
+ showToast(R.drawable.ic_cross, "Custom error toast", Toast.LENGTH_LONG, Color.RED)
+ }
+ }
+
+ // Make and show custom toast
+ private fun showToast(iconId: Int, text: String, length: Int = Toast.LENGTH_SHORT, backgroundColor: Int = Color.GRAY) {
+ val toastView = layoutInflater.inflate(R.layout.custom_toast, requireActivity().findViewById(R.id.customToast))
+ val imgViewStatus = toastView.findViewById(R.id.imgViewStatus)
+ val tvMessage = toastView.findViewById(R.id.tvMessage)
+
+ toastView.setBackgroundColor(backgroundColor)
+ imgViewStatus.setImageResource(iconId)
+ tvMessage.text = text
+
+ Toast(requireContext()).apply {
+ setGravity(Gravity.CENTER, 0, 0)
+ duration = length
+ view = toastView
+ show()
+ }
+ }
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/adapters/ThemeAdapter.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/adapters/ThemeAdapter.kt
new file mode 100644
index 0000000..81716d3
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/adapters/ThemeAdapter.kt
@@ -0,0 +1,33 @@
+package com.krunal.demo.uicomponents.adapters
+
+import android.content.Context
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.BaseAdapter
+import android.widget.TextView
+import com.google.android.material.card.MaterialCardView
+import com.krunal.demo.R
+import com.krunal.demo.uicomponents.models.Theme
+
+class ThemeAdapter(
+ private val context: Context,
+ private val themes: List
+) : BaseAdapter() {
+ override fun getCount(): Int = themes.size
+
+ override fun getItem(position: Int): Any? = null
+
+ override fun getItemId(position: Int): Long = 0
+
+ override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
+ val inflater = LayoutInflater.from(context)
+ val view = inflater.inflate(R.layout.theme_layout, null)
+ val tvName = view.findViewById(R.id.tvThemeName)
+ val viewTheme = view.findViewById(R.id.cardThemeColor)
+
+ tvName.text = themes[position].name
+ viewTheme.setCardBackgroundColor(themes[position].color)
+ return view
+ }
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/adapters/TimezoneAdapter.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/adapters/TimezoneAdapter.kt
new file mode 100644
index 0000000..4f445da
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/adapters/TimezoneAdapter.kt
@@ -0,0 +1,29 @@
+package com.krunal.demo.uicomponents.adapters
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.BaseAdapter
+import android.widget.TextView
+import com.krunal.demo.R
+
+class TimezoneAdapter(private val context: Context, private val timezones: Array): BaseAdapter() {
+
+ override fun getCount() = timezones.size
+
+ override fun getItem(position: Int) = null
+
+ override fun getItemId(position: Int): Long = 0
+
+ @SuppressLint("ViewHolder")
+ override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
+ val inflater = LayoutInflater.from(context)
+ val view = inflater.inflate(R.layout.timezone_spinner, null)
+ val tvName = view.findViewById(R.id.tvTimezone)
+ tvName.text = timezones[position]
+
+ return view
+ }
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/adapters/ViewBindingAdapter.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/adapters/ViewBindingAdapter.kt
new file mode 100644
index 0000000..548048c
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/adapters/ViewBindingAdapter.kt
@@ -0,0 +1,61 @@
+package com.krunal.demo.uicomponents.adapters
+
+import android.graphics.Color
+import android.graphics.drawable.GradientDrawable
+import android.view.View
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.annotation.ColorRes
+import androidx.annotation.DrawableRes
+import androidx.appcompat.content.res.AppCompatResources
+import androidx.core.graphics.ColorUtils
+import androidx.databinding.BindingAdapter
+
+@BindingAdapter("drawableResource")
+fun ImageView.setDrawableResource(@DrawableRes drawableResource: Int) {
+ setImageResource(drawableResource)
+}
+
+@BindingAdapter("drawableResource")
+fun TextView.setStartDrawableResource(@DrawableRes drawableResource: Int) {
+ setCompoundDrawablesRelativeWithIntrinsicBounds(
+ AppCompatResources.getDrawable(context, drawableResource), null, null, null
+ )
+}
+
+@BindingAdapter("drawableColorResource")
+fun TextView.setStartColorResource(@ColorRes colorResource: Int) {
+ compoundDrawablesRelative.filterNotNull().forEach { drawable ->
+ drawable.mutate().setTint(resources.getColor(colorResource, context.theme))
+ }
+}
+
+@BindingAdapter("textColorResource")
+fun TextView.setTextColorResource(@ColorRes colorResource: Int) {
+ setTextColor(resources.getColor(colorResource, context.theme))
+}
+
+@BindingAdapter("textColor")
+fun TextView.setTextColor(color: Int) {
+ setTextColor(color)
+}
+
+@BindingAdapter("backgroundColor")
+fun View.setViewBackgroundColor(color: Int) {
+ setBackgroundColor(color)
+}
+
+@BindingAdapter("gradientStartColor", "gradientEndColor", "angle", requireAll = false)
+fun View.setGradientBackground(gradientStartColor: Int?, gradientEndColor: Int?, angle: Int?) {
+ gradientStartColor?.let { it ->
+ ColorUtils.setAlphaComponent(it, 0x4f).let { color ->
+ GradientDrawable(
+ GradientDrawable.Orientation.TR_BL,
+ intArrayOf(color, gradientEndColor ?: Color.TRANSPARENT)
+ ).also {
+ it.cornerRadius = 0f
+ background = it
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/adapters/ViewPagerAdapter.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/adapters/ViewPagerAdapter.kt
new file mode 100644
index 0000000..b88918c
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/adapters/ViewPagerAdapter.kt
@@ -0,0 +1,16 @@
+package com.krunal.demo.uicomponents.adapters
+
+import androidx.fragment.app.FragmentActivity
+import androidx.viewpager2.adapter.FragmentStateAdapter
+import com.krunal.demo.uicomponents.tablayoutfragments.CallsFragment
+import com.krunal.demo.uicomponents.tablayoutfragments.ChatFragment
+import com.krunal.demo.uicomponents.tablayoutfragments.HomeFragment
+
+class ViewPagerAdapter(fa: FragmentActivity): FragmentStateAdapter(fa) {
+
+ private val fragments = listOf(HomeFragment(), ChatFragment(), CallsFragment())
+
+ override fun getItemCount() = fragments.count()
+
+ override fun createFragment(position: Int) = fragments[position]
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/binding/DataBindingFragment.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/binding/DataBindingFragment.kt
new file mode 100644
index 0000000..c89d361
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/binding/DataBindingFragment.kt
@@ -0,0 +1,26 @@
+package com.krunal.demo.uicomponents.binding
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.viewModels
+import com.krunal.demo.databinding.FragmentDataBindingBinding
+
+class DataBindingFragment : Fragment() {
+
+ private lateinit var binding: FragmentDataBindingBinding
+ private val viewModel: DataBingingViewModel by viewModels()
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ binding = FragmentDataBindingBinding.inflate(inflater)
+ binding.viewModel = viewModel
+ binding.lifecycleOwner = viewLifecycleOwner
+ return binding.root
+ }
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/binding/DataBingingViewModel.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/binding/DataBingingViewModel.kt
new file mode 100644
index 0000000..ced1218
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/binding/DataBingingViewModel.kt
@@ -0,0 +1,34 @@
+package com.krunal.demo.uicomponents.binding
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import com.krunal.demo.uicomponents.models.Name
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.launch
+
+class DataBingingViewModel : ViewModel() {
+
+ private val _nameFlow = MutableStateFlow(null)
+ val nameFlow: StateFlow = _nameFlow
+
+ init {
+ randomName()
+ }
+
+ /** Generate and emmit random names to [nameFlow] */
+ private fun randomName() {
+ // List of random names
+ val names = listOf(
+ Name("Harry", "Potter")
+ )
+
+ viewModelScope.launch {
+ while (true) {
+ delay(3000)
+ _nameFlow.emit(names.first())
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/cardscreen/CardFragment.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/cardscreen/CardFragment.kt
new file mode 100644
index 0000000..f296686
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/cardscreen/CardFragment.kt
@@ -0,0 +1,117 @@
+package com.krunal.demo.uicomponents.cardscreen
+
+import android.graphics.Color
+import android.graphics.drawable.ColorDrawable
+import android.os.Bundle
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.LinearLayout
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.viewModels
+import androidx.lifecycle.lifecycleScope
+import com.google.android.material.chip.Chip
+import com.google.android.material.navigation.NavigationBarView
+import com.krunal.demo.R
+import com.krunal.demo.UIComponentsActivity
+import com.krunal.demo.databinding.CardLayoutBinding
+import com.krunal.demo.databinding.FragmentCardBinding
+import com.krunal.demo.uicomponents.dialogs.MyDatePickerDialog
+import com.krunal.demo.uicomponents.extentions.dpFormat
+import com.krunal.demo.uicomponents.models.CardDetail
+import com.krunal.demo.uicomponents.sheets.OperationsBottomSheetFragment
+import kotlinx.coroutines.launch
+
+class CardFragment : Fragment() {
+
+ private lateinit var binding: FragmentCardBinding
+ private val viewModel: CardFragmentViewModel by viewModels()
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
+ ): View {
+ binding = FragmentCardBinding.inflate(layoutInflater)
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ setupUI()
+ }
+
+ private fun setupUI() {
+ setupBottomBar()
+ (activity as? UIComponentsActivity)?.supportActionBar?.apply {
+ title = getString(R.string.my_cards)
+ setBackgroundDrawable(ColorDrawable(Color.parseColor("#2F7CEF")))
+ elevation = 0f
+ // TODO: Make title center
+ }
+
+ setupCardChips()
+
+ setupCard()
+
+ binding.cardOperations.btnDetails.setOnClickListener {
+ OperationsBottomSheetFragment().show(childFragmentManager, null)
+ }
+
+ binding.cardOperations.btnCalendar.setOnClickListener {
+ MyDatePickerDialog().show(childFragmentManager, null)
+ }
+ }
+
+ private fun setupCardChips() {
+ viewModel.dummyCardDetails.forEach { card ->
+ (layoutInflater.inflate(R.layout.card_chip, null) as? Chip)?.apply {
+ text = getString(R.string.card_name, card.type, card.number)
+ isChecked = card.isSelected
+ setOnCheckedChangeListener { _, isChecked ->
+ viewModel.updateCardSelection(
+ card,
+ isChecked
+ )
+ }
+ }.also { cardChip ->
+ binding.cgCard.addView(cardChip)
+ }
+ }
+ }
+
+ private fun setupCard() {
+ addSelectedCards(viewModel.dummyCardDetails)
+ lifecycleScope.launch {
+ viewModel.selectedCards.collect { cardList ->
+ binding.llCards.removeViews(1, binding.llCards.childCount - 1)
+ addSelectedCards(cardList)
+ }
+ }
+ }
+
+ private fun addSelectedCards(cardList: List) {
+ cardList
+ .filter { it.isSelected }
+ .forEach { card ->
+ val cardBinding = CardLayoutBinding.inflate(layoutInflater)
+ cardBinding.card = card
+
+ val layoutParams = LinearLayout.LayoutParams(
+ 300.dpFormat(requireContext()),
+ 200.dpFormat(requireContext()),
+ ).apply {
+ marginEnd = 18.dpFormat(requireContext())
+ }
+
+ cardBinding.root.layoutParams = layoutParams
+ binding.llCards.addView(cardBinding.root)
+ }
+ }
+
+ private fun setupBottomBar() {
+ binding.bottomNavigation.apply {
+ selectedItemId = menu.getItem(1).itemId
+ labelVisibilityMode = NavigationBarView.LABEL_VISIBILITY_SELECTED
+ }
+ }
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/cardscreen/CardFragmentViewModel.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/cardscreen/CardFragmentViewModel.kt
new file mode 100644
index 0000000..2c76f8e
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/cardscreen/CardFragmentViewModel.kt
@@ -0,0 +1,29 @@
+package com.krunal.demo.uicomponents.cardscreen
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import com.krunal.demo.uicomponents.models.CardDetail
+import com.krunal.demo.uicomponents.models.enums.CardType
+import kotlinx.coroutines.flow.MutableSharedFlow
+import kotlinx.coroutines.flow.SharedFlow
+import kotlinx.coroutines.launch
+
+class CardFragmentViewModel : ViewModel() {
+
+ private val _selectedCards = MutableSharedFlow>()
+ val selectedCards: SharedFlow> = _selectedCards
+
+ var dummyCardDetails: List = buildList {
+ add(CardDetail(CardType.DEBIT, 1963, "$2,983.78", true))
+ add(CardDetail(CardType.DEBIT, 1822, "$1,002.02"))
+ add(CardDetail(CardType.CREDIT, 2291, "$540.00"))
+ }
+
+ fun updateCardSelection(card: CardDetail, isSelected: Boolean) {
+ dummyCardDetails.find { it.number == card.number }?.isSelected =
+ isSelected
+ viewModelScope.launch {
+ _selectedCards.emit(dummyCardDetails)
+ }
+ }
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/constraintLayouts/ChainBiasFragment.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/constraintLayouts/ChainBiasFragment.kt
new file mode 100644
index 0000000..dfb8893
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/constraintLayouts/ChainBiasFragment.kt
@@ -0,0 +1,5 @@
+package com.krunal.demo.uicomponents.constraintLayouts
+
+import androidx.fragment.app.Fragment
+
+class ChainBiasFragment : Fragment()
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/constraintLayouts/CircularFragment.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/constraintLayouts/CircularFragment.kt
new file mode 100644
index 0000000..2f8fbe6
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/constraintLayouts/CircularFragment.kt
@@ -0,0 +1,32 @@
+package com.krunal.demo.uicomponents.constraintLayouts
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import com.krunal.demo.R
+import com.krunal.demo.databinding.FragmentClCircularBinding
+
+class CircularFragment : Fragment(R.layout.fragment_cl_circular) {
+
+ private lateinit var binding: FragmentClCircularBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
+ ): View {
+ binding = FragmentClCircularBinding.inflate(layoutInflater)
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ setupUI()
+ }
+
+ private fun setupUI() {
+ binding.imgBtnMain.setOnCheckedChangeListener { _, isChecked ->
+ binding.groupEmojis.visibility = if (isChecked) View.VISIBLE else View.INVISIBLE
+ }
+ }
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/constraintLayouts/GuidelineBarrierFragment.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/constraintLayouts/GuidelineBarrierFragment.kt
new file mode 100644
index 0000000..64d7c05
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/constraintLayouts/GuidelineBarrierFragment.kt
@@ -0,0 +1,5 @@
+package com.krunal.demo.uicomponents.constraintLayouts
+
+import androidx.fragment.app.Fragment
+
+class GuidelineBarrierFragment : Fragment()
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/constraintLayouts/RelativeFragment.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/constraintLayouts/RelativeFragment.kt
new file mode 100644
index 0000000..18dac3a
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/constraintLayouts/RelativeFragment.kt
@@ -0,0 +1,6 @@
+package com.krunal.demo.uicomponents.constraintLayouts
+
+import androidx.fragment.app.Fragment
+import com.krunal.demo.R
+
+class RelativeFragment : Fragment(R.layout.fragment_cl_relative)
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/dialogs/MyDatePickerDialog.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/dialogs/MyDatePickerDialog.kt
new file mode 100644
index 0000000..369e675
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/dialogs/MyDatePickerDialog.kt
@@ -0,0 +1,21 @@
+package com.krunal.demo.uicomponents.dialogs
+
+import android.app.DatePickerDialog
+import android.app.Dialog
+import android.os.Bundle
+import androidx.fragment.app.DialogFragment
+import java.util.Calendar
+
+class MyDatePickerDialog : DialogFragment() {
+
+ override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+ val mCalendar: Calendar = Calendar.getInstance()
+ val year = mCalendar.get(Calendar.YEAR)
+ val month = mCalendar.get(Calendar.MONTH)
+ val dayOfMonth = mCalendar.get(Calendar.DAY_OF_MONTH)
+
+ return DatePickerDialog(requireActivity(), null, year, month, dayOfMonth).apply {
+ datePicker.maxDate = Calendar.getInstance().timeInMillis
+ }
+ }
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/extentions/ActivityExtentions.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/extentions/ActivityExtentions.kt
new file mode 100644
index 0000000..36b32d9
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/extentions/ActivityExtentions.kt
@@ -0,0 +1,21 @@
+package com.krunal.demo.uicomponents.extentions
+
+import android.app.Activity
+import android.content.Context
+import android.content.res.Configuration
+import android.util.TypedValue
+
+
+fun Context.getThemeColor(resId: Int): Int {
+ val typedValue = TypedValue()
+ theme.resolveAttribute(resId, typedValue, true)
+ return typedValue.data
+}
+
+val Activity.isDarkMode: Boolean
+ get() = when (resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) {
+ Configuration.UI_MODE_NIGHT_YES -> true
+ Configuration.UI_MODE_NIGHT_NO -> false
+ Configuration.UI_MODE_NIGHT_UNDEFINED -> false
+ else -> false
+ }
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/extentions/LinearLayoutExtentions.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/extentions/LinearLayoutExtentions.kt
new file mode 100644
index 0000000..4ee254f
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/extentions/LinearLayoutExtentions.kt
@@ -0,0 +1,29 @@
+package com.krunal.demo.uicomponents.extentions
+
+import android.text.Spanned
+import android.text.method.LinkMovementMethod
+import android.widget.LinearLayout
+import android.widget.TextView
+import androidx.core.text.toSpanned
+
+// Add text to the LinearLayout by creating new TextView
+fun LinearLayout.addTextView(text: String) {
+ addTextView(text.toSpanned())
+}
+
+// Add spanned text to the LinearLayout by creating new TextView
+fun LinearLayout.addTextView(spanText: Spanned) {
+ TextView(context).apply {
+ layoutParams = LinearLayout.LayoutParams(
+ LinearLayout.LayoutParams.MATCH_PARENT,
+ LinearLayout.LayoutParams.WRAP_CONTENT,
+ ).apply {
+ topMargin = 24.dpFormat(context)
+ }
+ text = spanText
+ textSize = 18f
+ movementMethod = LinkMovementMethod.getInstance()
+ }.also { textView ->
+ addView(textView)
+ }
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/extentions/NumberExtentions.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/extentions/NumberExtentions.kt
new file mode 100644
index 0000000..43bc8c3
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/extentions/NumberExtentions.kt
@@ -0,0 +1,10 @@
+package com.krunal.demo.uicomponents.extentions
+
+import android.content.Context
+import android.util.DisplayMetrics
+import kotlin.math.roundToInt
+
+fun Int.dpFormat(context: Context): Int {
+ val displayMetrics = context.resources.displayMetrics
+ return (this * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT)).roundToInt()
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/extentions/TypedArrayExtentions.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/extentions/TypedArrayExtentions.kt
new file mode 100644
index 0000000..9e6af51
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/extentions/TypedArrayExtentions.kt
@@ -0,0 +1,15 @@
+package com.krunal.demo.uicomponents.extentions
+
+import android.content.res.TypedArray
+
+fun TypedArray.toFloat(): List = buildList {
+ for (i in 0 until length()) {
+ add(getFloat(i, -1f))
+ }
+}
+
+fun TypedArray.toInt(): List = buildList {
+ for (i in 0 until length()) {
+ add(getInt(i, -1))
+ }
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/extentions/ViewExtentions.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/extentions/ViewExtentions.kt
new file mode 100644
index 0000000..856ac34
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/extentions/ViewExtentions.kt
@@ -0,0 +1,10 @@
+package com.krunal.demo.uicomponents.extentions
+
+import android.app.Activity
+import android.view.View
+import android.view.inputmethod.InputMethodManager
+
+fun View.hideKeyboard() {
+ val inputMethodManager = context.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
+ inputMethodManager.hideSoftInputFromWindow(windowToken, 0)
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/helpers/PreferenceHelper.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/helpers/PreferenceHelper.kt
new file mode 100644
index 0000000..4c7cca8
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/helpers/PreferenceHelper.kt
@@ -0,0 +1,69 @@
+package com.krunal.demo.uicomponents.helpers
+
+import android.content.Context
+import android.content.SharedPreferences
+import androidx.preference.PreferenceManager
+
+object PreferenceHelper {
+
+ private lateinit var preferences: SharedPreferences
+ private lateinit var editor: SharedPreferences.Editor
+
+ /**
+ * set the context that is being used to access the shared preferences
+ */
+ fun initialize(context: Context) {
+ preferences = getDefaultSharedPreferences(context)
+ editor = preferences.edit()
+ }
+
+ fun putString(key: String, value: String) {
+ editor.putString(key, value).commit()
+ }
+
+ fun putBoolean(key: String, value: Boolean) {
+ editor.putBoolean(key, value).commit()
+ }
+
+ fun putInt(key: String, value: Int) {
+ editor.putInt(key, value).commit()
+ }
+
+ fun putFloat(key: String, value: Float) {
+ editor.putFloat(key, value).commit()
+ }
+
+ fun putLong(key: String, value: Long) {
+ editor.putLong(key, value).commit()
+ }
+
+ fun getString(key: String?, defValue: String): String {
+ return preferences.getString(key, defValue) ?: defValue
+ }
+
+ fun getBoolean(key: String?, defValue: Boolean): Boolean {
+ return preferences.getBoolean(key, defValue)
+ }
+
+ fun getInt(key: String?, defValue: Int): Int {
+ return runCatching {
+ preferences.getInt(key, defValue)
+ }.getOrElse { preferences.getLong(key, defValue.toLong()).toInt() }
+ }
+
+ fun getLong(key: String?, defValue: Long): Long {
+ return preferences.getLong(key, defValue)
+ }
+
+ fun getFloat(key: String?, defValue: Float): Float {
+ return preferences.getFloat(key, defValue)
+ }
+
+ fun clearPreferences() {
+ editor.clear().apply()
+ }
+
+ private fun getDefaultSharedPreferences(context: Context): SharedPreferences {
+ return PreferenceManager.getDefaultSharedPreferences(context)
+ }
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/helpers/ThemeHelper.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/helpers/ThemeHelper.kt
new file mode 100644
index 0000000..2bedaae
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/helpers/ThemeHelper.kt
@@ -0,0 +1,79 @@
+package com.krunal.demo.uicomponents.helpers
+
+import android.content.Context
+import com.krunal.demo.R
+import com.krunal.demo.uicomponents.models.Theme
+import com.krunal.demo.uicomponents.models.enums.AccentColor
+import com.krunal.demo.uicomponents.models.enums.ThemeMode
+import com.krunal.demo.uicomponents.utils.PreferenceKeys
+
+object ThemeHelper {
+ fun getThemes(context: Context, isDark: Boolean = false): List {
+ val accentValues = AccentColor.values()
+ val accent = context.resources.getStringArray(R.array.accents)
+
+ return buildList {
+ for (i in accentValues.indices) {
+ add(
+ Theme(
+ accent[i], accentValues[i], getAccentColor(context, accentValues[i], isDark)
+ )
+ )
+ }
+ }
+ }
+
+ fun getThemeResource(accentColor: AccentColor): Int {
+ return when (accentColor) {
+ AccentColor.RED -> R.style.Theme_Red
+ AccentColor.BLUE -> R.style.Theme_Blue
+ AccentColor.YELLOW -> R.style.Theme_Yellow
+ AccentColor.GREEN -> R.style.Theme_Green
+ AccentColor.PURPLE -> R.style.Theme_Purple
+ AccentColor.VIOLET -> R.style.Theme_Violet
+ }
+ }
+
+ fun getThemeMode(): ThemeMode {
+ return ThemeMode.valueOf(
+ PreferenceHelper.getString(
+ PreferenceKeys.THEME_MODE,
+ ThemeMode.AUTO.name
+ )
+ )
+ }
+
+ fun setThemeMode(mode: ThemeMode) {
+ PreferenceHelper.putString(PreferenceKeys.THEME_MODE, mode.name)
+ }
+
+ fun getThemeAccent(): AccentColor {
+ return AccentColor.valueOf(
+ PreferenceHelper.getString(
+ PreferenceKeys.ACCENT_COLOR,
+ AccentColor.VIOLET.name
+ )
+ )
+ }
+
+ fun setThemeAccent(color: AccentColor) {
+ PreferenceHelper.putString(PreferenceKeys.ACCENT_COLOR, color.name)
+ }
+
+ private fun getAccentColor(
+ context: Context,
+ accentColor: AccentColor,
+ isDarkMode: Boolean
+ ): Int {
+ return context.getColor(
+ when (accentColor) {
+ AccentColor.RED -> if (isDarkMode) R.color.red_md_theme_dark_primary else R.color.red_md_theme_light_primary
+ AccentColor.BLUE -> if (isDarkMode) R.color.blue_md_theme_dark_primary else R.color.blue_md_theme_light_primary
+ AccentColor.YELLOW -> if (isDarkMode) R.color.yellow_md_theme_dark_primary else R.color.yellow_md_theme_light_primary
+ AccentColor.GREEN -> if (isDarkMode) R.color.green_md_theme_dark_primary else R.color.green_md_theme_light_primary
+ AccentColor.PURPLE -> if (isDarkMode) R.color.purple_md_theme_dark_primary else R.color.purple_md_theme_light_primary
+ AccentColor.VIOLET -> if (isDarkMode) R.color.violet_theme_dark_primary else R.color.violet_theme_light_primary
+ }
+ )
+ }
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/models/CardDetail.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/models/CardDetail.kt
new file mode 100644
index 0000000..d910dbf
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/models/CardDetail.kt
@@ -0,0 +1,18 @@
+package com.krunal.demo.uicomponents.models
+
+import com.krunal.demo.uicomponents.models.enums.CardType
+
+data class CardDetail(
+ val type: CardType, val number: Int, val amount: String = "$0"
+) {
+
+ var isSelected: Boolean = false
+
+ constructor(type: CardType, number: Int, amount: String, isSelected: Boolean) : this(
+ type,
+ number,
+ amount
+ ) {
+ this.isSelected = isSelected
+ }
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/models/DrawableResource.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/models/DrawableResource.kt
new file mode 100644
index 0000000..9f3f4fb
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/models/DrawableResource.kt
@@ -0,0 +1,8 @@
+package com.krunal.demo.uicomponents.models
+
+import android.graphics.Bitmap as AndroidBitmap
+
+sealed interface DrawableResource {
+ data class Drawable(val id: Int): DrawableResource
+ data class Bitmap(val bitmap: AndroidBitmap): DrawableResource
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/models/Name.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/models/Name.kt
new file mode 100644
index 0000000..cb56627
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/models/Name.kt
@@ -0,0 +1,3 @@
+package com.krunal.demo.uicomponents.models
+
+data class Name(val firstName: String, val lastName: String)
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/models/Theme.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/models/Theme.kt
new file mode 100644
index 0000000..400d7fa
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/models/Theme.kt
@@ -0,0 +1,11 @@
+package com.krunal.demo.uicomponents.models
+
+import androidx.annotation.ColorRes
+import com.krunal.demo.uicomponents.models.enums.AccentColor
+
+data class Theme(
+ val name: String,
+ val accentColor: AccentColor,
+ val color: Int,
+ val isDarkMode: Boolean = false
+)
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/models/enums/AccentColor.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/models/enums/AccentColor.kt
new file mode 100644
index 0000000..944286c
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/models/enums/AccentColor.kt
@@ -0,0 +1,5 @@
+package com.krunal.demo.uicomponents.models.enums
+
+enum class AccentColor {
+ RED, BLUE, YELLOW, GREEN, PURPLE, VIOLET
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/models/enums/CardType.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/models/enums/CardType.kt
new file mode 100644
index 0000000..d3ac2a3
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/models/enums/CardType.kt
@@ -0,0 +1,11 @@
+package com.krunal.demo.uicomponents.models.enums
+
+import java.util.Locale
+
+enum class CardType {
+ DEBIT, CREDIT;
+
+ override fun toString(): String {
+ return name.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.ROOT) else it.toString() }
+ }
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/models/enums/ThemeMode.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/models/enums/ThemeMode.kt
new file mode 100644
index 0000000..4b7b2f5
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/models/enums/ThemeMode.kt
@@ -0,0 +1,5 @@
+package com.krunal.demo.uicomponents.models.enums
+
+enum class ThemeMode {
+ AUTO, DARK, LIGHT
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/picker/DatePickerFragment.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/picker/DatePickerFragment.kt
new file mode 100644
index 0000000..0c78ada
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/picker/DatePickerFragment.kt
@@ -0,0 +1,31 @@
+package com.krunal.demo.uicomponents.picker
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import com.krunal.demo.databinding.FragmentDatePickerBinding
+import java.util.Date
+
+class DatePickerFragment : Fragment() {
+
+ private lateinit var binding: FragmentDatePickerBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
+ ): View {
+ binding = FragmentDatePickerBinding.inflate(layoutInflater)
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ setupPicker()
+ }
+
+ private fun setupPicker() {
+ binding.dpCalender.maxDate = Date().time
+ binding.dpCalender.updateDate(2023, 1, 1)
+ }
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/picker/TimePickerFragment.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/picker/TimePickerFragment.kt
new file mode 100644
index 0000000..8f99181
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/picker/TimePickerFragment.kt
@@ -0,0 +1,62 @@
+package com.krunal.demo.uicomponents.picker
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TimePicker
+import android.widget.TimePicker.OnTimeChangedListener
+import androidx.fragment.app.Fragment
+import com.krunal.demo.R
+import com.krunal.demo.databinding.FragmentTimePickerBinding
+
+class TimePickerFragment : Fragment(), OnTimeChangedListener {
+
+ private lateinit var binding: FragmentTimePickerBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
+ ): View {
+ binding = FragmentTimePickerBinding.inflate(layoutInflater)
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ setupPicker()
+ }
+
+ private fun setupPicker() {
+ // Set is 24 hour format
+ binding.switch24hour.setOnCheckedChangeListener { _, isChecked ->
+ binding.tpClock.setIs24HourView(isChecked)
+ binding.tpSpinner.setIs24HourView(isChecked)
+ }
+
+ binding.tpClock.setOnTimeChangedListener(this)
+ binding.tpSpinner.setOnTimeChangedListener(this)
+ }
+
+ override fun onTimeChanged(timePicker: TimePicker, hourOfDay: Int, minute: Int) {
+ // Sync both time pickers
+ if (timePicker == binding.tpClock) {
+ binding.tpSpinner.hour = hourOfDay
+ binding.tpSpinner.minute = minute
+ } else {
+ binding.tpClock.hour = hourOfDay
+ binding.tpClock.minute = minute
+ }
+
+ // Update time text view
+ binding.tvTime.text = if (timePicker.is24HourView) {
+ getString(R.string.time, hourOfDay, minute, "")
+ } else {
+ getString(
+ R.string.time,
+ if (hourOfDay % 12 == 0) 12 else hourOfDay,
+ minute,
+ if (hourOfDay < 12) "AM" else "PM"
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/sheets/OperationsBottomSheetFragment.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/sheets/OperationsBottomSheetFragment.kt
new file mode 100644
index 0000000..693b651
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/sheets/OperationsBottomSheetFragment.kt
@@ -0,0 +1,35 @@
+package com.krunal.demo.uicomponents.sheets
+
+import android.annotation.SuppressLint
+import android.app.Dialog
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import com.google.android.material.bottomsheet.BottomSheetBehavior
+import com.google.android.material.bottomsheet.BottomSheetDialog
+import com.google.android.material.bottomsheet.BottomSheetDialogFragment
+import com.krunal.demo.databinding.FragmentOperationsBottomSheetBinding
+
+class OperationsBottomSheetFragment : BottomSheetDialogFragment() {
+
+ private lateinit var binding: FragmentOperationsBottomSheetBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
+ ): View {
+ binding = FragmentOperationsBottomSheetBinding.inflate(layoutInflater)
+ return binding.root
+ }
+
+ @SuppressLint("RestrictedApi", "VisibleForTests")
+ override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+ val dialog = super.onCreateDialog(savedInstanceState)
+
+ (dialog as BottomSheetDialog).behavior.apply {
+ isDraggable = true
+ state = BottomSheetBehavior.STATE_EXPANDED
+ }
+ return dialog
+ }
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/tablayoutfragments/CallsFragment.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/tablayoutfragments/CallsFragment.kt
new file mode 100644
index 0000000..9c9e82c
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/tablayoutfragments/CallsFragment.kt
@@ -0,0 +1,6 @@
+package com.krunal.demo.uicomponents.tablayoutfragments
+
+import androidx.fragment.app.Fragment
+import com.krunal.demo.R
+
+class CallsFragment : Fragment(R.layout.fragment_calls)
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/tablayoutfragments/ChatFragment.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/tablayoutfragments/ChatFragment.kt
new file mode 100644
index 0000000..9d9f346
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/tablayoutfragments/ChatFragment.kt
@@ -0,0 +1,11 @@
+package com.krunal.demo.uicomponents.tablayoutfragments
+
+import android.os.Bundle
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import com.krunal.demo.R
+
+class ChatFragment : Fragment(R.layout.fragment_chat) {
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/tablayoutfragments/HomeFragment.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/tablayoutfragments/HomeFragment.kt
new file mode 100644
index 0000000..8d124ab
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/tablayoutfragments/HomeFragment.kt
@@ -0,0 +1,66 @@
+package com.krunal.demo.uicomponents.tablayoutfragments
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import com.google.android.material.tabs.TabLayout
+import com.google.android.material.tabs.TabLayout.OnTabSelectedListener
+import com.krunal.demo.R
+import com.krunal.demo.databinding.FragmentHomeBinding
+
+class HomeFragment : Fragment(R.layout.fragment_home) {
+
+ private lateinit var binding: FragmentHomeBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
+ ): View {
+ binding = FragmentHomeBinding.inflate(layoutInflater)
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ setupTabs()
+ }
+
+ private fun setupTabs() {
+ // Text tabs programmatically
+ listOf("Tab1", "Tab2", "Tab3", "Tab4").forEach {
+ binding.tabLayoutText.apply {
+ addTab(newTab().setText(it))
+ }
+ }
+
+ // Show/Hide lable
+ binding.tabLayoutSelectedText.apply {
+ for (i in 0..tabCount) {
+ if (i != selectedTabPosition) {
+ getTabAt(i)?.tabLabelVisibility = TabLayout.TAB_LABEL_VISIBILITY_UNLABELED
+ }
+ }
+ }
+ binding.tabLayoutSelectedText.addOnTabSelectedListener(object : OnTabSelectedListener {
+ override fun onTabSelected(tab: TabLayout.Tab?) {
+ tab?.tabLabelVisibility = TabLayout.TAB_LABEL_VISIBILITY_LABELED
+ }
+
+ override fun onTabUnselected(tab: TabLayout.Tab?) {
+ tab?.tabLabelVisibility = TabLayout.TAB_LABEL_VISIBILITY_UNLABELED
+ }
+
+ override fun onTabReselected(tab: TabLayout.Tab?) {
+
+ }
+ })
+
+ // Scrollable tabs
+ listOf("Tab1", "Tab2", "Tab3").forEach {
+ binding.tabLayoutScrollable.apply {
+ addTab(newTab().setText(it))
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/utils/PreferenceKeys.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/utils/PreferenceKeys.kt
new file mode 100644
index 0000000..70f4061
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/utils/PreferenceKeys.kt
@@ -0,0 +1,11 @@
+package com.krunal.demo.uicomponents.utils
+
+object PreferenceKeys {
+
+ /**
+ * Appearance
+ */
+ const val THEME_MODE = "theme_mode"
+ const val ACCENT_COLOR = "accent_color"
+
+}
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/views/CustomView.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/views/CustomView.kt
new file mode 100644
index 0000000..02e24ce
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/views/CustomView.kt
@@ -0,0 +1,41 @@
+package com.krunal.demo.uicomponents.views
+
+import android.content.Context
+import android.content.res.TypedArray
+import android.graphics.Canvas
+import android.graphics.Color
+import android.graphics.Paint
+import android.util.AttributeSet
+import android.view.View
+import com.krunal.demo.R
+
+class CustomView(context: Context, attrs: AttributeSet): View(context, attrs) {
+
+ private val paint = Paint()
+ private var centerOfX = 340F
+ private var centerOfY = 340F
+ private val radiusOfCircleView = 140F
+ private var isCenter = false
+
+ init {
+ val attributeArray: TypedArray = context.theme.obtainStyledAttributes(
+ attrs, R.styleable.CustomButton, 0, 0
+ )
+
+ paint.apply {
+ color = attributeArray.getColor(R.styleable.CustomButton_circleColor, Color.RED)
+ strokeWidth = attributeArray.getFloat(R.styleable.CustomButton_strokeSize, 20f)
+ style = Paint.Style.STROKE
+ }
+ isCenter = attributeArray.getBoolean(R.styleable.CustomButton_onCenter, isCenter)
+ }
+
+ override fun onDraw(canvas: Canvas?) {
+ if (isCenter) {
+ centerOfX = (width / 2).toFloat()
+ centerOfY = (height / 2).toFloat()
+ }
+ canvas?.drawCircle(centerOfX, centerOfY, radiusOfCircleView, paint)
+ super.onDraw(canvas)
+ }
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/views/HistoryLineView.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/views/HistoryLineView.kt
new file mode 100644
index 0000000..3fd28d1
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/views/HistoryLineView.kt
@@ -0,0 +1,70 @@
+package com.krunal.demo.uicomponents.views
+
+import android.content.Context
+import android.graphics.Canvas
+import android.graphics.Color
+import android.graphics.Paint
+import android.util.AttributeSet
+import android.view.View
+import com.krunal.demo.R
+
+class HistoryLineView(context: Context, attrs: AttributeSet) : View(context, attrs) {
+
+ private val thumbPaint = Paint(Paint.ANTI_ALIAS_FLAG)
+ private val linePaint = Paint(Paint.ANTI_ALIAS_FLAG)
+ private var thumbColor = Color.BLUE
+ private var lineColor = thumbColor
+ private var thumbRadius = 10F
+ private var lineWidth = 2F
+
+ init {
+
+ setupAttributes(attrs)
+ setupPaint()
+ }
+
+ private fun setupAttributes(attrs: AttributeSet) {
+ val typedArray =
+ context.theme.obtainStyledAttributes(attrs, R.styleable.HistoryLineView, 0, 0)
+ thumbColor = typedArray.getColor(R.styleable.HistoryLineView_thumbColor, thumbColor)
+ lineColor = typedArray.getColor(R.styleable.HistoryLineView_lineColor, lineColor)
+ thumbRadius = typedArray.getDimension(R.styleable.HistoryLineView_thumbRadius, thumbRadius)
+ lineWidth = typedArray.getDimension(R.styleable.HistoryLineView_lineWidth, lineWidth)
+
+// typedArray.recycle()
+ }
+
+ private fun setupPaint() {
+ thumbPaint.apply {
+ color = thumbColor
+ style = Paint.Style.FILL
+ }
+
+ linePaint.apply {
+ color = lineColor
+ strokeWidth = lineWidth
+ style = Paint.Style.STROKE
+ strokeCap = Paint.Cap.ROUND
+ }
+ }
+
+ override fun onDraw(canvas: Canvas) {
+ super.onDraw(canvas)
+
+ drawThumb(canvas)
+ drawLine(canvas)
+ }
+
+ private fun drawThumb(canvas: Canvas) {
+ canvas.drawCircle((width / 2).toFloat(), thumbRadius, thumbRadius, thumbPaint)
+ }
+
+ private fun drawLine(canvas: Canvas) {
+ val xPosition = (width / 2).toFloat()
+ val yStartPosition = (thumbRadius * 2) + lineWidth
+ val yEndPosition = height - yStartPosition
+ canvas.drawLine(
+ xPosition, yStartPosition, xPosition, yEndPosition, linePaint
+ )
+ }
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/java/com/krunal/demo/uicomponents/views/MyClickableSpan.kt b/Demo/app/src/main/java/com/krunal/demo/uicomponents/views/MyClickableSpan.kt
new file mode 100644
index 0000000..81d9176
--- /dev/null
+++ b/Demo/app/src/main/java/com/krunal/demo/uicomponents/views/MyClickableSpan.kt
@@ -0,0 +1,18 @@
+package com.krunal.demo.uicomponents.views
+
+import android.text.TextPaint
+import android.text.style.ClickableSpan
+import android.view.View
+
+class MyClickableSpan(
+ private val onTextClick: () -> Unit
+) : ClickableSpan() {
+ override fun onClick(view: View) {
+ onTextClick()
+ }
+
+ override fun updateDrawState(ds: TextPaint) {
+ super.updateDrawState(ds)
+ ds.isUnderlineText = false
+ }
+}
\ No newline at end of file
diff --git a/Demo/app/src/main/res/color/chip_card.xml b/Demo/app/src/main/res/color/chip_card.xml
new file mode 100644
index 0000000..ed1c356
--- /dev/null
+++ b/Demo/app/src/main/res/color/chip_card.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/color/chip_card_text.xml b/Demo/app/src/main/res/color/chip_card_text.xml
new file mode 100644
index 0000000..447acf5
--- /dev/null
+++ b/Demo/app/src/main/res/color/chip_card_text.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/color/chip_operations_time.xml b/Demo/app/src/main/res/color/chip_operations_time.xml
new file mode 100644
index 0000000..cd4dbcd
--- /dev/null
+++ b/Demo/app/src/main/res/color/chip_operations_time.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/color/stack_exchange_chip_background.xml b/Demo/app/src/main/res/color/stack_exchange_chip_background.xml
new file mode 100644
index 0000000..b4b0d3b
--- /dev/null
+++ b/Demo/app/src/main/res/color/stack_exchange_chip_background.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/drawable/calendar_banner.jpeg b/Demo/app/src/main/res/drawable/calendar_banner.jpeg
new file mode 100644
index 0000000..6b784d4
Binary files /dev/null and b/Demo/app/src/main/res/drawable/calendar_banner.jpeg differ
diff --git a/Demo/app/src/main/res/drawable/circle_image.xml b/Demo/app/src/main/res/drawable/circle_image.xml
new file mode 100644
index 0000000..2051ea6
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/circle_image.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/drawable/circular_progress.xml b/Demo/app/src/main/res/drawable/circular_progress.xml
new file mode 100644
index 0000000..26827c2
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/circular_progress.xml
@@ -0,0 +1,16 @@
+
+
+
+ -
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/drawable/dark_forest.jpeg b/Demo/app/src/main/res/drawable/dark_forest.jpeg
new file mode 100644
index 0000000..bd25b0d
Binary files /dev/null and b/Demo/app/src/main/res/drawable/dark_forest.jpeg differ
diff --git a/Demo/app/src/main/res/drawable/gradient_button.xml b/Demo/app/src/main/res/drawable/gradient_button.xml
new file mode 100644
index 0000000..1b2e930
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/gradient_button.xml
@@ -0,0 +1,13 @@
+
+
+ -
+
+
+
+
+
+
diff --git a/Demo/app/src/main/res/drawable/gradient_progress.xml b/Demo/app/src/main/res/drawable/gradient_progress.xml
new file mode 100644
index 0000000..5f6dc5f
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/gradient_progress.xml
@@ -0,0 +1,24 @@
+
+
+ -
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/drawable/highlighted_background.xml b/Demo/app/src/main/res/drawable/highlighted_background.xml
new file mode 100644
index 0000000..af6d70b
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/highlighted_background.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/drawable/ic_add.xml b/Demo/app/src/main/res/drawable/ic_add.xml
new file mode 100644
index 0000000..70046c4
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_add.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_add_filled.xml b/Demo/app/src/main/res/drawable/ic_add_filled.xml
new file mode 100644
index 0000000..a14875c
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_add_filled.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_android.xml b/Demo/app/src/main/res/drawable/ic_android.xml
new file mode 100644
index 0000000..1168496
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_android.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_avax_logo.xml b/Demo/app/src/main/res/drawable/ic_avax_logo.xml
new file mode 100644
index 0000000..c36bcab
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_avax_logo.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_back.xml b/Demo/app/src/main/res/drawable/ic_back.xml
new file mode 100644
index 0000000..6c3197a
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_back.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_calendar.xml b/Demo/app/src/main/res/drawable/ic_calendar.xml
new file mode 100644
index 0000000..b6caf72
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_calendar.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_call.xml b/Demo/app/src/main/res/drawable/ic_call.xml
new file mode 100644
index 0000000..2aba8ad
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_call.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_card.xml b/Demo/app/src/main/res/drawable/ic_card.xml
new file mode 100644
index 0000000..838fb42
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_card.xml
@@ -0,0 +1,5 @@
+
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_chat.xml b/Demo/app/src/main/res/drawable/ic_chat.xml
new file mode 100644
index 0000000..9e7de07
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_chat.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_check.xml b/Demo/app/src/main/res/drawable/ic_check.xml
new file mode 100644
index 0000000..fbc59ec
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_check.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_circle.xml b/Demo/app/src/main/res/drawable/ic_circle.xml
new file mode 100644
index 0000000..7c795ea
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_circle.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_cross.xml b/Demo/app/src/main/res/drawable/ic_cross.xml
new file mode 100644
index 0000000..70db409
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_cross.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_down_arrow.xml b/Demo/app/src/main/res/drawable/ic_down_arrow.xml
new file mode 100644
index 0000000..3dbfedb
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_down_arrow.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_down_arrow_outlined.xml b/Demo/app/src/main/res/drawable/ic_down_arrow_outlined.xml
new file mode 100644
index 0000000..1aeaa99
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_down_arrow_outlined.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_email.xml b/Demo/app/src/main/res/drawable/ic_email.xml
new file mode 100644
index 0000000..80111c8
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_email.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_exchange.xml b/Demo/app/src/main/res/drawable/ic_exchange.xml
new file mode 100644
index 0000000..6f7c7f3
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_exchange.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_feed.xml b/Demo/app/src/main/res/drawable/ic_feed.xml
new file mode 100644
index 0000000..4a4e158
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_feed.xml
@@ -0,0 +1,5 @@
+
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_female.xml b/Demo/app/src/main/res/drawable/ic_female.xml
new file mode 100644
index 0000000..ea62387
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_female.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_food.xml b/Demo/app/src/main/res/drawable/ic_food.xml
new file mode 100644
index 0000000..45861e1
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_food.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_gasoline.xml b/Demo/app/src/main/res/drawable/ic_gasoline.xml
new file mode 100644
index 0000000..bc05081
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_gasoline.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_heart_outlined.xml b/Demo/app/src/main/res/drawable/ic_heart_outlined.xml
new file mode 100644
index 0000000..58c0403
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_heart_outlined.xml
@@ -0,0 +1,4 @@
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_home.xml b/Demo/app/src/main/res/drawable/ic_home.xml
new file mode 100644
index 0000000..4c5e854
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_home.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_image.xml b/Demo/app/src/main/res/drawable/ic_image.xml
new file mode 100644
index 0000000..d35859d
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_image.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_info.xml b/Demo/app/src/main/res/drawable/ic_info.xml
new file mode 100644
index 0000000..e0ecb40
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_info.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_line_shader.xml b/Demo/app/src/main/res/drawable/ic_line_shader.xml
new file mode 100644
index 0000000..c775e03
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_line_shader.xml
@@ -0,0 +1,4 @@
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_link_logo.xml b/Demo/app/src/main/res/drawable/ic_link_logo.xml
new file mode 100644
index 0000000..5eb2e0c
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_link_logo.xml
@@ -0,0 +1,4 @@
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_male.xml b/Demo/app/src/main/res/drawable/ic_male.xml
new file mode 100644
index 0000000..97af074
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_male.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_market.xml b/Demo/app/src/main/res/drawable/ic_market.xml
new file mode 100644
index 0000000..9dd36e5
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_market.xml
@@ -0,0 +1,4 @@
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_mastercard.xml b/Demo/app/src/main/res/drawable/ic_mastercard.xml
new file mode 100644
index 0000000..3405fd8
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_mastercard.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_menu.xml b/Demo/app/src/main/res/drawable/ic_menu.xml
new file mode 100644
index 0000000..470db52
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_menu.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_next.xml b/Demo/app/src/main/res/drawable/ic_next.xml
new file mode 100644
index 0000000..4680420
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_next.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_notification.xml b/Demo/app/src/main/res/drawable/ic_notification.xml
new file mode 100644
index 0000000..45d15da
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_notification.xml
@@ -0,0 +1,4 @@
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_other_gender.xml b/Demo/app/src/main/res/drawable/ic_other_gender.xml
new file mode 100644
index 0000000..856139c
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_other_gender.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_paperplane.xml b/Demo/app/src/main/res/drawable/ic_paperplane.xml
new file mode 100644
index 0000000..bb0e194
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_paperplane.xml
@@ -0,0 +1,5 @@
+
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_pause.xml b/Demo/app/src/main/res/drawable/ic_pause.xml
new file mode 100644
index 0000000..f701d6f
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_pause.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_pause_outlined.xml b/Demo/app/src/main/res/drawable/ic_pause_outlined.xml
new file mode 100644
index 0000000..dbf5f42
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_pause_outlined.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_pen.xml b/Demo/app/src/main/res/drawable/ic_pen.xml
new file mode 100644
index 0000000..faddfce
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_pen.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_play.xml b/Demo/app/src/main/res/drawable/ic_play.xml
new file mode 100644
index 0000000..0870be8
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_play.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_play_outlined.xml b/Demo/app/src/main/res/drawable/ic_play_outlined.xml
new file mode 100644
index 0000000..c4f8875
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_play_outlined.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_previous.xml b/Demo/app/src/main/res/drawable/ic_previous.xml
new file mode 100644
index 0000000..544bf5b
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_previous.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_profile.xml b/Demo/app/src/main/res/drawable/ic_profile.xml
new file mode 100644
index 0000000..ea4bd5c
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_profile.xml
@@ -0,0 +1,4 @@
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_remove.xml b/Demo/app/src/main/res/drawable/ic_remove.xml
new file mode 100644
index 0000000..128a743
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_remove.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_right_arrow.xml b/Demo/app/src/main/res/drawable/ic_right_arrow.xml
new file mode 100644
index 0000000..a749bde
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_right_arrow.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_rose_logo.xml b/Demo/app/src/main/res/drawable/ic_rose_logo.xml
new file mode 100644
index 0000000..f418b9e
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_rose_logo.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_search.xml b/Demo/app/src/main/res/drawable/ic_search.xml
new file mode 100644
index 0000000..6031484
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_search.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_splash.xml b/Demo/app/src/main/res/drawable/ic_splash.xml
new file mode 100644
index 0000000..ce0d04e
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_splash.xml
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_swap.xml b/Demo/app/src/main/res/drawable/ic_swap.xml
new file mode 100644
index 0000000..d113e11
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_swap.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_timezone.xml b/Demo/app/src/main/res/drawable/ic_timezone.xml
new file mode 100644
index 0000000..3476385
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_timezone.xml
@@ -0,0 +1,5 @@
+
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_two_circle.xml b/Demo/app/src/main/res/drawable/ic_two_circle.xml
new file mode 100644
index 0000000..87fc77a
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_two_circle.xml
@@ -0,0 +1,4 @@
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_up_arrow.xml b/Demo/app/src/main/res/drawable/ic_up_arrow.xml
new file mode 100644
index 0000000..ba9e503
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_up_arrow.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/Demo/app/src/main/res/drawable/ic_wallet.xml b/Demo/app/src/main/res/drawable/ic_wallet.xml
new file mode 100644
index 0000000..fc12537
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/ic_wallet.xml
@@ -0,0 +1,5 @@
+
+
+
+
diff --git a/Demo/app/src/main/res/drawable/image_toggle.xml b/Demo/app/src/main/res/drawable/image_toggle.xml
new file mode 100644
index 0000000..56adc24
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/image_toggle.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/drawable/img.png b/Demo/app/src/main/res/drawable/img.png
new file mode 100644
index 0000000..bc5121c
Binary files /dev/null and b/Demo/app/src/main/res/drawable/img.png differ
diff --git a/Demo/app/src/main/res/drawable/profile.jpeg b/Demo/app/src/main/res/drawable/profile.jpeg
new file mode 100644
index 0000000..74d27a6
Binary files /dev/null and b/Demo/app/src/main/res/drawable/profile.jpeg differ
diff --git a/Demo/app/src/main/res/drawable/progress_vertical.xml b/Demo/app/src/main/res/drawable/progress_vertical.xml
new file mode 100644
index 0000000..c4350b1
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/progress_vertical.xml
@@ -0,0 +1,20 @@
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/drawable/progress_vertical_graph.xml b/Demo/app/src/main/res/drawable/progress_vertical_graph.xml
new file mode 100644
index 0000000..915dae8
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/progress_vertical_graph.xml
@@ -0,0 +1,20 @@
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/drawable/rounded_bottom_bar.xml b/Demo/app/src/main/res/drawable/rounded_bottom_bar.xml
new file mode 100644
index 0000000..b12f214
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/rounded_bottom_bar.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/drawable/rounded_bottom_sheet.xml b/Demo/app/src/main/res/drawable/rounded_bottom_sheet.xml
new file mode 100644
index 0000000..98c2220
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/rounded_bottom_sheet.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/drawable/rounded_image.xml b/Demo/app/src/main/res/drawable/rounded_image.xml
new file mode 100644
index 0000000..b93d8ec
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/rounded_image.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/drawable/rounded_tab_layout.xml b/Demo/app/src/main/res/drawable/rounded_tab_layout.xml
new file mode 100644
index 0000000..b576933
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/rounded_tab_layout.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/drawable/rounded_toast.xml b/Demo/app/src/main/res/drawable/rounded_toast.xml
new file mode 100644
index 0000000..db31de8
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/rounded_toast.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/drawable/rounded_transparent_background.xml b/Demo/app/src/main/res/drawable/rounded_transparent_background.xml
new file mode 100644
index 0000000..2526f09
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/rounded_transparent_background.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/drawable/running_up_that_hill.png b/Demo/app/src/main/res/drawable/running_up_that_hill.png
new file mode 100644
index 0000000..82e0545
Binary files /dev/null and b/Demo/app/src/main/res/drawable/running_up_that_hill.png differ
diff --git a/Demo/app/src/main/res/drawable/selected_theme.xml b/Demo/app/src/main/res/drawable/selected_theme.xml
new file mode 100644
index 0000000..0c30dbd
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/selected_theme.xml
@@ -0,0 +1,20 @@
+
+
+
+
+ -
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/drawable/tab_selected_background.xml b/Demo/app/src/main/res/drawable/tab_selected_background.xml
new file mode 100644
index 0000000..a596220
--- /dev/null
+++ b/Demo/app/src/main/res/drawable/tab_selected_background.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/drawable/time_banner.jpeg b/Demo/app/src/main/res/drawable/time_banner.jpeg
new file mode 100644
index 0000000..147a3f1
Binary files /dev/null and b/Demo/app/src/main/res/drawable/time_banner.jpeg differ
diff --git a/Demo/app/src/main/res/drawable/trade_graph.png b/Demo/app/src/main/res/drawable/trade_graph.png
new file mode 100644
index 0000000..034cbc8
Binary files /dev/null and b/Demo/app/src/main/res/drawable/trade_graph.png differ
diff --git a/Demo/app/src/main/res/layout/activity_uicomponents.xml b/Demo/app/src/main/res/layout/activity_uicomponents.xml
new file mode 100644
index 0000000..5851e1c
--- /dev/null
+++ b/Demo/app/src/main/res/layout/activity_uicomponents.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/card_chip.xml b/Demo/app/src/main/res/layout/card_chip.xml
new file mode 100644
index 0000000..8d95f42
--- /dev/null
+++ b/Demo/app/src/main/res/layout/card_chip.xml
@@ -0,0 +1,7 @@
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/card_layout.xml b/Demo/app/src/main/res/layout/card_layout.xml
new file mode 100644
index 0000000..8448f1c
--- /dev/null
+++ b/Demo/app/src/main/res/layout/card_layout.xml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/custom_toast.xml b/Demo/app/src/main/res/layout/custom_toast.xml
new file mode 100644
index 0000000..44d0ada
--- /dev/null
+++ b/Demo/app/src/main/res/layout/custom_toast.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/fragment_app_bar.xml b/Demo/app/src/main/res/layout/fragment_app_bar.xml
new file mode 100644
index 0000000..12ac20d
--- /dev/null
+++ b/Demo/app/src/main/res/layout/fragment_app_bar.xml
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/fragment_button.xml b/Demo/app/src/main/res/layout/fragment_button.xml
new file mode 100644
index 0000000..d333081
--- /dev/null
+++ b/Demo/app/src/main/res/layout/fragment_button.xml
@@ -0,0 +1,149 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/fragment_calls.xml b/Demo/app/src/main/res/layout/fragment_calls.xml
new file mode 100644
index 0000000..90b2028
--- /dev/null
+++ b/Demo/app/src/main/res/layout/fragment_calls.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/fragment_card.xml b/Demo/app/src/main/res/layout/fragment_card.xml
new file mode 100644
index 0000000..601c02e
--- /dev/null
+++ b/Demo/app/src/main/res/layout/fragment_card.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/fragment_chat.xml b/Demo/app/src/main/res/layout/fragment_chat.xml
new file mode 100644
index 0000000..a78ec1b
--- /dev/null
+++ b/Demo/app/src/main/res/layout/fragment_chat.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/fragment_checkbox.xml b/Demo/app/src/main/res/layout/fragment_checkbox.xml
new file mode 100644
index 0000000..b596b4d
--- /dev/null
+++ b/Demo/app/src/main/res/layout/fragment_checkbox.xml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/fragment_chip.xml b/Demo/app/src/main/res/layout/fragment_chip.xml
new file mode 100644
index 0000000..add4153
--- /dev/null
+++ b/Demo/app/src/main/res/layout/fragment_chip.xml
@@ -0,0 +1,286 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/fragment_cl_chain_bias.xml b/Demo/app/src/main/res/layout/fragment_cl_chain_bias.xml
new file mode 100644
index 0000000..b6684ab
--- /dev/null
+++ b/Demo/app/src/main/res/layout/fragment_cl_chain_bias.xml
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/fragment_cl_circular.xml b/Demo/app/src/main/res/layout/fragment_cl_circular.xml
new file mode 100644
index 0000000..a914dbc
--- /dev/null
+++ b/Demo/app/src/main/res/layout/fragment_cl_circular.xml
@@ -0,0 +1,119 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/fragment_cl_guideline_barrier.xml b/Demo/app/src/main/res/layout/fragment_cl_guideline_barrier.xml
new file mode 100644
index 0000000..1c03790
--- /dev/null
+++ b/Demo/app/src/main/res/layout/fragment_cl_guideline_barrier.xml
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/fragment_cl_relative.xml b/Demo/app/src/main/res/layout/fragment_cl_relative.xml
new file mode 100644
index 0000000..2449684
--- /dev/null
+++ b/Demo/app/src/main/res/layout/fragment_cl_relative.xml
@@ -0,0 +1,118 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/fragment_coordinator_layout.xml b/Demo/app/src/main/res/layout/fragment_coordinator_layout.xml
new file mode 100644
index 0000000..c6bb019
--- /dev/null
+++ b/Demo/app/src/main/res/layout/fragment_coordinator_layout.xml
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/fragment_custom_view.xml b/Demo/app/src/main/res/layout/fragment_custom_view.xml
new file mode 100644
index 0000000..0b1db78
--- /dev/null
+++ b/Demo/app/src/main/res/layout/fragment_custom_view.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/fragment_data_binding.xml b/Demo/app/src/main/res/layout/fragment_data_binding.xml
new file mode 100644
index 0000000..b14c936
--- /dev/null
+++ b/Demo/app/src/main/res/layout/fragment_data_binding.xml
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/fragment_date_picker.xml b/Demo/app/src/main/res/layout/fragment_date_picker.xml
new file mode 100644
index 0000000..14fa060
--- /dev/null
+++ b/Demo/app/src/main/res/layout/fragment_date_picker.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/fragment_edit_text.xml b/Demo/app/src/main/res/layout/fragment_edit_text.xml
new file mode 100644
index 0000000..f8c60b0
--- /dev/null
+++ b/Demo/app/src/main/res/layout/fragment_edit_text.xml
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/fragment_fab.xml b/Demo/app/src/main/res/layout/fragment_fab.xml
new file mode 100644
index 0000000..b26827c
--- /dev/null
+++ b/Demo/app/src/main/res/layout/fragment_fab.xml
@@ -0,0 +1,99 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/fragment_frame_layout.xml b/Demo/app/src/main/res/layout/fragment_frame_layout.xml
new file mode 100644
index 0000000..142333e
--- /dev/null
+++ b/Demo/app/src/main/res/layout/fragment_frame_layout.xml
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/fragment_home.xml b/Demo/app/src/main/res/layout/fragment_home.xml
new file mode 100644
index 0000000..53419cf
--- /dev/null
+++ b/Demo/app/src/main/res/layout/fragment_home.xml
@@ -0,0 +1,97 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/fragment_linear_layout.xml b/Demo/app/src/main/res/layout/fragment_linear_layout.xml
new file mode 100644
index 0000000..8260ec9
--- /dev/null
+++ b/Demo/app/src/main/res/layout/fragment_linear_layout.xml
@@ -0,0 +1,104 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/fragment_operations_bottom_sheet.xml b/Demo/app/src/main/res/layout/fragment_operations_bottom_sheet.xml
new file mode 100644
index 0000000..4316836
--- /dev/null
+++ b/Demo/app/src/main/res/layout/fragment_operations_bottom_sheet.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/fragment_progress_bar.xml b/Demo/app/src/main/res/layout/fragment_progress_bar.xml
new file mode 100644
index 0000000..3ff51f9
--- /dev/null
+++ b/Demo/app/src/main/res/layout/fragment_progress_bar.xml
@@ -0,0 +1,128 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/fragment_radio.xml b/Demo/app/src/main/res/layout/fragment_radio.xml
new file mode 100644
index 0000000..41dace5
--- /dev/null
+++ b/Demo/app/src/main/res/layout/fragment_radio.xml
@@ -0,0 +1,110 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/fragment_relative_layout.xml b/Demo/app/src/main/res/layout/fragment_relative_layout.xml
new file mode 100644
index 0000000..f6a65b7
--- /dev/null
+++ b/Demo/app/src/main/res/layout/fragment_relative_layout.xml
@@ -0,0 +1,122 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/fragment_slider.xml b/Demo/app/src/main/res/layout/fragment_slider.xml
new file mode 100644
index 0000000..b26a1a1
--- /dev/null
+++ b/Demo/app/src/main/res/layout/fragment_slider.xml
@@ -0,0 +1,118 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/fragment_snackbar.xml b/Demo/app/src/main/res/layout/fragment_snackbar.xml
new file mode 100644
index 0000000..cd3f664
--- /dev/null
+++ b/Demo/app/src/main/res/layout/fragment_snackbar.xml
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/fragment_span.xml b/Demo/app/src/main/res/layout/fragment_span.xml
new file mode 100644
index 0000000..4ba1dae
--- /dev/null
+++ b/Demo/app/src/main/res/layout/fragment_span.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/fragment_spinner.xml b/Demo/app/src/main/res/layout/fragment_spinner.xml
new file mode 100644
index 0000000..3f35787
--- /dev/null
+++ b/Demo/app/src/main/res/layout/fragment_spinner.xml
@@ -0,0 +1,119 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/fragment_tab_layout.xml b/Demo/app/src/main/res/layout/fragment_tab_layout.xml
new file mode 100644
index 0000000..6e58cac
--- /dev/null
+++ b/Demo/app/src/main/res/layout/fragment_tab_layout.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/fragment_theme.xml b/Demo/app/src/main/res/layout/fragment_theme.xml
new file mode 100644
index 0000000..019c01e
--- /dev/null
+++ b/Demo/app/src/main/res/layout/fragment_theme.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/fragment_time_picker.xml b/Demo/app/src/main/res/layout/fragment_time_picker.xml
new file mode 100644
index 0000000..ef19821
--- /dev/null
+++ b/Demo/app/src/main/res/layout/fragment_time_picker.xml
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/fragment_toast.xml b/Demo/app/src/main/res/layout/fragment_toast.xml
new file mode 100644
index 0000000..3c424ca
--- /dev/null
+++ b/Demo/app/src/main/res/layout/fragment_toast.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/name_layout.xml b/Demo/app/src/main/res/layout/name_layout.xml
new file mode 100644
index 0000000..83b82bb
--- /dev/null
+++ b/Demo/app/src/main/res/layout/name_layout.xml
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/name_merge_layout.xml b/Demo/app/src/main/res/layout/name_merge_layout.xml
new file mode 100644
index 0000000..4e091eb
--- /dev/null
+++ b/Demo/app/src/main/res/layout/name_merge_layout.xml
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/notification_layout.xml b/Demo/app/src/main/res/layout/notification_layout.xml
new file mode 100644
index 0000000..2093f75
--- /dev/null
+++ b/Demo/app/src/main/res/layout/notification_layout.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/operations_card_layout.xml b/Demo/app/src/main/res/layout/operations_card_layout.xml
new file mode 100644
index 0000000..c6e6893
--- /dev/null
+++ b/Demo/app/src/main/res/layout/operations_card_layout.xml
@@ -0,0 +1,314 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/recent_operation_layout.xml b/Demo/app/src/main/res/layout/recent_operation_layout.xml
new file mode 100644
index 0000000..98b8901
--- /dev/null
+++ b/Demo/app/src/main/res/layout/recent_operation_layout.xml
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/theme_layout.xml b/Demo/app/src/main/res/layout/theme_layout.xml
new file mode 100644
index 0000000..0ab2c08
--- /dev/null
+++ b/Demo/app/src/main/res/layout/theme_layout.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/layout/timezone_spinner.xml b/Demo/app/src/main/res/layout/timezone_spinner.xml
new file mode 100644
index 0000000..e77e4bc
--- /dev/null
+++ b/Demo/app/src/main/res/layout/timezone_spinner.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/menu/card_bottom_navigation_items.xml b/Demo/app/src/main/res/menu/card_bottom_navigation_items.xml
new file mode 100644
index 0000000..1bf6a7f
--- /dev/null
+++ b/Demo/app/src/main/res/menu/card_bottom_navigation_items.xml
@@ -0,0 +1,15 @@
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/menu/toolbar_menu.xml b/Demo/app/src/main/res/menu/toolbar_menu.xml
new file mode 100644
index 0000000..b9d969a
--- /dev/null
+++ b/Demo/app/src/main/res/menu/toolbar_menu.xml
@@ -0,0 +1,28 @@
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/menu/toolbar_search_menu.xml b/Demo/app/src/main/res/menu/toolbar_search_menu.xml
new file mode 100644
index 0000000..fe0277c
--- /dev/null
+++ b/Demo/app/src/main/res/menu/toolbar_search_menu.xml
@@ -0,0 +1,20 @@
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/values-night/themes.xml b/Demo/app/src/main/res/values-night/themes.xml
index cab700d..6fdeb72 100644
--- a/Demo/app/src/main/res/values-night/themes.xml
+++ b/Demo/app/src/main/res/values-night/themes.xml
@@ -12,5 +12,258 @@
- ?attr/colorPrimaryVariant
+ -
+ @style/Widget.MaterialComponents.BottomSheet.DragHandle
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/values/arrays.xml b/Demo/app/src/main/res/values/arrays.xml
new file mode 100644
index 0000000..6ca93c0
--- /dev/null
+++ b/Demo/app/src/main/res/values/arrays.xml
@@ -0,0 +1,90 @@
+
+
+
+ - 10
+ - 50
+
+
+
+ - (UTC) Casablanca
+ - (UTC) Coordinated Universal Time
+ - (UTC) Dublin, Edinburgh, Lisbon, London
+ - (UTC) Monrovia, Reykjavik
+ - (UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna
+ - (UTC+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague
+ - (UTC+01:00) Brussels, Copenhagen, Madrid, Paris
+ - (UTC+01:00) Sarajevo, Skopje, Warsaw, Zagreb
+ - (UTC+01:00) West Central Africa
+ - (UTC+01:00) Windhoek
+ - (UTC+02:00) Amman
+ - (UTC+02:00) Athens, Bucharest
+ - (UTC+02:00) Beirut
+ - (UTC+02:00) Cairo
+ - (UTC+02:00) Damascus
+ - (UTC+02:00) E. Europe
+ - (UTC+02:00) Harare, Pretoria
+ - (UTC+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius
+ - (UTC+02:00) Istanbul
+ - (UTC+02:00) Jerusalem
+ - (UTC+03:00) Baghdad
+ - (UTC+03:00) Kuwait, Riyadh
+ - (UTC+03:00) Minsk
+ - (UTC+03:00) Moscow, St. Petersburg, Volgograd (RTZ 2)
+ - (UTC+03:00) Nairobi
+ - (UTC+03:30) Tehran
+ - (UTC+04:00) Abu Dhabi, Muscat
+ - (UTC+04:00) Baku
+ - (UTC+04:00) Port Louis
+ - (UTC+04:00) Tbilisi
+ - (UTC+04:00) Yerevan
+ - (UTC+04:30) Kabul
+ - (UTC+05:00) Ashgabat, Tashkent
+ - (UTC+05:00) Islamabad, Karachi
+ - (UTC+05:30) Chennai, Kolkata, Mumbai, New Delhi
+ - (UTC+05:30) Sri Jayawardenepura
+ - (UTC+05:45) Kathmandu
+ - (UTC+06:00) Astana
+ - (UTC+06:00) Dhaka
+ - (UTC+06:30) Yangon (Rangoon)
+ - (UTC+07:00) Bangkok, Hanoi, Jakarta
+ - (UTC+08:00) Beijing, Chongqing, Hong Kong, Urumqi
+ - (UTC+08:00) Kuala Lumpur, Singapore
+ - (UTC+08:00) Taipei
+ - (UTC+08:00) Ulaanbaatar
+ - (UTC+09:00) Osaka, Sapporo, Tokyo
+ - (UTC+09:00) Seoul
+ - (UTC+10:00) Canberra, Melbourne, Sydney
+
+
+
+ - @string/color_red
+ - @string/color_blue
+ - @string/color_yellow
+ - @string/color_green
+ - @string/color_purple
+ - @string/color_violet
+
+
+
+ - RED
+ - BLUE
+ - YELLOW
+ - GREEN
+ - PURPLE
+ - VIOLET
+
+
+
+ - 32
+ - 28
+ - 26
+ - 14
+
+
+
+ - #FFC107
+ - #DF9B68
+ - #8BC34A
+ - #03A9F4
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/values/attrs.xml b/Demo/app/src/main/res/values/attrs.xml
new file mode 100644
index 0000000..49dc0b7
--- /dev/null
+++ b/Demo/app/src/main/res/values/attrs.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/values/colors.xml b/Demo/app/src/main/res/values/colors.xml
index f8c6127..44ee837 100644
--- a/Demo/app/src/main/res/values/colors.xml
+++ b/Demo/app/src/main/res/values/colors.xml
@@ -7,4 +7,441 @@
#FF018786
#FF000000
#FFFFFFFF
+
+ #0D7BD2
+ #BF4DDF
+ #DDAA7E
+ #F34A4A
+
+ // Custom theme colors
+ #0058CB
+ #FFFFFF
+ #D9E2FF
+ #001945
+ #575E71
+ #FFFFFF
+ #DCE2F9
+ #141B2C
+ #725572
+ #FFFFFF
+ #FDD7FA
+ #2A132C
+ #BA1A1A
+ #FFDAD6
+ #FFFFFF
+ #410002
+ #FEFBFF
+ #1B1B1F
+ #FEFBFF
+ #1B1B1F
+ #E1E2EC
+ #44464F
+ #757780
+ #F2F0F4
+ #303034
+ #B0C6FF
+ #B0C6FF
+ #002D6F
+ #00429B
+ #D9E2FF
+ #C0C6DC
+ #293042
+ #404659
+ #DCE2F9
+ #E0BBDD
+ #412742
+ #593D5A
+ #FDD7FA
+ #FFB4AB
+ #93000A
+ #690005
+ #FFDAD6
+ #1B1B1F
+ #E3E2E6
+ #1B1B1F
+ #E3E2E6
+ #44464F
+ #C5C6D0
+ #8F9099
+ #1B1B1F
+ #E3E2E6
+ #0058CB
+
+ #9F4034
+ #FFFFFF
+ #FFDAD5
+ #410000
+ #775652
+ #FFFFFF
+ #FFDAD5
+ #2C1512
+ #705C2E
+ #FFFFFF
+ #FCDFA6
+ #251A00
+ #BA1A1A
+ #FFDAD6
+ #FFFFFF
+ #410002
+ #FFFBFF
+ #201A19
+ #FFFBFF
+ #201A19
+ #F5DDDA
+ #534341
+ #857370
+ #FBEEEC
+ #362F2E
+ #FFB4A9
+ #FFB4A9
+ #61120C
+ #7F291F
+ #FFDAD5
+ #E7BDB6
+ #442925
+ #5D3F3B
+ #FFDAD5
+ #DEC38C
+ #3E2E04
+ #574419
+ #FCDFA6
+ #FFB4AB
+ #93000A
+ #690005
+ #FFDAD6
+ #201A19
+ #EDE0DE
+ #201A19
+ #EDE0DE
+ #534341
+ #D8C2BE
+ #A08C89
+ #201A19
+ #EDE0DE
+ #9F4034
+
+ #745B00
+ #FFFFFF
+ #FFE08D
+ #241A00
+ #695D3F
+ #FFFFFF
+ #F2E1BB
+ #231B04
+ #47664A
+ #FFFFFF
+ #C9ECC8
+ #04210B
+ #BA1A1A
+ #FFDAD6
+ #FFFFFF
+ #410002
+ #FFFBFF
+ #1E1B16
+ #FFFBFF
+ #1E1B16
+ #EBE1CF
+ #4C4639
+ #7E7667
+ #F7F0E7
+ #33302A
+ #EBC248
+ #EBC248
+ #3D2F00
+ #584400
+ #FFE08D
+ #D5C5A1
+ #392F15
+ #50462A
+ #F2E1BB
+ #ADCFAD
+ #19361F
+ #304D34
+ #C9ECC8
+ #FFB4AB
+ #93000A
+ #690005
+ #FFDAD6
+ #1E1B16
+ #E8E1D9
+ #1E1B16
+ #E8E1D9
+ #4C4639
+ #CFC5B4
+ #989080
+ #1E1B16
+ #E8E1D9
+ #745B00
+
+ #3E6A00
+ #FFFFFF
+ #B9F474
+ #0F2000
+ #576249
+ #FFFFFF
+ #DBE7C8
+ #151E0B
+ #386663
+ #FFFFFF
+ #BBECE8
+ #00201E
+ #BA1A1A
+ #FFDAD6
+ #FFFFFF
+ #410002
+ #FDFCF5
+ #1B1C18
+ #FDFCF5
+ #1B1C18
+ #E1E4D5
+ #44483D
+ #75796C
+ #F2F1E9
+ #30312C
+ #9ED75B
+ #9ED75B
+ #1E3700
+ #2E4F00
+ #B9F474
+ #BFCBAD
+ #2A331E
+ #404A33
+ #DBE7C8
+ #A0D0CC
+ #003735
+ #1F4E4B
+ #BBECE8
+ #FFB4AB
+ #93000A
+ #690005
+ #FFDAD6
+ #1B1C18
+ #E3E3DB
+ #1B1C18
+ #E3E3DB
+ #44483D
+ #C5C8BA
+ #8E9285
+ #1B1C18
+ #E3E3DB
+ #3E6A00
+
+ #9B3489
+ #FFFFFF
+ #FFD7F0
+ #3A0032
+ #6F5767
+ #FFFFFF
+ #F9DAEC
+ #281623
+ #815341
+ #FFFFFF
+ #FFDBCE
+ #321205
+ #BA1A1A
+ #FFDAD6
+ #FFFFFF
+ #410002
+ #FFFBFF
+ #1F1A1D
+ #FFFBFF
+ #1F1A1D
+ #EFDEE6
+ #4F444A
+ #81737B
+ #F8EEF1
+ #342F32
+ #FFACE7
+ #FFACE7
+ #5E0052
+ #7E186F
+ #FFD7F0
+ #DCBED0
+ #3E2A38
+ #56404F
+ #F9DAEC
+ #F5B9A2
+ #4B2617
+ #663C2B
+ #FFDBCE
+ #FFB4AB
+ #93000A
+ #690005
+ #FFDAD6
+ #1F1A1D
+ #EAE0E3
+ #1F1A1D
+ #EAE0E3
+ #4F444A
+ #D2C2CA
+ #9B8D94
+ #1F1A1D
+ #EAE0E3
+ #9B3489
+
+ // Colors without comments seem to be not used
+ #616161
+ // LibreTube Logo, Hyperlinks and on-off switch (on status: filling) (also influence on the
+ navbar colour)
+ #FFFFFF
+ // on-off switch (on status: circle)
+ #DCDCDC
+ #272727
+ #797979
+ // Headline Text
+ #B39494
+ // SponsorBlock marker
+ #DCDCDC
+ // NavBar Icon Container (selected)
+ #272727
+ // Navbar Icon (selected)
+ #DCDCDC
+ #272727
+ #DCDCDC
+ #272727
+ #DCDCDC
+ #DCDCDC
+ #272727
+ #272727
+ #FFFFFF
+ // Background (Settings and home)
+ #272727
+ #FFFFFF
+ // Navbar and Flyouts (uses also the "primary" color)
+ #272727
+ // NavBar Text (selected) and some Flyout Headlines
+ #DCDCDC
+ // on-off switch (off status: filling)
+ #353535
+ // text in Flyouts, Animation color (subscription button)
+ #797979
+ // on-off switch (off status: border)
+ #DCDCDC
+ #606060
+ #C1C1C1
+ #959595
+ // LibreTube Logo, Hyperlinks and on-off switch (on status: filling) (also influence on the
+ navbar colour)
+ #161616
+ // on-off switch (on status: circle)
+ #4D4D4D
+ #A3A3A3
+ #A3A3A3
+ // Headline Text
+ #886A6A
+ // SponsorBlock marker
+ #4D4D4D
+ // NavBar Icon Container (selected)
+ #CCCCCC
+ // Navbar Icon Color (selected)
+ #4D4D4D
+ #A3A3A3
+ #4D4D4D
+ #A3A3A3
+ #4D4D4D
+ #4D4D4D
+ #A3A3A3
+ #A3A3A3
+ #161616
+ // Background (Settings and home)
+ #A3A3A3
+ #161616
+ // Navbar and Flyouts (uses also the "primary" color)
+ #BDBDBD
+ // NavBar Text (selected) and some Flyout Headlines
+ #4D4D4D
+ // on-off switch (off status: filling)
+ #A3A3A3
+ // text in Flyouts, Animation color (subscription button)
+ #A3A3A3
+ // on-off switch (off status: border)
+ #404040
+ #C3C3C3
+ #707070
+
+ #714AAA
+ #FFFFFF
+ #EDDCFF
+ #290055
+ #714AAA
+ #FFFFFF
+ #EDDCFF
+ #290055
+ #714AAA
+ #FFFFFF
+ #EDDCFF
+ #290055
+ #BA1A1A
+ #FFDAD6
+ #FFFFFF
+ #410002
+ #FFFBFF
+ #2B0052
+ #FFFBFF
+ #2B0052
+ #E8E0EB
+ #4A454E
+ #7B757F
+ #F9ECFF
+ #421A6C
+ #D7BAFF
+ #D7BAFF
+ #411478
+ #593090
+ #EDDCFF
+ #D7BAFF
+ #411478
+ #593090
+ #EDDCFF
+ #D7BAFF
+ #411478
+ #593090
+ #EDDCFF
+ #FFB4AB
+ #93000A
+ #690005
+ #FFDAD6
+ #2B0052
+ #EFDBFF
+ #2B0052
+ #EFDBFF
+ #4A454E
+ #CCC4CF
+ #958E99
+ #2B0052
+ #EFDBFF
+ #714AAA
+
+ // StackExchange
+ #FDFEFE
+ #373D41
+ #292d30
+ #FAFAFC
+ #E4AE8C
+ #FDFEFE
+ #32383C
+ #FCFCFC
+ #8AB98A
+ #DADFE0
+ #373D41
+ #DCDCDC
+ #FFB4AB
+ #93000A
+ #690005
+ #FFDAD6
+ #22282C
+ #F5F9F9
+ #383C3F
+ #F3F3F4
+ #79695e
+ #FEFEFE
+ #4C5053
+ #958E99
+ #2B0052
+ #EFDBFF
+ #714AAA
+ #FCFDFE
+ #7E8084
+ #729975
+ #d26e6d
\ No newline at end of file
diff --git a/Demo/app/src/main/res/values/dimens.xml b/Demo/app/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..4a1306d
--- /dev/null
+++ b/Demo/app/src/main/res/values/dimens.xml
@@ -0,0 +1,14 @@
+
+
+ 16sp
+ 18sp
+ 14sp
+ 12sp
+ 12sp
+ 11sp
+ 16dp
+ 12dp
+ 10dp
+ 60dp
+ 1dp
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/values/splash.xml b/Demo/app/src/main/res/values/splash.xml
new file mode 100644
index 0000000..730efe5
--- /dev/null
+++ b/Demo/app/src/main/res/values/splash.xml
@@ -0,0 +1,9 @@
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/values/strings.xml b/Demo/app/src/main/res/values/strings.xml
index aee84b4..6403d93 100644
--- a/Demo/app/src/main/res/values/strings.xml
+++ b/Demo/app/src/main/res/values/strings.xml
@@ -1,3 +1,134 @@
Demo
+ Current time: %1$s
+ Normal Button
+ Bordered Button
+
+ Hello blank fragment
+ Rounded Button
+ Disabled Button
+ Outlined Button
+ Text Button
+ Image Button
+ info
+ Gradient Button
+ Short Toast
+ Long toast
+ Success Toast
+ Error Toast
+ Start
+ Stop
+ Switch
+ Enabled
+ Disabled
+ Select known languages:
+ English
+ Hindi
+ Gujarati
+ Spanish
+ Save Changes
+ Select your house:
+ Gryffindor
+ Ravenclaw
+ Hufflepuff
+ Slytherin
+ Select your gender:
+ Add
+ Email
+ min 6 characters, at least one symbol and digit
+ Description
+ Normal Text Input Edit Text
+ Floating hint
+ Outlined text field
+ Password
+ Invalid email address
+ Clear
+ Short snack bar
+ Long snack bar
+ Multi Line\nsnack bar
+ Action snack bar
+ Anchor snack bar
+ Swipeable snack bar
+ Welcome to Home Fragment
+ Welcome to Chat Fragment
+ Welcome to Chat Fragment
+ Home
+ Chat
+ Calls
+ Compose Email
+ Tool Bar Normal
+ Profile
+ Tool Bar with navigation
+ Tool Bar with items
+ Search
+ Search Bar
+ Tool Bar Logo
+ Left Action
+ Insects are pancrustacean hexapod invertebrates of the class Insecta. They are the largest group within the arthropod phylum. Insects have a chitinous exoskeleton, a three-part body, three pairs of jointed legs, compound eyes and one pair of antennae. Insects is an international, peer-reviewed, open access journal of entomology published monthly online by MDPI.
+ Travel is the movement of people between distant geographical locations.
+ It doesn\'t hurt me (yeah, yeah, yo)\nDo you wanna feel how it feels? (Yeah, yeah, yo)\nDo you wanna know, know that it doesn\'t hurt me? (Yeah, yeah, yo)\nDo you wanna hear about the deal that I\'m making? (Yeah, yeah, yo)\nYou\nIt\'s you and me\nAnd if I only could\nI\'d make a deal with God\nAnd I\'d get Him to swap our places\nBe runnin\' up that road\nBe runnin\' up that hill\nBe runnin\' up that building\nSay, if I only could, oh\nYou don\'t wanna hurt me (yeah, yeah, yo)\nBut see how deep the bullet lies (yeah, yeah, yo)\nUnaware I\'m tearin\' you asunder (yeah, yeah, yo)\nOh, there is thunder in our hearts (yeah, yeah, yo)\nIs there so much hate for the ones we love? (Yeah, yeah, yo)\nOh, tell me, we both matter, don\'t we? (Yeah, yeah, yo)\nYou\nIt\'s you and me\nIt\'s you and me\nWon\'t be unhappy\nAnd if I only could\nI\'d make a deal with God\nAnd I\'d get Him to swap our places\nBe runnin\' up that road\nBe runnin\' up that hill\nBe runnin\' up that building (yo)\nSay, if I only could, oh\nYou (yeah, yeah, yo)\nIt\'s you and me\nIt\'s you and me\nWon\'t be unhappy (yeah, yeah, yo)\nOh, come on, baby (yeah)\nOh, come on, darlin\' (yo)\nLet me steal this moment from you now\nOh, come on, angel\nCome on, come on, darlin\'\nLet\'s exchange the experience (yo), oh, ooh, ooh\nAnd if I only could\nI\'d make a deal with God\nAnd I\'d get Him to swap our places\nI\'d be runnin\' up that road\nBe runnin\' up that hill\nWith no problems\nSay, if I only could\nI\'d make a deal with God\nAnd I\'d get Him to swap our places\nI\'d be runnin\' up that road\nBe runnin\' up that hill\nWith no problems\nSay, if I only could\nI\'d make a deal with God\nAnd I\'d get Him to swap our places\nI\'d be runnin\' up that road\nBe runnin\' up that hill\nWith no problems\nSay, if I only could\nI\'d be runnin\' up that hill\nWith no problems
+ βΊοΈ
+ π
+ π‘
+ π
+ π
+ π₯
+ π«
+ π
+ Toggle Emoji
+ After Barrier
+ Button 1
+ Button 2
+ Button 3
+ Button 4
+ Button 5
+ Button 6
+ 24 hour
+ %1$d:%2$d %3$s
+ Slider value: %1$.2f
+ Slider value: from %1$.2f to %2$.2f
+ Continues slider normal
+ Discrete slider
+ Range continues slider
+ Range discrete slider
+ Nothing selected
+ Normal drop-down
+ Bordered drop-down
+ Dialog drop-down
+ Underlined drop-down
+ Timezones
+ Exposed drop-down
+ Custom drop-down
+ Disabled drop-down
+ First name
+ Last name
+ This is Red and Green colored text.
+ This is Underlined and LineThrough text.
+ This is my Portfolio
+ You clicked: %1$s
+ Feed
+ My cards
+ Operations
+ See Details
+ Day
+ Week
+ Month
+ Year
+ Charges
+ Income
+ Mastercard logo
+ Recent
+ History
+ Select theme:
+ Accents
+ Resting red
+ Blissful blue
+ Yeeting yellow
+ Groovy green
+ Pleasurable purple
+ Material You
+ Versatile Violet
+ %1$s *%2$d
+ *** %1$d
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/values/styles.xml b/Demo/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..c72e140
--- /dev/null
+++ b/Demo/app/src/main/res/values/styles.xml
@@ -0,0 +1,142 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/app/src/main/res/values/themes.xml b/Demo/app/src/main/res/values/themes.xml
index e53585f..d540a60 100644
--- a/Demo/app/src/main/res/values/themes.xml
+++ b/Demo/app/src/main/res/values/themes.xml
@@ -6,11 +6,312 @@
- @color/purple_700
- @color/white
- - @color/teal_200
- - @color/teal_700
+ - #F44336
+ - #D47069
- @color/black
- ?attr/colorPrimaryVariant
+ - #CDCDCD
+ - @style/Widget.MaterialComponents.BottomSheet.DragHandle
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demo/gradle/wrapper/gradle-wrapper.properties b/Demo/gradle/wrapper/gradle-wrapper.properties
index adfcfb3..7f2a4f6 100644
--- a/Demo/gradle/wrapper/gradle-wrapper.properties
+++ b/Demo/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,5 @@
-#Mon Jun 05 16:09:56 IST 2023
+#Mon May 01 09:43:46 IST 2023
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
-zipStorePath=wrapper/dists