如何创建标准的无边框按钮(如所提到的设计指南中的那样)?

117

我只是在查看设计指南,并想知道无边框按钮的情况。 我通过谷歌搜索并尝试在源代码中找到答案,但是自己无法解决。 这是普通的按钮小部件,但您添加了自定义(Android默认)样式吗? 如何制作这些无边框按钮(当然您可以将背景设置为空,但是那样我就没有分隔线了)?

以下链接是设计指南:

enter image description here


类似的问题:在使用Holoeverywhere库时,我的应用程序在setContentView上强制关闭。 - Khaled Annajar
19个回答

165
为了消除一些困惑: 这是分两步完成的:将按钮背景属性设置为android:attr/selectableItemBackground会创建一个带有反馈但没有背景的按钮。
android:background="?android:attr/selectableItemBackground"

使用带有背景属性android:attr/dividerVertical的视图来分隔无边框按钮与其余布局。

android:background="?android:attr/dividerVertical"
为了更好地理解,在您屏幕底部的OK / Cancel无边框按钮组合的布局如右图所示。
<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>

25
值得指出的是:此解决方案仅适用于API级别11及以上。 - user153275
9
如果您使用HoloEverywhere,它适用于API级别7+。 您必须将?android:attr/selectableItemBackground更改为?attr/selectableItemBackground,并将?android:attr/dividerVertical更改为?attr/dividerVertical - Brais Gabin
1
?android:attr/dividerVertical?attr/dividerVertical也适用于abs。 - oscarthecat

51

22

虽然回答晚了,但是有很多浏览量。由于API小于11的版本仍然存在,所以对于那些感兴趣的人,这里有一个技巧。

让你的容器具有所需的颜色(可以是透明的)。然后给你的按钮一个选择器,带有默认的透明颜色和按下时的某种颜色。这样你就会拥有一个透明的按钮,但是当被按下时会改变颜色(像Holo一样)。你还可以添加一些动画(像Holo一样)。选择器应该像这样:

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>

同时按钮应该有 android:background="@drawable/selector_transparent_button"

PS:如果你的API < 11,请使用android:divider='@android:drawable/...让你的容器具有分隔线

PS [新手]: 你应该在values/colors.xml文件中定义这些颜色


这对于 API Level 10API Level > 10 都完美地运行了! - theblang
这比编程实现更好,尽管两种方法都可以。 - Eran Goldin
1
属性“exitFadeDuration”仅适用于API级别11及以上。 - Bevor
没错 @Bevor,很不错。读者们要知道未知的 XML 标签会被忽略,所以它将在 API >=11 中使用淡化效果,对于 <11 的版本将可以正常工作。 - aacotroneo

18

对于想要无边框按钮但仍带有点击动画的人,在按钮中添加以下内容。

style="?android:attr/borderlessButtonStyle"

如果你想在它们之间添加分隔符/线,请在线性布局中添加以下内容。

style="?android:buttonBarStyle"

摘要

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

按钮栏样式的加号。顺便说一下,这就是答案。 - frostymarvelous

7
使用AppCompat库时,若需要材料化样式,请添加style="@style/Widget.AppCompat.Button.Borderless"

5

我从iosched应用程序源代码中得到了这个ButtonBar类:

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

这将是“确定”和“取消”按钮所在的LinearLayout,并处理将它们放入适当的顺序中。然后将其放入要放置按钮的布局中:
<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>

这样可以让您看到没有边框按钮的对话框外观。您可以在框架的res文件中找到这些属性。buttonBarStyle设置了垂直分隔线和填充。buttonBarButtonStyle被设置为borderlessButtonStyle用于Holo主题,但我认为这应该是最稳健的方式来显示它,因为框架想要显示它。


我该如何将(?android:attr/buttonBarButtonStyle)作为样式的一项放入styles.xml中? - lis

4

请查看主题属性buttonBarStylebuttonBarButtonStyleborderlessButtonStyle


如果我使用 buttonBarButtonStyle,我会得到一个异常 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} 不知道为什么,但是使用 selectableItemBackground 就很好用。 - Someone Somewhere

4

您也可以通过代码使按钮无边框:

TypedValue value= new TypedValue();
getApplicationContext().getTheme().resolveAttribute(android.R.attr.selectableItemBackground, value, true);
 myButton.setBackgroundResource(value.resourceId);

可以工作了,谢谢。但是 android.R.attr.selectableItemBackground 需要 API 21。有没有办法在早期版本上实现这个功能? - arenaq
它不起作用。我正在尝试设置android.R.attr.buttonBarButtonStyle的资源,但它显示找不到该资源。 - Kristy Welsh
使用 android.R.attr.selectableItemBackground - Isj

2
这是如何在不使用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);

我之前使用的是:`ContextThemeWrapper myContext = new ContextThemeWrapper(this.getActivity(), R.style.Widget_AppCompat_Button_Borderless_Colored);Button myButton = new Button(myContext);` 但它无法正常工作。在添加第二个和第三个参数后,它现在可以正常工作了! - levibostian

2

另一种在较老和较新的Android平台上都应该有效的解决方案是使用

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

按钮视图的属性。但是添加了上述代码后,按钮将不会提供触摸反馈。

为了提供触摸反馈,请将以下代码添加到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;
    }
});

我觉得它运作良好。


我会在 case MotionEvent.ACTION_UP: 下面添加 case MotionEvent.ACTION_CANCEL: - Medo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接