{"record":{"id":"bcc4466155a63fcb","repo":"material-components/material-components-android","slug":"icongravity-cannot-have-the-same-alignment-as-seco","errorCode":null,"errorMessage":"iconGravity cannot have the same alignment as secondaryIconGravity","messagePattern":"iconGravity cannot have the same alignment as secondaryIconGravity","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"lib/java/com/google/android/material/button/MaterialButton.java","lineNumber":1258,"sourceCode":"    boolean hasIconChanged =\n        (isIconStart() && drawableStart != icon)\n            || (isIconEnd() && drawableEnd != icon)\n            || (isIconTop() && drawableTop != icon);\n    // Force icon update if needsIconReset otherwise updated it only if icon has changed.\n    if (needsIconReset || hasIconChanged) {\n      if (isIconStart()) {\n        setCompoundDrawablesRelative(icon, getUpdatedIconFor(1), getUpdatedIconFor(2), null);\n      } else if (isIconEnd()) {\n        setCompoundDrawablesRelative(getUpdatedIconFor(0), getUpdatedIconFor(1), icon, null);\n      } else if (isIconTop()) {\n        setCompoundDrawablesRelative(getUpdatedIconFor(0), icon, getUpdatedIconFor(2), null);\n      }\n    }\n  }\n\n  private void validateIconGravity() {\n    if (icon != null && secondaryIcon != null && areIconsGravitySameAlignment()) {\n      throw new IllegalArgumentException(\n          \"iconGravity cannot have the same alignment as secondaryIconGravity\");\n    }\n  }\n\n  private boolean areIconsGravitySameAlignment() {\n    return (isIconStart() && isSecondaryIconStart())\n        || (isIconEnd() && isSecondaryIconEnd())\n        || (isIconTop() && isSecondaryIconTop());\n  }\n\n  @Nullable\n  private Drawable getUpdatedIconFor(int position) {\n    switch (position) {\n      case 0: // start\n        return (secondaryIcon != null && isSecondaryIconStart()) ? secondaryIcon : null;\n      case 1: // top\n        return (secondaryIcon != null && isSecondaryIconTop()) ? secondaryIcon : null;\n      case 2: // end","sourceCodeStart":1240,"sourceCodeEnd":1276,"githubUrl":"https://github.com/material-components/material-components-android/blob/ac7e18efeefb331850c561faf9ab8bf81d27ba68/lib/java/com/google/android/material/button/MaterialButton.java#L1240-L1276","documentation":"MaterialButton supports an optional secondary icon (e.g. for dropdown/chevron usage). The primary iconGravity and secondaryIconGravity must not resolve to the same alignment (start/end/top) when both icons are set, otherwise the two drawables would be stacked in the same compound-drawable slot. validateIconGravity enforces this with IllegalArgumentException whenever both icons exist and areIconsGravitySameAlignment() is true.","triggerScenarios":"Setting both icon and secondaryIcon on the same MaterialButton with app:iconGravity and app:secondaryIconGravity both resolving to start, end, or top; changing gravity attributes in XML or calling the gravity setters so both align identically.","commonSituations":"Adding a secondary icon (e.g. a chevron) to an existing button that already has iconGravity=\"start\" and copying the same value for secondaryIconGravity; configuring gravity from a shared style/theme so both attributes inherit the same alignment; programmatically toggling gravities at runtime without keeping them distinct.","solutions":["Give the two gravities different alignments, e.g. iconGravity=\"start\" with secondaryIconGravity=\"end\" (the typical icon + chevron pattern).","If only one icon is needed, remove the secondary icon (unset app:secondaryIcon / secondaryIcon null) so validation passes regardless of gravity values.","When setting gravities programmatically, keep a mapping/constant pair that is guaranteed distinct."],"exampleFix":"<!-- before -->\n<com.google.android.material.button.MaterialButton\n    app:icon=\"@drawable/ic_send\"\n    app:iconGravity=\"start\"\n    app:secondaryIcon=\"@drawable/ic_chevron_down\"\n    app:secondaryIconGravity=\"start\" ... /> <!-- throws -->\n\n<!-- after -->\n<com.google.android.material.button.MaterialButton\n    app:icon=\"@drawable/ic_send\"\n    app:iconGravity=\"start\"\n    app:secondaryIcon=\"@drawable/ic_chevron_down\"\n    app:secondaryIconGravity=\"end\" ... />","handlingStrategy":"validation","validationCode":"// Ensure the gravities differ whenever both icons are present\nif (icon != null && secondaryIcon != null) {\n  android.util.Log.d(TAG, \"primary=\" + iconGravity + \" secondary=\" + secondaryIconGravity);\n  // require: not (start&start), (end&end), or (top&top)\n}","typeGuard":"private static boolean gravitiesConflict(int primaryGravity, int secondaryGravity) {\n  return primaryGravity == secondaryGravity; // same start/end/top alignment\n}\n// usage: if (!gravitiesConflict(iconGravity, secondaryIconGravity)) button.setSecondaryIcon(chevron);","tryCatchPattern":null,"preventionTips":["Use distinct alignments (e.g. primary=start, secondary=end) in shared styles.","Only set a secondary icon when the gravity attributes are guaranteed different."],"tags":["material-button","icon","illegal-argument","xml-configuration"],"backgroundTag":null,"analyzedSha":"ac7e18efeefb331850c561faf9ab8bf81d27ba68","analyzedAt":"2026-08-14T15:35:35.735Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}