Aidan Follestad 6 年之前
父節點
當前提交
b31f6934e8

+ 4 - 4
core/src/main/java/com/afollestad/materialdialogs/checkbox/DialogCheckboxExt.kt

@@ -25,11 +25,10 @@ import androidx.core.widget.CompoundButtonCompat
 import com.afollestad.materialdialogs.MaterialDialog
 import com.afollestad.materialdialogs.R
 import com.afollestad.materialdialogs.assertOneSet
-import com.afollestad.materialdialogs.utils.MDUtil.ifNotZero
 import com.afollestad.materialdialogs.utils.MDUtil.maybeSetTextColor
 import com.afollestad.materialdialogs.utils.MDUtil.resolveString
 import com.afollestad.materialdialogs.utils.createColorSelector
-import com.afollestad.materialdialogs.utils.resolveColor
+import com.afollestad.materialdialogs.utils.resolveColors
 
 typealias BooleanCallback = ((Boolean) -> Unit)?
 
@@ -62,10 +61,11 @@ typealias BooleanCallback = ((Boolean) -> Unit)?
     maybeSetTextColor(windowContext, R.attr.md_color_content)
     bodyFont?.let { this.typeface = it }
 
-    resolveColor(attr = R.attr.md_color_widget).ifNotZero {
+    val widgetAttrs = intArrayOf(R.attr.md_color_widget, R.attr.md_color_widget_unchecked)
+    resolveColors(attrs = widgetAttrs).let {
       CompoundButtonCompat.setButtonTintList(
           this,
-          createColorSelector(checked = it)
+          createColorSelector(checked = it[0], unchecked = it[1])
       )
     }
   }

+ 7 - 5
core/src/main/java/com/afollestad/materialdialogs/internal/list/MultiChoiceDialogAdapter.kt

@@ -29,14 +29,13 @@ import com.afollestad.materialdialogs.actions.hasActionButtons
 import com.afollestad.materialdialogs.actions.setActionButtonEnabled
 import com.afollestad.materialdialogs.list.MultiChoiceListener
 import com.afollestad.materialdialogs.list.getItemSelector
-import com.afollestad.materialdialogs.utils.MDUtil.ifNotZero
 import com.afollestad.materialdialogs.utils.MDUtil.maybeSetTextColor
 import com.afollestad.materialdialogs.utils.appendAll
 import com.afollestad.materialdialogs.utils.createColorSelector
 import com.afollestad.materialdialogs.utils.inflate
 import com.afollestad.materialdialogs.utils.pullIndices
 import com.afollestad.materialdialogs.utils.removeAll
