Skip to content

Commit

Permalink
Merge pull request #157 from natura-cosmeticos/DSY-999-tag
Browse files Browse the repository at this point in the history
[DSY-999] create tag component and add it to sample
  • Loading branch information
mlcsouza authored Sep 21, 2020
2 parents 7ee1ee4 + 919f907 commit 1fc47f2
Show file tree
Hide file tree
Showing 19 changed files with 587 additions and 0 deletions.
153 changes: 153 additions & 0 deletions designsystem/src/main/kotlin/com/natura/android/tag/Tag.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
package com.natura.android.tag

import android.content.Context
import android.content.res.TypedArray
import android.util.AttributeSet
import android.view.View
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat
import androidx.core.content.res.getIntOrThrow
import androidx.core.content.res.getResourceIdOrThrow
import androidx.core.content.res.getStringOrThrow
import androidx.core.graphics.drawable.DrawableCompat
import com.natura.android.R
import com.natura.android.exceptions.MissingThemeException
import com.natura.android.extensions.setAppearance

class Tag @JvmOverloads constructor(
context: Context,
private val attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : ConstraintLayout(context, attrs, defStyleAttr) {

private var labelAttribute: String? = null
private var typeAttribute: Int? = null
private var backgroundColorResourceAttribute = 0
private var labelTextAppearanceResourceAttribute = 0
private var labelTextColorResourceAttribute = 0
private var tagAttributesArray: TypedArray

private val labelContainer by lazy { findViewById<TextView>(R.id.tagLabel) }
private val backgroundContainer by lazy { findViewById<View>(R.id.tagBackground) }

init {
try {
View.inflate(context, R.layout.ds_tag, this)
} catch (e: Exception) {
throw (MissingThemeException())
}

tagAttributesArray = context.obtainStyledAttributes(attrs, R.styleable.Tag)

getTagAttributes()
getAttributesFromTheme()
configureTagByType(typeAttribute)

tagAttributesArray.recycle()
}

fun setLabel(text: String?) {
labelContainer.text = text
labelContainer.setAppearance(labelTextAppearanceResourceAttribute)
setTextColor()
invalidate()
requestLayout()
}

fun getLabel(): CharSequence? {
return labelContainer.text
}

fun getType(): Int? = typeAttribute

private fun configureTagByType(type: Int?) {
type?.apply {
setLabel(labelAttribute)
setTextColor()
setBackground()
}
}

private fun setTextColor() {
labelContainer.setTextColor(ContextCompat.getColor(context, labelTextColorResourceAttribute))
}

private fun setBackground() {
val background = resources.getDrawable(R.drawable.tag_background, null)
val backgroundWrap = DrawableCompat.wrap(background).mutate()
DrawableCompat.setTint(backgroundWrap, ContextCompat.getColor(context, backgroundColorResourceAttribute))

backgroundContainer.background = background
}

private fun getAttributesFromTheme() {
try {
if (typeAttribute == PRIMARY) {
setPrimaryTypeAttributes()
} else {
setAlertTypeAttributes()
}
} catch (e: Exception) {
throw (MissingThemeException())
}
}

private fun setPrimaryTypeAttributes() {
context
.theme
.obtainStyledAttributes(
attrs,
R.styleable.Tag,
R.attr.tagPrimary,
0
)
.apply {
backgroundColorResourceAttribute = this.getResourceIdOrThrow(R.styleable.Tag_colorBackground)
labelTextAppearanceResourceAttribute = this.getResourceIdOrThrow(R.styleable.Tag_labelAppearance)
labelTextColorResourceAttribute = this.getResourceIdOrThrow(R.styleable.Tag_android_textColor)
}
}

private fun setAlertTypeAttributes() {
context
.theme
.obtainStyledAttributes(
attrs,
R.styleable.Tag,
R.attr.tagAlert,
0
)
.apply {
backgroundColorResourceAttribute = this.getResourceIdOrThrow(R.styleable.Tag_colorBackground)
labelTextAppearanceResourceAttribute = this.getResourceIdOrThrow(R.styleable.Tag_labelAppearance)
labelTextColorResourceAttribute = this.getResourceIdOrThrow(R.styleable.Tag_android_textColor)
}
}

private fun getTagAttributes() {
getLabelAttribute()
getTypeAttribute()
}

private fun getTypeAttribute() {
try {
typeAttribute = tagAttributesArray.getIntOrThrow(R.styleable.Tag_tag_type)
} catch (e: Exception) {
throw (IllegalArgumentException("⚠️ ⚠️ Missing tag required argument. You MUST set the tag type(primary or alert).", e))
}
}

private fun getLabelAttribute() {
try {
labelAttribute = tagAttributesArray.getStringOrThrow(R.styleable.Tag_textLabel)
} catch (e: Exception) {
throw (IllegalArgumentException("⚠️ ⚠️ Missing tag required argument. You MUST set the tag label(string).", e))
}
}

companion object {
const val PRIMARY = 0
const val ALERT = 1
}
}
6 changes: 6 additions & 0 deletions designsystem/src/main/res/drawable/tag_background.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="50dp"/>
<solid android:color="?colorAlert"/>
</shape>
29 changes: 29 additions & 0 deletions designsystem/src/main/res/layout/ds_tag.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">

<View
android:id="@+id/tagBackground"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="@+id/tagLabel"
app:layout_constraintStart_toStartOf="@+id/tagLabel"
app:layout_constraintEnd_toEndOf="@+id/tagLabel"
app:layout_constraintBottom_toBottomOf="@+id/tagLabel"
android:background="@drawable/tag_background"/>

<TextView
android:id="@+id/tagLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="?spacingTiny"
android:paddingEnd="?spacingTiny"
android:textAppearance="?textAppearanceCaption"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:text="tag example"/>

</androidx.constraintlayout.widget.ConstraintLayout>
11 changes: 11 additions & 0 deletions designsystem/src/main/res/values/ds_attrs.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="Tag" >
<attr name="tag_type" format="enum">
<enum name="primary" value="0"/>
<enum name="alert" value="1"/>
</attr>
<attr name="colorBackground"/>
<attr name="labelAppearance"/>
<attr name="textLabel"/>
<attr name="android:textColor"/>
</declare-styleable>

<declare-styleable name="Shortcut" >
<attr name="type" format="enum">
<enum name="outlined" value="0"/>
Expand Down
4 changes: 4 additions & 0 deletions designsystem/src/main/res/values/ds_base_attrs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 +130,8 @@
<!-- Shortcut references -->
<attr name="shortcutOutlined" format="reference"/>
<attr name="shortcutContained" format="reference"/>

<!-- Tag references -->
<attr name="tagPrimary" format="reference"/>
<attr name="tagAlert" format="reference"/>
</resources>
6 changes: 6 additions & 0 deletions designsystem/src/main/res/values/ds_base_themes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,9 @@

<item name="shortcutContained">@style/Widget.DS.Shortcut.Contained</item>
<item name="shortcutOutlined">@style/Widget.DS.Shortcut.Outlined</item>

<item name="tagPrimary">@style/Widget.DS.Tag.Primary</item>
<item name="tagAlert">@style/Widget.DS.Tag.Alert</item>
</style>

<style name="Theme.DsBaseDark" parent="Theme.MaterialComponents.DayNight">
Expand Down Expand Up @@ -275,5 +278,8 @@

<item name="shortcutContained">@style/Widget.DS.Shortcut.Contained</item>
<item name="shortcutOutlined">@style/Widget.DS.Shortcut.Outlined</item>

<item name="tagPrimary">@style/Widget.DS.Tag.Primary</item>
<item name="tagAlert">@style/Widget.DS.Tag.Alert</item>
</style>
</resources>
15 changes: 15 additions & 0 deletions designsystem/src/main/res/values/styles.xml
Original file line number Diff line number Diff line change
Expand Up @@ -322,5 +322,20 @@
<item name="labelAppearance">?textAppearanceCaption</item>
</style>

<!-- TAG STYLES -->
<style name="Widget.DS.Tag.Primary" parent="Widget.DS.Tag">
<item name="colorBackground">?colorPrimary</item>
<item name="android:textColor">?colorOnPrimary</item>
</style>

<style name="Widget.DS.Tag.Alert" parent="Widget.DS.Tag">
<item name="colorBackground">?colorAlert</item>
<item name="android:textColor">?colorOnAlert</item>
</style>

<style name="Widget.DS.Tag">
<item name="labelAppearance">?textAppearanceCaption</item>
</style>

<style name="Widget.DS"/>
</resources>
61 changes: 61 additions & 0 deletions designsystem/src/test/kotlin/com/natura/android/tag/TagFixture.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.natura.android.tag

import android.content.Context
import androidx.test.core.app.ApplicationProvider
import com.natura.android.R
import org.robolectric.Robolectric

internal class TagFixture private constructor(
private var type: Int? = null,
private var label: String? = null,
private var context: Context = ApplicationProvider.getApplicationContext()
) {

companion object {
private const val PRIMARY = 0
private const val ALERT = 1

private const val defaultType = PRIMARY
private const val defaultLabel = "tag label"
private var context = ApplicationProvider.getApplicationContext<Context>()

fun aTag(): TagFixture {
context.setTheme(R.style.Theme_Natura)
return TagFixture(defaultType, defaultLabel, context)
}

fun aEmptyTag(): TagFixture {
return TagFixture()
}
}

fun withTypePrimary(): TagFixture {
this.type = PRIMARY
return this
}

fun withTypeAlert(): TagFixture {
this.type = ALERT
return this
}

fun withLabel(label: String): TagFixture {
this.label = label
return this
}

fun withContext(customContext: Context): TagFixture {
this.context = customContext
return this
}

fun build(): Tag {
val attributes = Robolectric
.buildAttributeSet()
.addAttribute(R.attr.tag_type, type.toString())
.addAttribute(R.attr.textLabel, label)
.build()

return Tag(context, attributes)
}
}
Loading

0 comments on commit 1fc47f2

Please sign in to comment.