1/* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package androidx.core.content.res 18 19import android.content.res.ColorStateList 20import android.content.res.TypedArray 21import android.graphics.Typeface 22import android.graphics.drawable.Drawable 23import androidx.annotation.AnyRes 24import androidx.annotation.ColorInt 25import androidx.annotation.Dimension 26import androidx.annotation.RequiresApi 27import androidx.annotation.StyleableRes 28 29private fun TypedArray.checkAttribute(@StyleableRes index: Int) { 30 if (!hasValue(index)) { 31 throw IllegalArgumentException("Attribute not defined in set.") 32 } 33} 34 35/** 36 * Retrieve the boolean value for the attribute at [index] or throws [IllegalArgumentException] 37 * if not defined. 38 * 39 * @see TypedArray.hasValue 40 * @see TypedArray.getBoolean 41 */ 42fun TypedArray.getBooleanOrThrow(@StyleableRes index: Int): Boolean { 43 checkAttribute(index) 44 return getBoolean(index, false) 45} 46 47/** 48 * Retrieve the color value for the attribute at [index] or throws [IllegalArgumentException] 49 * if not defined. 50 * 51 * @see TypedArray.hasValue 52 * @see TypedArray.getColor 53 */ 54@ColorInt 55fun TypedArray.getColorOrThrow(@StyleableRes index: Int): Int { 56 checkAttribute(index) 57 return getColor(index, 0) 58} 59 60/** 61 * Retrieve the color state list value for the attribute at [index] or throws 62 * [IllegalArgumentException] if not defined. 63 * 64 * @see TypedArray.hasValue 65 * @see TypedArray.getColorStateList 66 */ 67fun TypedArray.getColorStateListOrThrow(@StyleableRes index: Int): ColorStateList { 68 checkAttribute(index) 69 return checkNotNull(getColorStateList(index)) { 70 "Attribute value was not a color or color state list." 71 } 72} 73 74/** 75 * Retrieve the dimension value for the attribute at [index] or throws [IllegalArgumentException] 76 * if not defined. 77 * 78 * @see TypedArray.hasValue 79 * @see TypedArray.getDimension 80 */ 81fun TypedArray.getDimensionOrThrow(@StyleableRes index: Int): Float { 82 checkAttribute(index) 83 return getDimension(index, 0f) 84} 85 86/** 87 * Retrieve the dimension pixel offset value for the attribute at [index] or throws 88 * [IllegalArgumentException] if not defined. 89 * 90 * @see TypedArray.hasValue 91 * @see TypedArray.getDimensionPixelOffset 92 */ 93@Dimension 94fun TypedArray.getDimensionPixelOffsetOrThrow(@StyleableRes index: Int): Int { 95 checkAttribute(index) 96 return getDimensionPixelOffset(index, 0) 97} 98 99/** 100 * Retrieve the dimension pixel size value for the attribute at [index] or throws 101 * [IllegalArgumentException] if not defined. 102 * 103 * @see TypedArray.hasValue 104 * @see TypedArray.getDimensionPixelSize 105 */ 106@Dimension 107fun TypedArray.getDimensionPixelSizeOrThrow(@StyleableRes index: Int): Int { 108 checkAttribute(index) 109 return getDimensionPixelSize(index, 0) 110} 111 112/** 113 * Retrieve the drawable value for the attribute at [index] or throws [IllegalArgumentException] 114 * if not defined. 115 * 116 * @see TypedArray.hasValue 117 * @see TypedArray.getDrawable 118 */ 119fun TypedArray.getDrawableOrThrow(@StyleableRes index: Int): Drawable { 120 checkAttribute(index) 121 return getDrawable(index) 122} 123 124/** 125 * Retrieve the float value for the attribute at [index] or throws [IllegalArgumentException] 126 * if not defined. 127 * 128 * @see TypedArray.hasValue 129 * @see TypedArray.getFloat 130 */ 131fun TypedArray.getFloatOrThrow(@StyleableRes index: Int): Float { 132 checkAttribute(index) 133 return getFloat(index, 0f) 134} 135 136/** 137 * Retrieve the font value for the attribute at [index] or throws [IllegalArgumentException] 138 * if not defined. 139 * 140 * @see TypedArray.hasValue 141 * @see TypedArray.getFont 142 */ 143@RequiresApi(26) 144fun TypedArray.getFontOrThrow(@StyleableRes index: Int): Typeface { 145 checkAttribute(index) 146 return getFont(index) 147} 148 149/** 150 * Retrieve the integer value for the attribute at [index] or throws [IllegalArgumentException] 151 * if not defined. 152 * 153 * @see TypedArray.hasValue 154 * @see TypedArray.getInt 155 */ 156fun TypedArray.getIntOrThrow(@StyleableRes index: Int): Int { 157 checkAttribute(index) 158 return getInt(index, 0) 159} 160 161/** 162 * Retrieve the integer value for the attribute at [index] or throws [IllegalArgumentException] 163 * if not defined. 164 * 165 * @see TypedArray.hasValue 166 * @see TypedArray.getInteger 167 */ 168fun TypedArray.getIntegerOrThrow(@StyleableRes index: Int): Int { 169 checkAttribute(index) 170 return getInteger(index, 0) 171} 172 173/** 174 * Retrieves the resource identifier for the attribute at [index] or throws 175 * [IllegalArgumentException] if not defined. 176 * 177 * @see TypedArray.hasValue 178 * @see TypedArray.getResourceId 179 */ 180@AnyRes 181fun TypedArray.getResourceIdOrThrow(@StyleableRes index: Int): Int { 182 checkAttribute(index) 183 return getResourceId(index, 0) 184} 185 186/** 187 * Retrieve the string value for the attribute at [index] or throws [IllegalArgumentException] 188 * if not defined. 189 * 190 * @see TypedArray.hasValue 191 * @see TypedArray.getString 192 */ 193fun TypedArray.getStringOrThrow(@StyleableRes index: Int): String { 194 checkAttribute(index) 195 return checkNotNull(getString(index)) { 196 "Attribute value could not be coerced to String." 197 } 198} 199 200/** 201 * Retrieve the text value for the attribute at [index] or throws [IllegalArgumentException] 202 * if not defined. 203 * 204 * @see TypedArray.hasValue 205 * @see TypedArray.getText 206 */ 207fun TypedArray.getTextOrThrow(@StyleableRes index: Int): CharSequence { 208 checkAttribute(index) 209 return checkNotNull(getText(index)) { 210 "Attribute value could not be coerced to CharSequence." 211 } 212} 213 214/** 215 * Retrieve the text array value for the attribute at [index] or throws 216 * [IllegalArgumentException] if not defined. 217 * 218 * @see TypedArray.hasValue 219 * @see TypedArray.getTextArray 220 */ 221fun TypedArray.getTextArrayOrThrow(@StyleableRes index: Int): Array<CharSequence> { 222 checkAttribute(index) 223 return getTextArray(index) 224} 225 226/** 227 * Executes the given [block] function on this TypedArray and then recycles it. 228 * 229 * @see kotlin.io.use 230 */ 231inline fun <R> TypedArray.use(block: (TypedArray) -> R): R { 232 return block(this).also { 233 recycle() 234 } 235} 236