Jak stworzyć standardowe przyciski bez obramowania (jak we wspomnianych wytycznych projektowych)?

114

Właśnie sprawdzałem wytyczne projektowe i zastanawiałem się nad przyciskami bez obramowania. Wytrzeszczyłem oczy i próbowałem znaleźć w źródle, ale nie mogę sam tego zebrać. Czy to normalny widżet Przycisk, ale dodajesz niestandardowy (domyślny dla Androida) styl? Jak zrobić te przyciski bez obramowania (oczywiście możesz ustawić puste tło, ale wtedy nie mam separatora)?

Tutaj linki do wytycznych projektowych:

wprowadź opis obrazu tutaj

KarlKarlsom
źródło

Odpowiedzi:

163

Aby usunąć zamieszanie:

Odbywa się to w 2 krokach: Ustawienie atrybutu tła przycisku na android: attr / selectableItemBackground tworzy przycisk z informacją zwrotną, ale bez tła.

android:background="?android:attr/selectableItemBackground"

Linia oddzielająca przycisk bez obramowania od reszty układu jest tworzona przez widok z tłem android: attr / dividerVertical

android:background="?android:attr/dividerVertical"

Dla lepszego zrozumienia jest tutaj układ kombinacji przycisków OK / Anuluj bez obramowania u dołu ekranu (jak na prawym obrazku powyżej).

<RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="48dp"
        android:layout_alignParentBottom="true">
        <View
            android:layout_width="match_parent"
            android:layout_height="1dip"
            android:layout_marginLeft="4dip"
            android:layout_marginRight="4dip"
            android:background="?android:attr/dividerVertical"
            android:layout_alignParentTop="true"/>
        <View
            android:id="@+id/ViewColorPickerHelper"
            android:layout_width="1dip"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_alignParentBottom="true"
            android:layout_marginBottom="4dip"
            android:layout_marginTop="4dip"
            android:background="?android:attr/dividerVertical" 
            android:layout_centerHorizontal="true"/>
        <Button
            android:id="@+id/BtnColorPickerCancel"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_alignParentTop="true"
            android:layout_toLeftOf="@id/ViewColorPickerHelper"
            android:background="?android:attr/selectableItemBackground"
            android:text="@android:string/cancel" 
            android:layout_alignParentBottom="true"/>
        <Button
            android:id="@+id/BtnColorPickerOk"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_alignParentRight="true"
            android:layout_alignParentTop="true"
            android:background="?android:attr/selectableItemBackground"
            android:text="@android:string/ok" 
            android:layout_alignParentBottom="true" 
            android:layout_toRightOf="@id/ViewColorPickerHelper"/>
    </RelativeLayout>
KarlKarlsom
źródło
25
Warto zwrócić uwagę: to rozwiązanie działa tylko dla poziomu API 11+.
9
Jeśli używasz HoloEverywhere , działa to na poziomie API 7+. Musisz zmienić ?android:attr/selectableItemBackgroundna ?attr/selectableItemBackgroundi ?android:attr/dividerVerticalna?attr/dividerVertical
Brais Gabin
1
?android:attr/dividerVerticalfora ?attr/dividerVerticaltakże działa na abs
oscarthecat
22

Późna odpowiedź, ale wiele opinii. Ponieważ API <11 jeszcze nie umarły, dla zainteresowanych jest to sztuczka.

Niech twój pojemnik uzyska pożądany kolor (może być przezroczysty). Następnie nadaj przyciskom selektor z domyślnym przezroczystym kolorem i pewnym kolorem po naciśnięciu. W ten sposób będziesz mieć przezroczysty przycisk, ale po naciśnięciu zmieni kolor (jak hologramy). Możesz także dodać animację (np. Hologramy). Selektor powinien wyglądać mniej więcej tak:

res/drawable/selector_transparent_button.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" 
          android:exitFadeDuration="@android:integer/config_shortAnimTime">
     <item android:state_pressed="true"
         android:drawable="@color/blue" />

   <item android:drawable="@color/transparent" />
</selector>

A przycisk powinien mieć android:background="@drawable/selector_transparent_button"

