Làm thế nào để tạo các nút không viền tiêu chuẩn (như trong hướng dẫn thiết kế đã đề cập)?


113

Tôi chỉ đang kiểm tra các hướng dẫn thiết kế và tự hỏi về các nút không viền. Tôi lục lọi và cố gắng tìm nguồn nhưng không thể tự mình tổng hợp lại được. Đây có phải là tiện ích Nút bình thường nhưng bạn thêm kiểu tùy chỉnh (mặc định của Android) không? Làm thế nào để tạo các nút không viền này (tất nhiên bạn có thể đặt nền trống, nhưng sau đó tôi không có dải phân cách)?

Đây liên kết đến các nguyên tắc thiết kế:

nhập mô tả hình ảnh ở đây


Câu trả lời:


163

Để xóa một số nhầm lẫn:

Điều này được thực hiện theo 2 bước: Đặt thuộc tính nền nút thành android: attr / selectableItemBackground tạo cho bạn một nút có phản hồi nhưng không có nền.

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

Đường phân chia nút không viền khỏi bố cục còn lại của bạn được thực hiện bởi một chế độ xem có nền android: attr / dividerVertical

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

Để hiểu rõ hơn ở đây là bố cục cho tổ hợp nút OK / Hủy không viền ở cuối màn hình của bạn (như trong hình bên phải ở trên).

<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
Đáng chỉ ra: giải pháp này chỉ hoạt động cho API cấp 11+.

9
Nếu bạn sử dụng HoloEverywhere thì nó hoạt động cho API cấp 7+. Bạn phải thay đổi ?android:attr/selectableItemBackgroundcho ?attr/selectableItemBackground?android:attr/dividerVerticalcho?attr/dividerVertical
Brais Gabin

1
?android:attr/dividerVerticalfor?attr/dividerVerticalcũng làm việc cho abs
oscarthecat


22

Câu trả lời muộn, nhưng nhiều lượt xem. Vì các API <11 vẫn chưa chết, đối với những người quan tâm đây là một mẹo nhỏ.

