¿Golpe de Android de lados abiertos?

94

¿Es posible crear un objeto de forma de Android con trazo en solo ciertos lados?

Por ejemplo, tengo:

<stroke 
 android:width="3dip" 
 android:color="#000000"
    android:dashWidth="10dip" 
    android:dashGap="6dip" />

Que es similar a este CSS:

border: 3px dashed black;

¿Cómo puedo configurar el trazo en un solo lado? Así es como lo haría en CSS:

border-left: 3px dashed black;

¿Cómo se hace esto en XML de Android?

Reed Morse
fuente

Respuestas:

127

Logré una buena solución con este:

<?xml version="1.0" encoding="utf-8"?>

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- This is the line -->
    <item android:top="-1dp" android:right="-1dp" android:left="-1dp">
      <shape>
            <solid android:color="@android:color/transparent" />
            <stroke android:width="1dp" android:color="#ffffff" />
      </shape>
    </item>

</layer-list>

Esto funciona bien en caso de que necesite un fondo transparente pero aún un color de trazo abierto (en mi caso, solo necesitaba una línea de fondo). Si necesita un color de fondo, puede agregar un color de forma sólida como en la respuesta de Maragues.

EDITAR 1

A veces, para dispositivos de alta densidad, el uso de valores de inmersión bajos puede terminar en trazos o distancias muy delgados o invisibles. Esto puede sucederle también al configurar divisores ListView.

La solución alternativa más sencilla es utilizar una distancia de 1 px en lugar de 1 dp. Esto hará que la línea sea siempre visible en todas las densidades. La mejor solución sería crear recursos de dimensión para cada densidad, para obtener el mejor tamaño para cada dispositivo.

Editar 2

Divertido, pero intenté usar esto 6 años después y no puedo obtener un buen resultado en los dispositivos Lollipop.

Probablemente la solución actual sea utilizar 9 parches. Android debería haber sido una solución fácil para este problema después de todo este tiempo.

htafoya
fuente
Esto también funcionó para mí, pero no sé exactamente por qué tuve que usar -2dp en lugar de -1dp. Si usara este último, aún podría ver una línea delgada.
Edu Zamora
1
@EduZamora sí, parece que para dispositivos de alta densidad -1dp no funciona como se esperaba
htafoya
También obtengo un borde para todos los lados, pero no solo el borde inferior.
Cheok Yan Cheng
@YanChengCHEOK intente con 1px en lugar de 1dp.
htafoya
@htafoya esta es una solución brillante. ¡Gracias!
abriggs
52

Sé que esta pregunta se publicó hace mucho tiempo, por lo que la persona que publicó esta pregunta no usará la respuesta, pero aún puede ayudar a otros.

 <?xml version="1.0" encoding="UTF-8"?>
    <!-- inset is used to remove border from top, it can remove border from any other side-->
    <inset xmlns:android="http://schemas.android.com/apk/res/android"
        android:insetTop="-2dp"
        >
    <shape xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/rectangle">
        <stroke android:width="1dp" android:color="#b7b7b7" />
        <corners android:bottomRightRadius="5dp"  android:bottomLeftRadius="5dp"/>

        <solid android:color="#454444"/>
    </shape>
    </inset>

Utilice la insetetiqueta y asigne un valor negativo al borde lateral que desea eliminar.

Los posibles valores son:

android:insetTop="-1dp" android:insetBottom="-1dp" android:insetLeft="-1dp" android:insetRight="-1dp"

Nirmal Dhara
fuente
¡Sí, y no hagas lo que hice y trates de poner el atributo insertado en la etiqueta de trazo sin leer el resto de la respuesta! (gracias por la respuesta BTW OP. Solución perfecta)
Kiran
elegante! Me encanta esta solución
Hao Qi
41

Resolví esto usando una capa de lista, combinando dos formas, una de las cuales con una altura de 1 dp colocada en la parte inferior

optionscreen_bottomrectangle.xml:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- This is the line -->
<item>
      <shape>
            <solid android:color="#535353" />
      </shape>
</item>
<!-- This is the main color -->
<item android:bottom="1dp">
     <shape>
           <solid android:color="#252525" />
     </shape>
</item>
</layer-list>

Luego, en el archivo layout / main.xml

<TextView
    android:id="@+id/bottom_rectangle"
    android:background="@drawable/optionscreen_bottomrectangle"
    android:layout_width="fill_parent"
    android:layout_height="0dp"
    android:layout_below="@id/table_options"
    android:layout_above="@id/exit_bar"/>

Lo que llena el espacio entre table_options y exit_bar con un fondo y justo antes de exit_bar imprime una línea de 1dp. Esto funcionó para mí, espero que ayude a alguien más.