PS: pozwól kontenerowi mieć separatory ( android:divider='@android:drawable/...dla API <11)

PS [Newbies]: powinieneś zdefiniować te kolory w values ​​/ colors.xml

aacotroneo
źródło
To działało idealnie zarówno w przypadku, jak API Level 10i API Level > 10!
theblang
Jest to lepsze niż robienie tego programowo, mimo że oba będą działać.
Eran Goldin
1
Atrybut „exitFadeDuration” jest używany tylko na poziomie interfejsu API 11 i wyższych.
Bevor
tak @Bevor, niezłe. Czytelnicy uważają, że nieznane znaczniki xml są ignorowane, więc użyje zanikania dla api> = 11 i po prostu będzie działać dla <11
aacotroneo
18

Dla tych, którzy chcą przyciski bez obramowania, ale nadal są animowane po kliknięciu. Dodaj to w przycisku.

style="?android:attr/borderlessButtonStyle"

Jeśli chcesz, aby między nimi była dzielnica / linia. Dodaj to w układzie liniowym.

style="?android:buttonBarStyle"

Podsumowanie

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:orientation="horizontal"
   style="?android:buttonBarStyle">

    <Button
        android:id="@+id/add"
        android:layout_weight="1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/add_dialog" 
        style="?android:attr/borderlessButtonStyle"
        />

    <Button
        android:id="@+id/cancel"
        android:layout_weight="1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/cancel_dialog" 
        style="?android:attr/borderlessButtonStyle"
        />

</LinearLayout>
aLIEz
źródło
plus dla buttonBarStyle. i to jest przy okazji odpowiedź.
mroźno cudowny
7

Aby uzyskać styl materiału, dodaj style="@style/Widget.AppCompat.Button.Borderless"podczas korzystania z biblioteki AppCompat.

Roel
źródło
5

Ze źródła aplikacji na iOS wymyśliłem tę ButtonBarklasę:

/**
 * An extremely simple {@link LinearLayout} descendant that simply reverses the 
 * order of its child views on Android 4.0+. The reason for this is that on 
 * Android 4.0+, negative buttons should be shown to the left of positive buttons.
 */
public class ButtonBar extends LinearLayout {

    public ButtonBar(Context context) {
        super(context);
    }

    public ButtonBar(Context context, AttributeSet attributes) {
        super(context, attributes);
    }

    public ButtonBar(Context context, AttributeSet attributes, int def_style) {
        super(context, attributes, def_style);
    }

    @Override
    public View getChildAt(int index) {
        if (_has_ics)
            // Flip the buttons so that "OK | Cancel" becomes "Cancel | OK" on ICS
            return super.getChildAt(getChildCount() - 1 - index);

        return super.getChildAt(index);
    }

    private final static boolean _has_ics = Build.VERSION.SDK_INT >= 
                                        Build.VERSION_CODES.ICE_CREAM_SANDWICH;
}

Będzie to miejsce LinearLayout, do którego trafiają przyciski „OK” i „Anuluj” i zajmą się umieszczaniem ich w odpowiedniej kolejności. Następnie umieść to w układzie, w którym chcesz umieścić przyciski:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:divider="?android:attr/dividerHorizontal"
          android:orientation="vertical"
          android:showDividers="middle">
    <!--- A view, this approach only works with a single view here -->
    <your.package.ButtonBar style="?android:attr/buttonBarStyle"
        android:id="@+id/buttons"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:weightSum="1.0">
        <Button style="?android:attr/buttonBarButtonStyle"
            android:id="@+id/ok_button"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="0.5"
            android:text="@string/ok_button" />
        <Button style="?android:attr/buttonBarButtonStyle"
            android:id="@+id/cancel_button"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="0.5"
            android:text="@string/cancel_button" />
    </your.package.ButtonBar>
</LinearLayout>

Daje to wygląd okna dialogowego z przyciskami bez obramowania. Możesz znaleźć te atrybuty w res we frameworku. buttonBarStylewykonuje pionowy separator i dopełnienie. buttonBarButtonStylejest ustawiony jak borderlessButtonStylemotyw Holo, ale uważam, że powinien to być najpewniejszy sposób wyświetlania go, ponieważ struktura chce go wyświetlić.

Dandre Allison
źródło
jak mogę umieścić to (? android: attr / buttonBarButtonStyle) w styles.xml jako element stylu?
lis
4

Spojrzenie na temat atrybutów buttonBarStyle, buttonBarButtonStyleoraz borderlessButtonStyle.

Josh Lee
źródło
Jeśli używam buttonBarButtonStyle, otrzymuję wyjątek E/AndroidRuntime(17134): Caused by: java.lang.reflect.InvocationTargetException E/AndroidRuntime(17134): Caused by: android.content.res.Resources$NotFoundException: Resource is not a Drawable (color or path): TypedValue{t=0x1/d=0x1030281 a=2 r=0x1030281}Nie mam pojęcia dlaczego, ale używanie selectableItemBackgrounddziała cuda.
Someone Somewhere
4

Możesz również uczynić przyciski bez obramowania za pomocą kodu:

TypedValue value= new TypedValue();
getApplicationContext().getTheme().resolveAttribute(android.R.attr.selectableItemBackground, value, true);
 myButton.setBackgroundResource(value.resourceId);
Isj
źródło
Działa, dzięki. Ale android.R.attr.selectableItemBackgroundwymaga API 21. Jakieś pomysły, jak to zrobić we wcześniejszych wersjach?
arenaq
To nie działa. Próbuję ustawić zasób android.R.attr.buttonBarButtonStyle i mówi, że nie można znaleźć zasobu.
Kristy Welsh
użyj android.R.attr.selectableItemBackground
Isj
2

Dla tych, którzy chcą programowo utworzyć przycisk bez obramowania dla API> = 8

ImageButton smsImgBtn = new ImageButton(this);
//Sets a drawable as the content of this button
smsImgBtn.setImageResource(R.drawable.message_icon);    
//Set to 0 to remove the background or for bordeless button
smsImgBtn.setBackgroundResource(0);
Sohail
źródło
To jest lepsze, prostsze niż rozwiązanie lsj. Po prostu ustawBackgroundResource (0)
jk7
2

Innym rozwiązaniem, które powinno działać zarówno na starszej, jak i nowszej platformie Android, jest użycie

android:background="@android:color/transparent"

atrybut dla widoku przycisku. Ale po dodaniu powyższej linii przycisk nie zapewni reakcji na dotyk.

Aby zapewnić reakcję dotykową, dodaj następujący kod do klasy Activity

button.setOnTouchListener(new View.OnTouchListener() {          
    @Override
    public boolean onTouch(View view, MotionEvent event) {
        switch (event.getAction())
        {
            case MotionEvent.ACTION_DOWN:    
                ((Button)view).setBackgroundColor(Color.LTGRAY);
                break;
            case MotionEvent.ACTION_UP:
                ((Button)view).setBackgroundColor(Color.TRANSPARENT);
        }
        return false;
    }
});

Dla mnie działa dobrze.

prodev
źródło
Dodałbym również case MotionEvent.ACTION_CANCEL: poniżej case MotionEvent.ACTION_UP: .
Medo
2

Dla każdego, kto wciąż szuka:

odziedzicz własny styl pasków przycisków Holo:

<style name="yourStyle" parent="@android:style/Holo.ButtonBar">
  ...
</style>

lub Holo Light:

<style name="yourStyle" parent="@android:style/Holo.Light.ButtonBar">
  ...
</style>

a dla przycisków Holo bez obramowania:

<style name="yourStyle" parent="@android:style/Widget.Holo.Button.Borderless.Small">
  ...
</style>

lub Holo Light:

<style name="yourStyle" parent="@android:style/Widget.Holo.Light.Button.Borderless.Small">
  ...
</style>
silversmurf
źródło
2

W ten sposób programistycznie tworzysz przycisk bez obramowania (płaski) bez użycia XML

ContextThemeWrapper myContext = new ContextThemeWrapper(this.getActivity(), 
   R.style.Widget_AppCompat_Button_Borderless_Colored);

Button myButton = new Button(myContext, null, 
   R.style.Widget_AppCompat_Button_Borderless_Colored);
Manuel
źródło
Używałem: ContextThemeWrapper myContext = new ContextThemeWrapper(this.getActivity(), R.style.Widget_AppCompat_Button_Borderless_Colored); Button myButton = new Button(myContext); i to nie zadziała. Po dodaniu drugiego i trzeciego parametru działa!
lewibostian
1

Użyj poniższego kodu w pliku xml. Użyj android: background = "# 00000000", aby uzyskać przezroczysty kolor.

<Button
   android:id="@+id/btnLocation"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:background="#00000000"
   android:text="@string/menu_location"
   android:paddingRight="7dp"
/>
Kayuri Ravrani
źródło
1

Możesz użyć biblioteki obsługi AppCompat dla przycisku bez obramowania.

Możesz utworzyć przycisk bez obramowania w następujący sposób:

<Button
    style="@style/Widget.AppCompat.Button.Borderless"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="16dp" 
    android:text="@string/borderless_button"/>

Możesz utworzyć kolorowy przycisk bez obramowania w następujący sposób:

<Button
    style="@style/Widget.AppCompat.Button.Borderless.Colored"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="16dp" 
    android:text="@string/borderless_colored_button"/>
Rajesh
źródło
0

Z jakiegoś powodu style="Widget.Holo.Button.Borderless"ani android:background="?android:attr/selectableItemBackground"dla mnie, ani dla mnie nie działały. Mówiąc dokładniej, Widget.Holo.Button.Borderlesswykonałem zadanie na Androidzie 4.0, ale nie działało na Androidzie 2.3.3. Jaki był dla mnie trick w obu wersjach android:background="@drawable/transparent"i ten XML w res / drawable / transparent.xml:

<shape xmlns:android="http://schemas.android.com/apk/res/android" 
    android:shape="rectangle" >
</shape>

Prosta głowa przez podejście do ściany.

Cesarz Orionii
źródło
2
Ustawienie tła na @android: color / transparent działało jak dla mnie, bez potrzeby dodatkowego pliku XML.
Nicolai Buch-Andersen
Nie obejmuje to, jak uzyskać rozdzielacz.
Navarr
3
@Navarr, zgodnie z odpowiedzią Blundella, dzielnik nie jest częścią „przycisku bez obramowania”. Nie powinno też tak być, ponieważ przyciski i inne klasy widoku nie powinny być informowane o otaczających elementach GUI. To odpowiedzialność kontenera. W komentarzach do posta Blundella znajduje się łącze do czegoś, co wygląda na układ elementu szczegółów kontaktu ICS. Istnieje dodatkowy widok (z id vertical_divider) do wyświetlania separatora. Brak gotowego rozwiązania dla automatycznych rozdzielaczy, chociaż jest zgrabna android:background="?android:attr/dividerVertical"sztuczka.
Emperor Orionii
Pytanie OP dotyczyło Android UX „Borderless Buttons” i we wszystkich przykładach mają one separator - który najwyraźniej jest częścią buttonBarStyle. Mimo że przekazałeś mi kilka bardzo pomocnych informacji, dziękuję.
Navarr
0

Świetny pokaz slajdów pokazujący, jak osiągnąć pożądany efekt od Googles Nick Butcher (zacznij od slajdu 20). Używa standardowego Androida @attrdo stylizacji przycisku i rozdzielacza.

Moritz
źródło
Zwróć uwagę, że odradza się udzielanie odpowiedzi zawierających tylko łącze , odpowiedzi SO powinny być końcowym punktem poszukiwania rozwiązania (w porównaniu z kolejnym zatrzymaniem odniesień, które z czasem stają się nieaktualne). Proszę rozważyć dodanie tutaj samodzielnego streszczenia, zachowując link jako odniesienie.
kleopatra
0

Dodając do pierwszej odpowiedzi, możesz także użyć widoków z ciemnoszarym tłem w układzie liniowym, takim jak ten.

<View
    android:layout_width="match_parent"
    android:layout_height="1dip"
    android:layout_marginBottom="4dip"
    android:layout_marginLeft="4dip"
    android:layout_marginRight="4dip"
    android:layout_marginTop="4dip"
    android:background="@android:color/darker_gray"/>

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginBottom="4dip"
    android:orientation="horizontal"
    android:weightSum="1">

    <Button
        android:id="@+id/button_decline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_weight="0.50"
        android:background="?android:attr/selectableItemBackground"
        android:padding="10dip"
        android:text="@string/decline"/>

    <View
        android:layout_width="1dip"
        android:layout_height="match_parent"
        android:layout_marginLeft="4dip"
        android:layout_marginRight="4dip"
        android:background="@android:color/darker_gray"/>

    <Button
        android:id="@+id/button_accept"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginRight="10dp"
        android:layout_weight="0.50"
        android:background="?android:attr/selectableItemBackground"
        android:padding="10dip"
        android:text="@string/accept"/>
</LinearLayout>

Jeśli twoja linia jest pozioma, będziesz chciał ustawić wysokość na 1dip i szerokość tak, aby pasowała do rodzica i odwrotnie, jeśli twoja linia jest pionowa.

Munaz
źródło
0

Jeśli chcesz osiągnąć to samo programowo:

(to jest C #, ale łatwo można przetłumaczyć na Javę)

Button button = new Button(new ContextThemeWrapper(Context, Resource.Style.Widget_AppCompat_Button_Borderless_Colored), null, Resource.Style.Widget_AppCompat_Button_Borderless_Colored);

Mecz

    <Button
       style="@style/Widget.AppCompat.Button.Borderless.Colored"
    .../>
Yohan Dahmani
źródło
0

Wypróbuj ten kod, aby programowo usunąć tło do rysowania (@ drawable / bg), po prostu musimy podać wartość null jako parametr.

Button btn= new Button(this);
btn.setText("HI");
btn.setBackground(null);
Ramesh Kumar
źródło
1
Dziękujemy za ten fragment kodu, który może zapewnić ograniczoną, natychmiastową pomoc. Właściwe wyjaśnienie byłoby znacznie poprawić swoją długoterminową wartość pokazując dlaczego jest to dobre rozwiązanie problemu i byłoby bardziej użyteczne dla czytelników przyszłości z innymi, podobnymi pytaniami. Proszę edytować swoją odpowiedź dodać kilka wyjaśnień, w tym założeń już wykonanych.
NIE,