Để hộp đựng của bạn có màu sắc mong muốn (có thể trong suốt). Sau đó, cung cấp cho các nút của bạn một bộ chọn với màu trong suốt mặc định và một số màu khi được nhấn. Bằng cách đó, bạn sẽ có một nút trong suốt, nhưng sẽ thay đổi màu sắc khi được nhấn (như nút holo). Bạn cũng có thể thêm một số hoạt ảnh (như holo's). Bộ chọn phải giống như sau:

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>

Và nút phải có android:background="@drawable/selector_transparent_button"

PS: cho phép vùng chứa của bạn có các bộ chia ( android:divider='@android:drawable/...đối với API <11)

PS [Người mới]: bạn nên xác định các màu đó trong giá trị / màu sắc.xml


Điều này hoạt động hoàn hảo cho cả hai API Level 10API Level > 10!
theblang

Điều này tốt hơn là làm theo chương trình mặc dù cả hai đều hoạt động.
Eran Goldin

1
Thuộc tính "exitFadeDuration" chỉ được sử dụng trong API cấp 11 trở lên.
Bevor

yep @Bevor, hay quá. Độc giả xem xét rằng các thẻ xml chưa biết được bỏ qua vì vậy nó sẽ sử dụng mờ dần cho api> = 11, và chỉ làm việc cho <11
aacotroneo

18

Đối với những người muốn các nút không viền nhưng vẫn hoạt hình khi nhấp vào. Thêm điều này vào nút.

style="?android:attr/borderlessButtonStyle"

Nếu bạn muốn có một dải phân cách / dòng giữa chúng. Thêm điều này trong bố cục tuyến tính.

style="?android:buttonBarStyle"

Tóm lược

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

cộng cho buttonBarStyle. và đây là câu trả lời btw.
frostymarvelous

7

Đối với material style, hãy thêm style="@style/Widget.AppCompat.Button.Borderless"khi sử dụng thư viện AppCompat.


5

Từ nguồn ứng dụng iosched, tôi đã nghĩ ra ButtonBarlớp này :

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

Đây sẽ là nơi LinearLayoutmà các nút "OK" và "Cancel" đi vào và sẽ xử lý việc đặt chúng theo thứ tự thích hợp. Sau đó, đặt nó vào bố cục mà bạn muốn các nút trong đó:

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

Điều này cung cấp cho bạn giao diện của hộp thoại với các nút không viền. Bạn có thể tìm thấy các thuộc tính này trong res trong framework. buttonBarStylelàm ngăn cách dọc và đệm. buttonBarButtonStyleđược đặt như borderlessButtonStylecho chủ đề Holo, nhưng tôi tin rằng đây sẽ là cách mạnh mẽ nhất để hiển thị nó như khuôn khổ muốn hiển thị nó.


làm thế nào tôi có thể đặt cái này (? android: attr / buttonBarButtonStyle) trong styles.xml dưới dạng mục của một phong cách?
lis

4

Nhìn vào chủ đề thuộc tính buttonBarStyle, buttonBarButtonStyleborderlessButtonStyle.


Nếu tôi sử dụng, buttonBarButtonStyletôi nhận được một ngoại lệ 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}Không biết tại sao, nhưng việc sử dụng có selectableItemBackgroundtác dụng kỳ diệu.
Ai đó ở đâu đó

4

Bạn cũng có thể làm cho các nút không có đường viền thông qua mã:

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

Nó đang hoạt động, cảm ơn. Nhưng android.R.attr.selectableItemBackgroundyêu cầu API 21. Bất kỳ ý tưởng nào về cách thực hiện điều này trên các phiên bản trước đó?
Arenaq

Nó không hoạt động. Tôi đang cố gắng đặt tài nguyên của android.R.attr.buttonBarButtonStyle và nó thông báo rằng không thể tìm thấy tài nguyên.
Kristy Welsh

sử dụng android.R.attr.selectableItemBackground
Isj

2

Đối với những người muốn tạo nút không viền theo lập trình cho API của> = 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);

Điều này tốt hơn, đơn giản hơn giải pháp của lsj. Just setBackgroundResource (0)
jk7

2

Một giải pháp khác sẽ hoạt động trên cả nền tảng Android cũ hơn và mới hơn là sử dụng

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

thuộc tính cho dạng xem Nút. Nhưng sau khi thêm nút dòng trên sẽ không cung cấp phản hồi cảm ứng.

Để cung cấp phản hồi chạm, hãy thêm mã sau vào lớp Hoạt động

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;
    }
});

Nó hoạt động tốt cho tôi.


Tôi cũng sẽ thêm vào case MotionEvent.ACTION_CANCEL: bên dưới case MotionEvent.ACTION_UP: .
Medo

2

Đối với bất kỳ ai vẫn đang tìm kiếm:

kế thừa phong cách của riêng bạn cho thanh nút Holo:

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

hoặc Holo Light:

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

và đối với các nút Holo không viền:

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

hoặc Holo Light:

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

2

Đây là cách bạn tạo nút không viền (phẳng) theo lập trình mà không cần sử dụng 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);

Tôi đã sử dụng: ContextThemeWrapper myContext = new ContextThemeWrapper(this.getActivity(), R.style.Widget_AppCompat_Button_Borderless_Colored); Button myButton = new Button(myContext); và nó sẽ không hoạt động. Sau khi thêm tham số thứ 2 và thứ 3, nó đang hoạt động!
levibostian

1

Sử dụng mã bên dưới trong tệp xml của bạn. Sử dụng android: background = "# 00000000" để có màu trong suốt.

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

1

Bạn có thể sử dụng Thư viện hỗ trợ AppCompat cho Nút không viền.

Bạn có thể tạo một Nút không viền như sau:

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

Bạn có thể tạo Nút màu không viền như sau:

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

0

