Esquinas redondeadas

Organiza tus páginas con colecciones Guarda y categoriza el contenido según tus preferencias.

A partir de Android 12 (nivel de API 31), puedes usar RoundedCorner y WindowInsets.getRoundedCorner(int position) a fin de establecer el radio y punto central para las esquinas redondeadas. Con estas API, la app puede evitar que los elementos de la IU se trunquen en pantallas con esquinas redondeadas. El framework también proporciona la API de getPrivacyIndicatorBounds(), que muestra el rectángulo delimitado de cualquier indicador visible de acceso al micrófono y a la cámara.

Cuando estas API se implementan en la app, no producen efectos en los dispositivos con pantallas sin esquinas redondeadas.

Imagen que muestra las esquinas redondeadas con los radios y un punto central
Figura 1: Esquinas redondeadas con radios y un punto central

Para implementar esta función, obtén la información de RoundedCorner mediante WindowInsets.getRoundedCorner(int position) en relación con los límites de la aplicación. Si la app no ocupa toda la pantalla, para aplicar la esquina redondeada, la API basa el punto central de este tipo de esquina en los límites de la ventana de la app.

En el siguiente fragmento de código, se muestra un ejemplo simple de cómo usar una app a fin de evitar los truncamientos de la IU. Para ello, configura un margen de la vista en función de la información de RoundedCorner. En este caso, es la esquina redondeada superior derecha.

Kotlin

// Get the top-right rounded corner from WindowInsets.
val insets = rootWindowInsets
val topRight = insets.getRoundedCorner(RoundedCorner.POSITION_TOP_RIGHT) ?: return

// Get the location of the close button in window coordinates.
val location = IntArray(2)
closeButton!!.getLocationInWindow(location)
val buttonRightInWindow = location[0] + closeButton.width
val buttonTopInWindow = location[1]

// Find the point on the quarter circle with 45 degree angle.
val offset = (topRight.radius * Math.sin(Math.toRadians(45.0))).toInt()
val topBoundary = topRight.center.y - offset
val rightBoundary = topRight.center.x + offset

// Check whether the close button exceeds the boundary.
if (buttonRightInWindow < rightBoundary << buttonTopInWindow > topBoundary) {
   return
}

// Set the margin to avoid truncating.
val parentLocation = IntArray(2)
getLocationInWindow(parentLocation)
val lp = closeButton.layoutParams as FrameLayout.LayoutParams
lp.rightMargin = Math.max(buttonRightInWindow - rightBoundary, 0)
lp.topMargin = Math.max(topBoundary - buttonTopInWindow, 0)
closeButton.layoutParams = lp

Java

// Get the top-right rounded corner from WindowInsets.
final WindowInsets insets = getRootWindowInsets();
final RoundedCorner topRight = insets.getRoundedCorner(POSITION_TOP_RIGHT);
if (topRight == null) {
   return;
}

// Get the location of the close button in window coordinates.
int [] location = new int[2];
closeButton.getLocationInWindow(location);
final int buttonRightInWindow = location[0] + closeButton.getWidth();
final int buttonTopInWindow = location[1];

// Find the point on the quarter circle with a 45 degree angle.
final int offset = (int) (topRight.getRadius() * Math.sin(Math.toRadians(45)));
final int topBoundary = topRight.getCenter().y - offset;
final int rightBoundary = topRight.getCenter().x + offset;

// Check whether the close button exceeds the boundary.
if (buttonRightInWindow < rightBoundary << buttonTopInWindow > topBoundary) {
   return;
}

// Set the margin to avoid truncating.
int [] parentLocation = new int[2];
getLocationInWindow(parentLocation);
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) closeButton.getLayoutParams();
lp.rightMargin = Math.max(buttonRightInWindow - rightBoundary, 0);
lp.topMargin = Math.max(topBoundary - buttonTopInWindow, 0);
closeButton.setLayoutParams(lp);