ShapeableImageView

Ken Baldauf

Software Engineer @ Acorns

What is it?

  • ImageView that draws bitmap with provided shape
  • Added in v1.2.0 of material design library
  • Behind the scenes 
    • Backed by a ShapeAppearanceModel
      • Used by MaterialShapeDrawable to draw itself
  • Controlled by two attributes
    • cornerSize
    • cornerFamily

cornerSize

  • Radius of the corner
  • Define via
    • Pixel measurement
    • Percentage
  • Can be set on a wholesale or corner by corner basis
    • cornerSize
    • cornerSizeTopLeft
    • cornerSizeTopRight
    • cornerSizeBottomRight
    • cornerSizeBottomLeft

cornerFamily

  • Shape of corner
  • Enum value
    • rounded
    • cut
  • Can be set on a wholesale or corner by corner basis
    • cornerFamily
    • cornerFamilyTopLeft
    • cornerFamilyTopRight
    • cornerFamilyBottomRight
    • cornerFamilyBottomLeft

XML Usage

    <com.google.android.material.imageview.ShapeableImageView
        android:id="@+id/imageView"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:background="@color/colorPrimaryDark"
        app:shapeAppearanceOverlay="@style/AppTheme.ShapeAppearanceOverlay"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <style name="AppTheme.ShapeAppearanceOverlay">
        <item name="cornerFamily">rounded</item>
        <item name="cornerSize">50dp</item>
    </style>

Programmatic Usage

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    // Generate builder from imageView.shapeAppearanceModel so we maintain
    // any shape configuration that may be already set via XML
    val shapeAppearanceModel = imageView.shapeAppearanceModel.toBuilder()
        .setAllCorners(CornerFamily.ROUNDED, 50.toPX)
        .build()
    imageView.shapeAppearanceModel = shapeAppearanceModel
}

Example: Cut Corners

val shapeAppearanceModel = ShapeAppearanceModel.Builder()
                // 100 is half the height of ImageView
            .setAllCorners(CornerFamily.CUT, 50.toPX)
            .build()
        imageView.shapeAppearanceModel = shapeAppearanceModel
    <style name="AppTheme.ShapeAppearanceOverlay">
        <item name="cornerFamily">cut</item>
        <item name="cornerSize">50dp</item>
    </style>

Example: Perfect Circle

val shapeAppearanceModel = ShapeAppearanceModel.Builder()
                // 100 is half the height of ImageView
            .setAllCorners(CornerFamily.ROUNDED, 100.toPX)
            .build()
        imageView.shapeAppearanceModel = shapeAppearanceModel
    <style name="AppTheme.ShapeAppearanceOverlay">
        <item name="cornerFamily">rounded</item>
        <item name="cornerSize">50%</item>
    </style>

Example: Diamond

val shapeAppearanceModel = ShapeAppearanceModel.Builder()
                // 100 is half the height of ImageView
            .setAllCorners(CornerFamily.CUT, 100.toPX)
            .build()
        imageView.shapeAppearanceModel = shapeAppearanceModel
    <style name="AppTheme.ShapeAppearanceOverlay">
        <item name="cornerFamily">cut</item>
        <item name="cornerSize">50%</item>
    </style>

Example: Hill

 val shapeAppearanceModel = ShapeAppearanceModel.Builder()
                // 100 is half the height of ImageView
            .setTopRightCorner(CornerFamily.ROUNDED, 100.toPX)
            .setTopLeftCorner(CornerFamily.ROUNDED, 100.toPX)
            .build()
        imageView.shapeAppearanceModel = shapeAppearanceModel
    <style name="AppTheme.ShapeAppearanceOverlay">
        <item name="cornerFamilyTopLeft">rounded</item>
        <item name="cornerFamilyTopRight">rounded</item>
        <item name="cornerSizeTopLeft">100dp</item>
        <item name="cornerSizeTopRight">100dp</item>
    </style>

Example: House

 val shapeAppearanceModel = ShapeAppearanceModel.Builder()
                // 100 is half the height of ImageView
            .setTopRightCorner(CornerFamily.CUT, 100.toPX)
            .setTopLeftCorner(CornerFamily.CUT, 100.toPX)
            .build()
        imageView.shapeAppearanceModel = shapeAppearanceModel
    <style name="AppTheme.ShapeAppearanceOverlay">
        <item name="cornerFamilyTopLeft">cut</item>
        <item name="cornerFamilyTopRight">cut</item>
        <item name="cornerSizeTopLeft">100dp</item>
        <item name="cornerSizeTopRight">100dp</item>
    </style>

Example: Triangle

 val shapeAppearanceModel = ShapeAppearanceModel.Builder()
                // 100 is half the height of ImageView
            .setTopRightCorner(CornerFamily.CUT, 200.toPX)
            .setTopLeftCorner(CornerFamily.CUT, 200.toPX)
            .build()
        imageView.shapeAppearanceModel = shapeAppearanceModel
    <style name="AppTheme.ShapeAppearanceOverlay">
        <item name="cornerFamilyTopLeft">cut</item>
        <item name="cornerFamilyTopRight">cut</item>
        <item name="cornerSizeTopLeft">200dp</item>
        <item name="cornerSizeTopRight">200dp</item>
    </style>

Example: ¯\_(ツ)_/¯

 val shapeAppearanceModel = ShapeAppearanceModel.Builder()
            .setBottomRightCorner(CornerFamily.ROUNDED, 85.toPX)
            .setBottomLeftCorner(CornerFamily.CUT, 120.toPX)
            .setTopLeftCorner(CornerFamily.ROUNDED, 50.toPX)
            .build()
        imageView.shapeAppearanceModel = shapeAppearanceModel
    <style name="AppTheme.ShapeAppearanceOverlay">
        <item name="cornerFamilyBottomRight">rounded</item>
        <item name="cornerFamilyBottomLeft">cut</item>
        <item name="cornerFamilyTopLeft">rounded</item>
        <item name="cornerSizeBottomRight">85dp</item>
        <item name="cornerSizeBottomLeft">120dp</item>
        <item name="cornerSizeTopLeft">50dp</item>
    </style>

Questions?

ShapeableImageView

By Kenneth Baldauf

ShapeableImageView

A look at the new ShapeableImageView added in version 1.2.0 of the material design library.

  • 452