Twelve: ListItem: Add support for leading and trailing custom views

Change-Id: If3865ab341a6e7da01ec74d4f72cb4fa666b2adc
diff --git a/app/src/main/java/org/lineageos/twelve/ui/views/ListItem.kt b/app/src/main/java/org/lineageos/twelve/ui/views/ListItem.kt
index 86cb4a7..f485c0d 100644
--- a/app/src/main/java/org/lineageos/twelve/ui/views/ListItem.kt
+++ b/app/src/main/java/org/lineageos/twelve/ui/views/ListItem.kt
@@ -11,10 +11,13 @@
 import android.graphics.drawable.Icon
 import android.net.Uri
 import android.util.AttributeSet
+import android.view.LayoutInflater
+import android.view.View
 import android.widget.FrameLayout
 import android.widget.ImageView
 import android.widget.TextView
 import androidx.annotation.DrawableRes
+import androidx.annotation.LayoutRes
 import androidx.annotation.StringRes
 import androidx.core.view.isVisible
 import org.lineageos.twelve.R
@@ -29,9 +32,11 @@
     private val headlineTextView by lazy { findViewById<TextView>(R.id.headlineTextView) }
     private val leadingIconImageView by lazy { findViewById<ImageView>(R.id.leadingIconImageView) }
     private val leadingTextView by lazy { findViewById<TextView>(R.id.leadingTextView) }
+    private val leadingViewContainerFrameLayout by lazy { findViewById<FrameLayout>(R.id.leadingViewContainerFrameLayout) }
     private val supportingTextView by lazy { findViewById<TextView>(R.id.supportingTextView) }
     private val trailingIconImageView by lazy { findViewById<ImageView>(R.id.trailingIconImageView) }
     private val trailingSupportingTextView by lazy { findViewById<TextView>(R.id.trailingSupportingTextView) }
+    private val trailingViewContainerFrameLayout by lazy { findViewById<FrameLayout>(R.id.trailingViewContainerFrameLayout) }
 
     var leadingIconImage: Drawable?
         get() = leadingIconImageView.drawable
@@ -45,6 +50,12 @@
             leadingTextView.setTextAndUpdateVisibility(value)
         }
 
+    var leadingView: View?
+        get() = leadingViewContainerFrameLayout.getChildAt(0)
+        set(value) {
+            leadingViewContainerFrameLayout.setChildAndUpdateVisibility(value)
+        }
+
     var headlineText: CharSequence?
         get() = headlineTextView.text
         set(value) {
@@ -69,6 +80,12 @@
             trailingSupportingTextView.setTextAndUpdateVisibility(value)
         }
 
+    var trailingView: View?
+        get() = trailingViewContainerFrameLayout.getChildAt(0)
+        set(value) {
+            trailingViewContainerFrameLayout.setChildAndUpdateVisibility(value)
+        }
+
     init {
         inflate(context, R.layout.list_item, this)
 
@@ -76,10 +93,20 @@
             try {
                 leadingIconImage = getDrawable(R.styleable.ListItem_leadingIconImage)
                 leadingText = getString(R.styleable.ListItem_leadingText)
+                getResourceId(R.styleable.ListItem_leadingViewLayout, 0).takeUnless {
+                    it == 0
+                }?.let {
+                    setLeadingView(it)
+                }
                 headlineText = getString(R.styleable.ListItem_headlineText)
                 supportingText = getString(R.styleable.ListItem_supportingText)
                 trailingIconImage = getDrawable(R.styleable.ListItem_trailingIconImage)
                 trailingSupportingText = getString(R.styleable.ListItem_trailingSupportingText)
+                getResourceId(R.styleable.ListItem_trailingViewLayout, 0).takeUnless {
+                    it == 0
+                }?.let {
+                    setTrailingView(it)
+                }
             } finally {
                 recycle()
             }
@@ -101,6 +128,9 @@
     fun setLeadingText(@StringRes resId: Int, vararg formatArgs: Any) =
         leadingTextView.setTextAndUpdateVisibility(resId, *formatArgs)
 
+    fun setLeadingView(@LayoutRes resId: Int) =
+        leadingViewContainerFrameLayout.setChildAndUpdateVisibility(resId)
+
     fun setSupportingText(@StringRes resId: Int) =
         supportingTextView.setTextAndUpdateVisibility(resId)
 
@@ -120,6 +150,27 @@
     fun setTrailingSupportingText(@StringRes resId: Int, vararg formatArgs: Any) =
         trailingSupportingTextView.setTextAndUpdateVisibility(resId, *formatArgs)
 
+    fun setTrailingView(@LayoutRes resId: Int) =
+        trailingViewContainerFrameLayout.setChildAndUpdateVisibility(resId)
+
+    // FrameLayout utils
+
+    private fun FrameLayout.updateVisibility(isVisible: Boolean) {
+        this.isVisible = isVisible && childCount > 0
+    }
+
+    private fun FrameLayout.setChildAndUpdateVisibility(child: View?) {
+        removeAllViews()
+        child?.let {
+            addView(it)
+        }
+        updateVisibility(true)
+    }
+
+    private fun FrameLayout.setChildAndUpdateVisibility(@LayoutRes resId: Int) {
+        setChildAndUpdateVisibility(LayoutInflater.from(context).inflate(resId, this, false))
+    }
+
     // ImageView utils
 
     private fun ImageView.setImageAndUpdateVisibility(bm: Bitmap) {
diff --git a/app/src/main/res/layout/list_item.xml b/app/src/main/res/layout/list_item.xml
index a971960..21fbc59 100644
--- a/app/src/main/res/layout/list_item.xml
+++ b/app/src/main/res/layout/list_item.xml
@@ -15,6 +15,13 @@
     android:paddingHorizontal="16dp"
     android:paddingVertical="12dp">
 
+    <FrameLayout
+        android:id="@+id/leadingViewContainerFrameLayout"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginEnd="16dp"
+        android:visibility="gone" />
+
     <ImageView
         android:id="@+id/leadingIconImageView"
         android:layout_width="wrap_content"
@@ -90,4 +97,10 @@
         tools:src="@android:drawable/star_on"
         tools:visibility="visible" />
 
+    <FrameLayout
+        android:id="@+id/trailingViewContainerFrameLayout"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:visibility="gone" />
+
 </LinearLayout>
diff --git a/app/src/main/res/values/attrs_ListItem.xml b/app/src/main/res/values/attrs_ListItem.xml
index 85df37b..c2a729a 100644
--- a/app/src/main/res/values/attrs_ListItem.xml
+++ b/app/src/main/res/values/attrs_ListItem.xml
@@ -8,8 +8,10 @@
         <attr name="headlineText" format="string" />
         <attr name="leadingIconImage" format="reference" />
         <attr name="leadingText" format="string" />
+        <attr name="leadingViewLayout" format="reference" />
         <attr name="supportingText" format="string" />
         <attr name="trailingIconImage" format="reference" />
         <attr name="trailingSupportingText" format="string" />
+        <attr name="trailingViewLayout" format="reference" />
     </declare-styleable>
 </resources>