Respuesta editada para colocar capas en el orden correcto. ¡Gracias Alex!

Maragues
fuente
Puede ser útil no publicar una respuesta si realmente desea tener una respuesta usted mismo. Cuando otros desarrolladores ven que ya hay una respuesta (aunque en este caso en realidad no es), no están tan dispuestos a responder.
MrSnowflake
31

Otra toma de las otras respuestas usando relleno en su lugar. Este pequeño chuletón hace un borde en la parte superior e inferior.

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- This is the line -->
    <item>
          <shape>
                <padding android:left="0dp" android:top="1dp" android:right="0dp" android:bottom="1dp"/>
                <solid android:color="#898989" />
          </shape>
    </item>
    <!-- This is the main color -->
    <item>
         <shape>
             <solid android:color="#ffffff" />
         </shape>
    </item>
</layer-list>
ug_
fuente
4
Esta es, con mucho, la mejor respuesta si necesita esquinas redondeadas.
MacKinley Smith
Este también me ayudó muchísimo. Por favor, pruébalo y vota a favor
Chico
@ug_ Creo que este es el mejor enfoque. Funciona perfectamente, gracias
Lalit Sharma
Trabajos. Parece completamente incorrecto en el panel de vista previa de Android Studio (v1.1), pero en el dispositivo está bien.
Murat Ögat
26

La respuesta de @ Maragues es al revés, ya que los elementos de diseño de la lista de capas se dibujan de arriba a abajo (lo que significa que el último elemento de la lista se dibuja en la parte superior):

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- This is the line -->
<item>
      <shape>
            <solid android:color="#535353" />
      </shape>
</item>
<!-- This is the main color -->
<item android:bottom="1dp">
     <shape>
           <solid android:color="#252525" />
     </shape>
</item>

</layer-list>

Esto llenará efectivamente la forma con el color de la línea, luego dibujará el color de fondo encima, dejando el último 1dp claro para que se vea el color de la línea.

Alex Pretzlav
fuente
2
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >


<item>
    <shape android:shape="rectangle" >
        <stroke  android:width="2dp"
                 android:color="#BBBBBB" />
        <solid android:color="@android:color/transparent" />
    </shape>
</item>
<item  android:bottom="2dp" >
    <shape android:shape="rectangle" >
        <stroke  android:width="2dp"
                 android:color="@color/main_background_color" />
        <solid android:color="@android:color/transparent" />
    </shape>
</item>

soleado
fuente
2

He usado el siguiente código.

<?xml version="1.0" encoding="UTF-8"?>
<!-- inset is used to remove border from top, it can remove border from any other side-->
<inset xmlns:android="http://schemas.android.com/apk/res/android"
    android:insetTop="-2dp" android:insetLeft="-2dp" android:insetRight="-2dp"
    >
    <shape xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/rectangle">
        <stroke android:width="1dp" android:color="@color/colorPrimary" />
        <solid android:color="#0000"/>
        <padding android:left="2dp" android:top="2dp" android:bottom="2dp" android:right="2dp"/>
    </shape>
</inset>
Ken W.
fuente
0

Simple y eficiente

Para tener una vista transparente y todo lo que está afuera tiene una superposición de algún color, lo que puede hacer es construir las vistas que encapsulan la vista central sin que las vistas externas pisen la vista central .

De esta forma, evita tener un dibujable externo al diseño y tiene más control sobre las distancias de las vistas sin tener que realizar cálculos en tiempo de ejecución.

<androidx.constraintlayout.widget.ConstraintLayout .. >

    <View
        android:id="@+id/center"
        android:layout_width="100dp"
        android:layout_height="100dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        android:background="@color/transparent"/>

   <View
        android:id="@+id/left_overlay"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@id/center"
        app:layout_constraintTop_toBottomOf="@id/top_overlay"
        app:layout_constraintBottom_toTopOf="@id/bottom_overlay"
        android:background="@color/black"
        android:alpha="0.5"
        />

    <View
        android:id="@+id/right_overlay"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintLeft_toRightOf="@id/center"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/top_overlay"
        app:layout_constraintBottom_toTopOf="@id/bottom_overlay"
        android:background="@color/black"
        android:alpha="0.5"
        />

    <View
        android:id="@+id/top_overlay"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toTopOf="@id/center"
        android:background="@color/black"
        android:alpha="0.5"
        />

    <View
        android:id="@+id/bottom_overlay"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toBottomOf="@id/center"
        android:background="@color/black"
        android:alpha="0.5"
        />

</androidx.constraintlayout.widget.ConstraintLayout>

GL

Coronel braian
fuente