Como criar botões padrão sem borda (como na diretriz de design mencionada)?

113

Eu estava apenas verificando as diretrizes de design e me perguntando sobre os botões sem borda. Eu arregalei os olhos e tentei encontrar a fonte, mas não consigo reuni-la sozinho. Este é o widget de botão normal, mas você adiciona um estilo personalizado (padrão do Android)? Como fazer esses botões sem borda (claro que você pode definir o fundo como vazio, mas eu não tenho o divisor)?

Aqui estão os links para as diretrizes de design:

insira a descrição da imagem aqui

KarlKarlsom
fonte
Semelhante stackoverflow.com/questions/14046232/...
Khaled Annajar

Respostas:

163

Para limpar alguma confusão:

Isso é feito em 2 etapas: Definir o atributo de fundo do botão como android: attr / selectableItemBackground cria um botão com feedback, mas sem fundo.

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

A linha para dividir o botão sem borda do restante do layout é feita por uma visualização com o Android de fundo : attr / dividerVertical

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

Para uma melhor compreensão, aqui está um layout para uma combinação de botões OK / Cancelar sem borda na parte inferior da tela (como na imagem à direita acima).

<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
fonte
25
Vale ressaltar: esta solução só funciona para API nível 11+.
9
Se você usar o HoloEverywhere, ele funcionará para o nível 7 da API. Você deve mudar ?android:attr/selectableItemBackgroundpara ?attr/selectableItemBackgrounde ?android:attr/dividerVerticalpara?attr/dividerVertical
Brais Gabin
1
?android:attr/dividerVerticalfore ?attr/dividerVerticaltambém funciona para abs
oscarthecat
22

Resposta tardia, mas muitos pontos de vista. Como as APIs <11 ainda não morreram, para os interessados ​​aqui está um truque.

Deixe seu container ter a cor desejada (pode ser transparente). Em seguida, dê aos seus botões um seletor com a cor transparente padrão e alguma cor quando pressionados. Dessa forma, você terá um botão transparente, mas mudará de cor quando pressionado (como o holo). Você também pode adicionar alguma animação (como holo). O seletor deve ser algo assim:

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>

E o botão deveria ter android:background="@drawable/selector_transparent_button"