Đối với một số lý do style="Widget.Holo.Button.Borderless"cũng không android:background="?android:attr/selectableItemBackground"làm việc cho tôi. Nói chính xác hơn, Widget.Holo.Button.Borderlessnó đã hoạt động trên Android 4.0 nhưng không hoạt động trên Android 2.3.3. Thủ thuật đối với tôi là gì trên cả hai phiên bản android:background="@drawable/transparent"và XML này trong res / drawable / transparent.xml:

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

Đi thẳng qua lối tiếp cận tường.


2
Đặt nền thành @android: color / transparent phù hợp với tôi mà không cần thêm tệp XML.
Nicolai Buch-Andersen

Điều này không bao gồm cách lấy dải phân cách.
Navarr

3
@Navarr theo câu trả lời của Blundell, dải phân cách không phải là một phần của "nút không viền". Cũng không nên vì các nút và bất kỳ lớp chế độ xem nào khác không được thông báo về các thành phần GUI xung quanh. Đó là trách nhiệm của container. Trong các bình luận cho bài đăng của Blundell có một liên kết đến những gì có vẻ là bố cục mục chi tiết liên hệ ICS. Có thêm chế độ xem (với id vertical_divider) để hiển thị dải phân cách. Không có giải pháp nào cho bộ chia tự động mặc dù có một android:background="?android:attr/dividerVertical"mẹo nhỏ.
Emperor Orionii,

Câu hỏi của OP đề cập đến "Các nút không viền" của Android UX và trong tất cả các ví dụ, chúng đều có dải phân cách - dường như là một phần của buttonBarStyle. Mặc dù Bạn đã cung cấp cho tôi một số thông tin rất hữu ích, cảm ơn bạn.
Navarr

0

Một trình chiếu tuyệt vời về cách đạt được hiệu quả mong muốn từ Google Nick Butcher (bắt đầu từ trang trình bày 20). Anh ấy sử dụng android tiêu chuẩn @attrđể tạo kiểu cho nút và dải phân cách.


Lưu ý rằng các câu trả lời chỉ có liên kết không được khuyến khích, các câu trả lời SO phải là điểm cuối của quá trình tìm kiếm giải pháp (so với một điểm dừng khác của các tham chiếu, có xu hướng cũ dần theo thời gian). Vui lòng xem xét thêm một bản tóm tắt độc lập ở đây, giữ liên kết làm tài liệu tham khảo.
kleopatra

0

Thêm vào câu trả lời trên cùng, bạn cũng có thể sử dụng các dạng xem có màu nền xám đậm trong Bố cục Tuyến tính như vậy.

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

Nếu đường thẳng của bạn nằm ngang, bạn sẽ muốn đặt chiều cao thành 1dip và chiều rộng để khớp với đường chính và ngược lại nếu đường thẳng đứng.


0

Nếu bạn muốn đạt được điều tương tự theo lập trình:

(đây là C # nhưng dễ dàng chuyển đổi sang Java)

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

Trận đấu

    <Button
       style="@style/Widget.AppCompat.Button.Borderless.Colored"
    .../>

0

Hãy thử mã này, để xóa nền có thể vẽ (@ drawable / bg) theo chương trình, chỉ cần chúng ta cung cấp null làm tham số.

Button btn= new Button(this);
btn.setText("HI");
btn.setBackground(null);

1
Cảm ơn bạn vì đoạn mã này, đoạn mã này có thể cung cấp một số trợ giúp hạn chế, tức thì. Một lời giải thích phù hợp sẽ cải thiện đáng kể giá trị lâu dài của nó bằng cách chỉ ra lý do tại sao đây là một giải pháp tốt cho vấn đề và sẽ giúp nó hữu ích hơn cho những người đọc trong tương lai với những câu hỏi tương tự khác. Vui lòng chỉnh sửa câu trả lời của bạn để thêm một số giải thích, bao gồm cả những giả định bạn đã đưa ra.
NOhs
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.