Otwarte obrysy Androida?


95

Czy można utworzyć obiekt kształtu Androida z obrysem tylko z niektórych stron?

Np. Mam:

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

Który jest podobny do tego CSS:

border: 3px dashed black;

Jak ustawić pociągnięcie tylko z jednej strony? Oto jak zrobiłbym to w CSS:

border-left: 3px dashed black;

Jak to zrobić w Android XML?

Odpowiedzi:


127

Dzięki temu osiągnąłem dobre rozwiązanie:

<?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>

Działa to dobrze, jeśli potrzebujesz przezroczystego tła, ale wciąż otwartego koloru obrysu (w moim przypadku potrzebowałem tylko dolnej linii). Jeśli potrzebujesz koloru tła, możesz dodać jednolity kolor kształtu, jak w odpowiedzi Maragues.

EDYCJA 1

Czasami, w przypadku urządzeń o wysokiej gęstości, używanie niskich wartości spadku może kończyć się bardzo cienkimi lub niewidocznymi pociągnięciami lub odległościami. Może się to zdarzyć również podczas ustawiania dzielników ListView.

Najprostszym obejściem jest użycie odległości 1 piksela zamiast 1 dp. Dzięki temu linia będzie zawsze widoczna przy wszystkich gęstościach. Najlepszym rozwiązaniem byłoby utworzenie zasobów wymiarów dla każdej gęstości, aby uzyskać najlepszy rozmiar dla każdego urządzenia.

Edytuj 2

Zabawne, ale próbowałem tego użyć 6 lat później i nie mogę uzyskać dobrego wyniku na urządzeniach Lollipop.

Prawdopodobnie obecnym rozwiązaniem jest użycie 9 łatek. Android po tylu latach powinien był łatwo rozwiązać ten problem.


To również zadziałało dla mnie, ale nie wiem dokładnie, dlaczego musiałem użyć -2dp zamiast -1dp. Gdybym użył tego drugiego, nadal widziałem cienką linię.
Edu Zamora

1
@EduZamora tak, wygląda na to, że dla urządzeń o dużej gęstości -1dp nie działa zgodnie z oczekiwaniami
htafoya

Dostaję też obramowanie ze wszystkich stron, ale nie tylko dolną.
Cheok Yan Cheng

@YanChengCHEOK spróbuj 1px zamiast 1dp.
htafoya

@htafoya to genialne rozwiązanie. Dzięki!
abriggs

53

Wiem, że to pytanie zostało wysłane dawno temu, więc odpowiedź nie zostanie użyta przez osobę, która je opublikowała, ale może pomóc innym.

 <?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>

Użyj insettagu i podaj ujemną wartość krawędzi bocznej, którą chcesz usunąć.

Możliwe wartości to:

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


Tak, i nie rób tego, co zrobiłem i spróbuj umieścić wstawkę atr w tagu obrysu bez czytania reszty odpowiedzi! (dzięki za odpowiedź BTW OP. Idealne rozwiązanie)
Kiran

elegancki! Uwielbiam to rozwiązanie
Hao Qi

41

Rozwiązałem to używając warstwy listy, łączącej dwa kształty, z których jeden o wysokości 1dp umieszczony na dole

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>

Następnie w pliku 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"/>

Wypełnia lukę między table_options i exit_bar tłem, a tuż przed exit_bar drukuje linię 1dp. To załatwiło sprawę dla mnie, mam nadzieję, że pomoże to komuś innemu.

Odpowiedź została zmieniona w celu umieszczenia warstw we właściwej kolejności. Dzięki Alex!


Może być przydatne nie publikowanie odpowiedzi, jeśli naprawdę chcesz uzyskać odpowiedź samodzielnie. Kiedy inni deweloperzy widzą, że jest już odpowiedź (chociaż w tym przypadku tak naprawdę nie jest), nie są tak skłonni do odpowiedzi.
MrSnowflake

31

Kolejne podejście do innych odpowiedzi wykorzystujących zamiast tego dopełnienie. Ten mały skrawek tworzy granicę na górze i na dole.

<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>

4
To zdecydowanie najlepsza odpowiedź, jeśli potrzebujesz zaokrąglonych rogów.
MacKinley Smith

Ten też bardzo mi pomógł. Proszę, spróbuj i zagłosuj za
Boy

@ug_ Myślę, że to najlepsze podejście. Działa idealnie, dzięki
Lalit Sharma

Pracuje. Wygląda zupełnie źle w okienku podglądu Android Studio (v1.1), ale na urządzeniu jest w porządku.
Murat Ögat

26

Odpowiedź @ Maragues jest odwrotna, ponieważ rysunki na liście warstw rysują się od góry do dołu (co oznacza, że ​​ostatni element na liście jest rysowany na górze):

<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>

Spowoduje to efektywne wypełnienie kształtu kolorem linii, a następnie narysowanie na nim koloru tła, pozostawiając ostatnie 1 dp przezroczyste, aby kolor linii był widoczny.


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>


2

Użyłem następującego kodu.

<?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>

0

Proste i wydajne

Aby mieć przejrzysty widok i wszystko, co jest na zewnątrz, ma nakładkę w jakimś kolorze, możesz stworzyć widoki, które obejmują widok środkowy, bez wkraczania widoków zewnętrznych na widok środkowy .

W ten sposób unikniesz konieczności rysowania zewnętrznego układu i masz większą kontrolę nad odległościami widoków bez konieczności wykonywania obliczeń w czasie wykonywania.

<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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.