-import com.afollestad.materialdialogs.utils.resolveColor
+import com.afollestad.materialdialogs.utils.resolveColors
 
 /** @author Aidan Follestad (afollestad) */
 internal class MultiChoiceViewHolder(
@@ -128,13 +127,16 @@ internal class MultiChoiceDialogAdapter(
         adapter = this
     )
     viewHolder.titleView.maybeSetTextColor(dialog.windowContext, R.attr.md_color_content)
-    dialog.resolveColor(attr = R.attr.md_color_widget)
-        .ifNotZero {
+
+    val widgetAttrs = intArrayOf(R.attr.md_color_widget, R.attr.md_color_widget_unchecked)
+    dialog.resolveColors(attrs = widgetAttrs)
+        .let {
           CompoundButtonCompat.setButtonTintList(
               viewHolder.controlView,
-              dialog.createColorSelector(checked = it)
+              dialog.createColorSelector(checked = it[0], unchecked = it[1])
           )
         }
+
     return viewHolder
   }
 

+ 7 - 5
core/src/main/java/com/afollestad/materialdialogs/internal/list/SingleChoiceDialogAdapter.kt

@@ -29,11 +29,10 @@ import com.afollestad.materialdialogs.actions.hasActionButtons
 import com.afollestad.materialdialogs.actions.setActionButtonEnabled
 import com.afollestad.materialdialogs.list.SingleChoiceListener
 import com.afollestad.materialdialogs.list.getItemSelector
-import com.afollestad.materialdialogs.utils.MDUtil.ifNotZero
 import com.afollestad.materialdialogs.utils.MDUtil.maybeSetTextColor
 import com.afollestad.materialdialogs.utils.createColorSelector
 import com.afollestad.materialdialogs.utils.inflate
-import com.afollestad.materialdialogs.utils.resolveColor
+import com.afollestad.materialdialogs.utils.resolveColors
 
 /** @author Aidan Follestad (afollestad) */
 internal class SingleChoiceViewHolder(
@@ -107,13 +106,16 @@ internal class SingleChoiceDialogAdapter(
         adapter = this
     )
     viewHolder.titleView.maybeSetTextColor(dialog.windowContext, R.attr.md_color_content)
-    dialog.resolveColor(attr = R.attr.md_color_widget)
-        .ifNotZero {
+
+    val widgetAttrs = intArrayOf(R.attr.md_color_widget, R.attr.md_color_widget_unchecked)
+    dialog.resolveColors(attrs = widgetAttrs)
+        .let {
           CompoundButtonCompat.setButtonTintList(
               viewHolder.controlView,
-              dialog.createColorSelector(checked = it)
+              dialog.createColorSelector(checked = it[0], unchecked = it[1])
           )
         }
+
     return viewHolder
   }
 

+ 22 - 7
core/src/main/java/com/afollestad/materialdialogs/utils/ColorExt.kt

@@ -13,6 +13,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+@file:Suppress("NOTHING_TO_INLINE")
+
 package com.afollestad.materialdialogs.utils
 
 import android.content.res.ColorStateList
@@ -26,28 +28,41 @@ import androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP
 import com.afollestad.materialdialogs.MaterialDialog
 import com.afollestad.materialdialogs.R
 import com.afollestad.materialdialogs.utils.MDUtil.resolveColor
+import com.afollestad.materialdialogs.utils.MDUtil.resolveColors
 
 @ColorInt @CheckResult
-internal fun MaterialDialog.resolveColor(
+internal inline fun MaterialDialog.resolveColor(
   @ColorRes res: Int? = null,
   @AttrRes attr: Int? = null
 ): Int = resolveColor(windowContext, res, attr)
 
+@CheckResult
+internal inline fun MaterialDialog.resolveColors(
+  attrs: IntArray,
+  noinline fallback: ((forAttr: Int) -> Int)? = null
+): IntArray = resolveColors(windowContext, attrs, fallback)
+
 @ColorInt @CheckResult
-internal fun Int.adjustAlpha(alpha: Float): Int {
-  val newAlpha = (255 * alpha).toInt()
-  return Color.argb(newAlpha, Color.red(this), Color.green(this), Color.blue(this))
+internal inline fun Int.adjustAlpha(alpha: Float): Int {
+  return Color.argb((255 * alpha).toInt(), Color.red(this), Color.green(this), Color.blue(this))
 }
 
 @RestrictTo(LIBRARY_GROUP) internal fun MaterialDialog.createColorSelector(
-  @ColorInt unchecked: Int = resolveColor(windowContext, attr = R.attr.colorControlNormal),
-  @ColorInt checked: Int = resolveColor(windowContext, attr = R.attr.colorControlActivated)
+  @ColorInt unchecked: Int = 0,
+  @ColorInt checked: Int = 0
 ): ColorStateList {
   return ColorStateList(
       arrayOf(
           intArrayOf(-android.R.attr.state_checked),
           intArrayOf(android.R.attr.state_checked)
       ),
-      intArrayOf(unchecked, checked)
+      intArrayOf(
+          if (unchecked == 0) resolveColor(
+              windowContext, attr = R.attr.colorControlNormal
+          ) else unchecked,
+          if (checked == 0) resolveColor(
+              windowContext, attr = R.attr.colorControlActivated
+          ) else checked
+      )
   )
 }

+ 3 - 1
core/src/main/java/com/afollestad/materialdialogs/utils/DimensExt.kt

@@ -13,6 +13,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+@file:Suppress("NOTHING_TO_INLINE")
+
 package com.afollestad.materialdialogs.utils
 
 import android.util.TypedValue
@@ -42,6 +44,6 @@ internal fun MaterialDialog.dimen(
   }
 }
 
-internal fun View.dp(value: Int): Float {
+internal inline fun View.dp(value: Int): Float {
   return TypedValue.applyDimension(COMPLEX_UNIT_DIP, value.toFloat(), resources.displayMetrics)
 }

+ 35 - 13
core/src/main/java/com/afollestad/materialdialogs/utils/MDUtil.kt

@@ -13,6 +13,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+@file:Suppress("NOTHING_TO_INLINE")
+
 package com.afollestad.materialdialogs.utils
 
 import android.content.Context
@@ -39,19 +41,17 @@ import com.afollestad.materialdialogs.MaterialDialog
 @RestrictTo(LIBRARY_GROUP)
 object MDUtil {
 
-  @RestrictTo(LIBRARY_GROUP) fun resolveString(
+  @RestrictTo(LIBRARY_GROUP) inline fun resolveString(
     materialDialog: MaterialDialog,
     @StringRes res: Int? = null,
     @StringRes fallback: Int? = null,
     html: Boolean = false
-  ): CharSequence? {
-    return resolveString(
-        context = materialDialog.windowContext,
-        res = res,
-        fallback = fallback,
-        html = html
-    )
-  }
+  ): CharSequence? = resolveString(
+      context = materialDialog.windowContext,
+      res = res,
+      fallback = fallback,
+      html = html
+  )
 
   @RestrictTo(LIBRARY_GROUP) fun resolveString(
     context: Context,
@@ -91,8 +91,7 @@ object MDUtil {
     return ContextCompat.getDrawable(context, res)
   }
 
-  @RestrictTo(LIBRARY_GROUP)
-  @ColorInt
+  @RestrictTo(LIBRARY_GROUP) @ColorInt
   fun resolveColor(
     context: Context,
     @ColorRes res: Int? = null,
@@ -114,6 +113,28 @@ object MDUtil {
     return ContextCompat.getColor(context, res ?: 0)
   }
 
+  @RestrictTo(LIBRARY_GROUP)
+  fun resolveColors(
+    context: Context,
+    attrs: IntArray,
+    fallback: ((forAttr: Int) -> Int)? = null
+  ): IntArray {
+    val a = context.theme.obtainStyledAttributes(attrs)
+    try {
+      return (0 until attrs.size).map { index ->
+        val color = a.getColor(index, 0)
+        return@map if (color != 0) {
+          color
+        } else {
+          fallback?.invoke(attrs[index]) ?: 0
+        }
+      }
+          .toIntArray()
+    } finally {
+      a.recycle()
+    }
+  }
+
   @RestrictTo(LIBRARY_GROUP) fun resolveInt(
     context: Context,
     @AttrRes attr: Int,
@@ -136,11 +157,12 @@ object MDUtil {
     return darkness >= threshold
   }
 
-  @RestrictTo(LIBRARY_GROUP) fun <T : View> T.dimenPx(@DimenRes res: Int): Int {
+  @RestrictTo(LIBRARY_GROUP)
+  inline fun <T : View> T.dimenPx(@DimenRes res: Int): Int {
     return context.resources.getDimensionPixelSize(res)
   }
 
-  @RestrictTo(LIBRARY_GROUP) fun Context.isLandscape() =
+  @RestrictTo(LIBRARY_GROUP) inline fun Context.isLandscape() =
     resources.configuration.orientation == ORIENTATION_LANDSCAPE
 
   @RestrictTo(LIBRARY_GROUP) fun EditText.textChanged(callback: (CharSequence) -> Unit) {

+ 4 - 3
core/src/main/java/com/afollestad/materialdialogs/utils/StringExt.kt

@@ -13,12 +13,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+@file:Suppress("NOTHING_TO_INLINE")
+
 package com.afollestad.materialdialogs.utils
 
 import androidx.annotation.ArrayRes
 import com.afollestad.materialdialogs.MaterialDialog
 
-internal fun MaterialDialog.getStringArray(@ArrayRes res: Int?): Array<String>? {
-  if (res == null) return emptyArray()
-  return windowContext.resources.getStringArray(res)
+internal inline fun MaterialDialog.getStringArray(@ArrayRes res: Int?): Array<String>? {
+  return if (res != null) return windowContext.resources.getStringArray(res) else emptyArray()
 }

+ 8 - 7
core/src/main/java/com/afollestad/materialdialogs/utils/ViewExt.kt

@@ -13,6 +13,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+@file:Suppress("NOTHING_TO_INLINE")
+
 package com.afollestad.materialdialogs.utils
 
 import android.content.Context
@@ -29,19 +31,19 @@ import androidx.annotation.LayoutRes
 import com.afollestad.materialdialogs.MaterialDialog
 
 @Suppress("UNCHECKED_CAST")
-internal fun <R : View> ViewGroup.inflate(
+internal inline fun <R : View> ViewGroup.inflate(
   ctxt: Context = context,
   @LayoutRes res: Int
 ) = LayoutInflater.from(ctxt).inflate(res, this, false) as R
 
 @Suppress("UNCHECKED_CAST")
-internal fun <T> MaterialDialog.inflate(
+internal inline fun <T> MaterialDialog.inflate(
   @LayoutRes res: Int,
   root: ViewGroup? = null
 ) = LayoutInflater.from(windowContext).inflate(res, root, false) as T
 
 @Suppress("UNCHECKED_CAST")
-internal fun <T> ViewGroup.inflate(
+internal inline fun <T> ViewGroup.inflate(
   @LayoutRes res: Int,
   root: ViewGroup? = this
 ) = LayoutInflater.from(context).inflate(res, root, false) as T
@@ -82,13 +84,12 @@ internal fun <T : View> T.isVisible(): Boolean {
   }
 }
 
-internal fun <T : View> T.isNotVisible(): Boolean {
+internal inline fun <T : View> T.isNotVisible(): Boolean {
   return !isVisible()
 }
 
-internal fun <T : View> T.isRtl(): Boolean {
-  if (SDK_INT < JELLY_BEAN_MR1) return false
-  return resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_RTL
+internal inline fun <T : View> T.isRtl(): Boolean {
+  return if (SDK_INT < JELLY_BEAN_MR1) false else resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_RTL
 }
 
 internal fun TextView.setGravityStartCompat() {

+ 1 - 0
core/src/main/res-public/values/public.xml

@@ -5,6 +5,7 @@
   <attr format="color" name="md_ripple_color"/>
   <attr format="color" name="md_color_button_text"/>
   <attr format="color" name="md_color_widget"/>
+  <attr format="color" name="md_color_widget_unchecked"/>
   <attr format="dimension" name="md_corner_radius"/>
   <attr format="reference" name="md_font_title"/>
   <attr format="reference" name="md_font_body"/>

+ 7 - 3
documentation/CORE.md

@@ -589,14 +589,18 @@ See the "Custom Theme" example in the sample project (open the overflow menu for
 
 ### Widget Color
 
-By default, widgets like CheckBoxes and RadioButtons use your theme's accent color. You can 
-override that to use whatever color you want. This applies to checkbox prompts, single and multiple 
-choice lists, etc. but will not automatically apply to widgets in your own custom views.
+By default, widgets like CheckBoxes and RadioButtons use your theme's accent color when they are 
+checked. You can override that to use whatever color you want. This applies to checkbox prompts, 
+single and multiple choice lists, etc. but will not automatically apply to widgets in your own 
+custom views.
 
 ```xml
 <style name="AppTheme.Custom" parent="Theme.AppCompat">
 
   <item name="md_widget_color">@color/your_color</item>
+  
+  <!-- Generally this should be avoided, checkboxes should be white or gray when unchecked -->
+  <item name="md_widget_color_unchecked">@color/your_color</item>
     
 </style>
 ```

+ 3 - 0
sample/src/main/res/values/styles.xml

@@ -27,7 +27,10 @@
     <item name="md_font_button">@font/raleway_semibold</item>
     <item name="md_ripple_color">@color/primary_custom_translucent</item>
     <item name="md_color_button_text">@color/accent_custom</item>
+
     <item name="md_color_widget">#00CC00</item>
+    <item name="md_color_widget_unchecked">#CC0000</item>
+
   </style>
 
   <style name="SampleHeader" tools:ignore="NewApi">