PS: deixe seu container ter as divisórias ( android:divider='@android:drawable/...para API <11)

PS [Iniciantes]: você deve definir essas cores em values ​​/ colors.xml

aacotroneo
fonte
Isso funcionou perfeitamente para API Level 10e API Level > 10!
theblang
Isso é melhor do que fazê-lo programaticamente, embora ambos funcionassem.
Eran Goldin
1
O atributo "exitFadeDuration" é usado apenas na API de nível 11 e superior.
Bevor
sim @Bevor, boa. Os leitores consideram que as tags xml desconhecidas são ignoradas, portanto, usará o esmaecimento para api> = 11 e funcionará apenas para <11
aacotroneo
18

Para quem deseja botões sem borda, mas ainda animados quando clicados. Adicione isso no botão.

style="?android:attr/borderlessButtonStyle"

Se você quiser uma divisória / linha entre eles. Adicione isso no layout linear.

style="?android:buttonBarStyle"

Resumo

<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
fonte
mais para buttonBarStyle. e esta é a resposta btw.
Frostymarvelous
7

Para estilo de material, adicione style="@style/Widget.AppCompat.Button.Borderless"ao usar a biblioteca AppCompat.

Roel
fonte
5

Da fonte do aplicativo iosched, criei esta ButtonBarclasse:

/**
 * 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;
}

Este será o local em LinearLayoutque os botões "OK" e "Cancelar" serão colocados e tratará de colocá-los na ordem apropriada. Em seguida, coloque isso no layout em que deseja que os botões:

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

Isso dá a você a aparência de um diálogo com botões sem bordas. Você pode encontrar esses atributos no res na estrutura. buttonBarStylefaz a divisória vertical e o preenchimento. buttonBarButtonStyleestá definido como borderlessButtonStylepara o tema Holo, mas acredito que esta seja a maneira mais robusta de exibi-lo como o framework deseja exibi-lo.

Dandre Allison
fonte
como eu poderia colocar isso (? android: attr / buttonBarButtonStyle) em styles.xml como item de um estilo?
lis
4

Olhar para o tema atributos buttonBarStyle, buttonBarButtonStylee borderlessButtonStyle.

Josh Lee
fonte
Se eu usar buttonBarButtonStyle, recebo uma exceção 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}Não tenho ideia do porquê, mas usando faz selectableItemBackgroundmaravilhas.
Alguém em algum lugar de
4

Você também pode tornar os botões sem bordas por meio do código:

TypedValue value= new TypedValue();
getApplicationContext().getTheme().resolveAttribute(android.R.attr.selectableItemBackground, value, true);
 myButton.setBackgroundResource(value.resourceId);
Isj
fonte
Está funcionando, obrigado. Mas android.R.attr.selectableItemBackgroundrequer API 21. Alguma ideia de como fazer isso em versões anteriores?
arenaq
Não está funcionando. Estou tentando definir o recurso de android.R.attr.buttonBarButtonStyle e diz que o recurso não foi encontrado.
Kristy Welsh
use android.R.attr.selectableItemBackground
Isj
2

Para aqueles que desejam criar botão sem borda programaticamente para APIs> = 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
fonte
Isso é melhor e mais simples do que a solução de lsj. Apenas setBackgroundResource (0)
jk7
2

Outra solução que deve funcionar nas plataformas Android mais antigas e mais recentes é usar

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

atributo para a visualização do botão. Mas depois de adicionar o botão da linha acima não fornecerá feedback de toque.

Para fornecer feedback de toque, adicione o seguinte código à classe 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;
    }
});

Está funcionando bem para mim.

prodev
fonte
Eu adicionaria case MotionEvent.ACTION_CANCEL: abaixo do case MotionEvent.ACTION_UP: também.
Medo
2

Para quem ainda está procurando:

herde seu próprio estilo para as barras de botão Holo:

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

ou Holo Light:

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

e para botões Holo sem borda:

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

ou Holo Light:

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

É assim que você cria um botão sem borda (plano) programaticamente sem usar 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
fonte
Eu estava usando: ContextThemeWrapper myContext = new ContextThemeWrapper(this.getActivity(), R.style.Widget_AppCompat_Button_Borderless_Colored); Button myButton = new Button(myContext); e não funcionava. Depois de adicionar o 2º e o 3º parâmetro, está funcionando!
levibostian
1

Use o código abaixo em seu arquivo xml. Use android: background = "# 00000000" para obter a cor transparente.

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

Você pode usar a Biblioteca de Suporte AppCompat para botão sem borda.

Você pode fazer um botão sem borda como este:

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

Você pode fazer um botão colorido sem borda como este:

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

Por algum motivo, nem style="Widget.Holo.Button.Borderless"nem android:background="?android:attr/selectableItemBackground"funcionou para mim. Para ser mais preciso, Widget.Holo.Button.Borderlessfuncionou no Android 4.0, mas não funcionou no Android 2.3.3. O que funcionou para mim em ambas as versões foi android:background="@drawable/transparent"este XML em res / drawable / transparent.xml:

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

Cabeça plana através da abordagem da parede.

Imperador orionii
fonte
2
Definir o fundo como @android: color / transparent funcionou para mim, sem a necessidade do arquivo XML extra.
Nicolai Buch-Andersen
Isso não inclui como obter o divisor.
Navarr de
3
@Navarr de acordo com a resposta de Blundell, divisor não faz parte do "botão sem borda". Nem deveria ser porque os botões e qualquer outra classe de visualização não devem ser informados sobre os componentes GUI em torno. Isso é responsabilidade do contêiner. Nos comentários da postagem de Blundell, há um link para o que parece ser o layout do item de detalhes do contato do ICS. Há uma visão extra (com id vertical_divider) para exibir o divisor. Nenhuma solução fora da caixa para divisórias automáticas, embora haja um android:background="?android:attr/dividerVertical"truque interessante.
Imperador Orionii
A questão dos OPs referia-se aos "Botões sem borda" do Android UX, e em todos os exemplos eles têm o divisor - que aparentemente faz parte do buttonBarStyle. Embora você tenha me dado algumas informações muito úteis, obrigado.
Navarr
0

Uma ótima apresentação de slides sobre como conseguir o efeito desejado do Google Nick Butcher (comece no slide 20). Ele usa o Android padrão @attrpara estilizar o botão e o divisor.

Moritz
fonte
Observe que as respostas somente com link são desencorajadas, as respostas do SO devem ser o ponto final de uma busca por uma solução (em vez de outra parada de referências, que tendem a ficar obsoletas com o tempo). Considere adicionar uma sinopse independente aqui, mantendo o link como uma referência.
kleopatra
0

Adicionando à resposta principal, você também pode usar visualizações com uma cor de fundo cinza escuro em um Layout Linear como este.

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

Se a sua linha for horizontal, você deve definir a altura para 1 mergulho e a largura para corresponder ao pai e vice-versa se a linha for vertical.

Munaz
fonte
0

Se você deseja obter o mesmo programaticamente:

(isso é C #, mas facilmente transacionável para Java)

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

Combine

    <Button
       style="@style/Widget.AppCompat.Button.Borderless.Colored"
    .../>
Yohan Dahmani
fonte
0

Tente este código, para remover o drawable de fundo (@ drawable / bg) programaticamente, apenas precisamos fornecer null como parâmetro.

Button btn= new Button(this);
btn.setText("HI");
btn.setBackground(null);
Ramesh kumar
fonte
1
Obrigado por este trecho de código, que pode fornecer alguma ajuda limitada e imediata. Uma explicação adequada melhoraria muito seu valor a longo prazo, mostrando por que essa é uma boa solução para o problema e a tornaria mais útil para futuros leitores com outras questões semelhantes. Por favor edite sua resposta para adicionar alguma explicação, incluindo as suposições que você fez.
NOhs