2012-04-01 28 views
6

tôi đã bị mắc kẹt trong một vấn đề lẻ với Android - Tôi muốn có một nút trông như thế này:Android: làm thế nào để tạo ra một nút với hình ảnh và văn bản được cả trung

|-----------------------------------------------------------------------| 
|     [icon] <5px> [text text text]      | 
|-----------------------------------------------------------------------| 

và nhóm ([biểu tượng] < 5px> [văn bản văn bản]] sẽ được căn giữa. Lưu ý rằng 5px được sử dụng giống như một trình giữ chỗ cho bất kỳ phần đệm nào bạn muốn có giữa biểu tượng và văn bản

Tôi tìm thấy một số câu trả lời ở đây là thu hút nhiều hoặc ít xung quanh hoặc đặt nền (mà tôi không muốn do tôi có một nền tảng khác) hoặc sử dụng thuộc tính android: drawableLeft để đặt biểu tượng.

Tuy nhiên, có vẻ như tài liệu của phương pháp setCompoundDrawablesWithIntrinsicBounds là một chút gây hiểu nhầm (see here). Nó nói rằng hình ảnh được đặt ở bên trái/phải/trên/dưới cùng của TEXT mà không đúng. Biểu tượng được đặt ở phía tương ứng của nút. Ví dụ:

Thiết lập android: drawableLeft tài sản đặt biểu tượng vào vị trí bên trái nhất và được tôi này (với CENTER trọng lực):

|-----------------------------------------------------------------------| 
| [icon]      [text text text]       | 
|-----------------------------------------------------------------------| 

hay này (với trọng lực trái):

|-----------------------------------------------------------------------| 
| [icon] [text text text]            | 
|-----------------------------------------------------------------------| 

Cả hai đều xấu xí như địa ngục :(

tôi tìm thấy một workaround trông như thế này:

public static void applyTextOffset(Button button, int buttonWidth) { 
    int textWidth = (int) button.getPaint().measureText(button.getText().toString()); 
    int padding = (buttonWidth/2) - ((textWidth/2) + Constants.ICON_WIDTH + Constants.ICON_TO_TEXT_PADDING); 
    button.setPadding(padding, 0, 0, 0); 
    button.setCompoundDrawablePadding(-padding); 
} 

Và nó hoạt động nhiều hay ít nhưng tôi không thấy nó theo ý thích của tôi vì những lý do sau đây:

  • nó đòi hỏi phải biết chiều rộng nút. Với các nút có kích thước tự động, nó sẽ không được biết cho đến khi bố cục thực tế được thực hiện. Google khuyên bạn nên sử dụng trình nghe để tìm hiểu chiều rộng thực tế sau khi hiển thị xong nhưng điều này làm phức tạp mã. không có
  • Tôi cảm thấy như tôi đang đảm nhận trách nhiệm bố trí từ động cơ bố trí Android

Là một giải pháp thanh lịch hơn?

+0

Hy vọng điều này, do đó bạn đã giải quyết vấn đề bạn – Ishu

Trả lời

10

Bạn có thể sử dụng lớp con Button sau để đạt được hiệu ứng này.

  1. Dán lớp này vào dự án của bạn và tinh chỉnh tên gói nếu muốn.
package com.phillipcalvin.iconbutton; 

    import android.content.Context; 
    import android.content.res.TypedArray; 
    import android.graphics.Rect; 
    import android.graphics.Paint; 
    import android.graphics.drawable.Drawable; 
    import android.util.AttributeSet; 
    import android.widget.Button; 

    public class IconButton extends Button { 
     protected int drawableWidth; 
     protected DrawablePositions drawablePosition; 
     protected int iconPadding; 

     // Cached to prevent allocation during onLayout 
     Rect bounds; 

     private enum DrawablePositions { 
     NONE, 
     LEFT, 
     RIGHT 
     } 

     public IconButton(Context context) { 
     super(context); 
     bounds = new Rect(); 
     } 

     public IconButton(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     bounds = new Rect(); 
     } 

     public IconButton(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
     bounds = new Rect(); 
     } 

     public void setIconPadding(int padding) { 
     iconPadding = padding; 
     requestLayout(); 
     } 

     @Override 
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 
     super.onLayout(changed, left, top, right, bottom); 

     Paint textPaint = getPaint(); 
     String text = getText().toString(); 
     textPaint.getTextBounds(text, 0, text.length(), bounds); 

     int textWidth = bounds.width(); 
     int contentWidth = drawableWidth + iconPadding + textWidth; 

     int contentLeft = (int)((getWidth()/2.0) - (contentWidth/2.0)); 
     setCompoundDrawablePadding(-contentLeft + iconPadding); 
     switch (drawablePosition) { 
     case LEFT: 
      setPadding(contentLeft, 0, 0, 0); 
      break; 
     case RIGHT: 
      setPadding(0, 0, contentLeft, 0); 
      break; 
     default: 
      setPadding(0, 0, 0, 0); 
     } 
     } 

     @Override 
     public void setCompoundDrawablesWithIntrinsicBounds(Drawable left, Drawable top, Drawable right, Drawable bottom) { 
     super.setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom); 
     if (null != left) { 
      drawableWidth = left.getIntrinsicWidth(); 
      drawablePosition = DrawablePositions.LEFT; 
     } else if (null != right) { 
      drawableWidth = right.getIntrinsicWidth(); 
      drawablePosition = DrawablePositions.RIGHT; 
     } else { 
      drawablePosition = DrawablePositions.NONE; 
     } 
     requestLayout(); 
     } 
    } 

2. Sửa đổi bố trí của bạn để sử dụng lớp con này mới thay vì đơn giản Button:

<com.phillipcalvin.iconbutton.IconButton 
     android:id="@+id/search" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
     android:drawableLeft="@drawable/search" 
     android:text="@string/search" /> 

3. Nếu bạn muốn thêm đệm giữa drawable và các văn bản, thêm dòng sau vào hoạt động của bạn là onCreate:

// Anywhere after setContentView(...) 
    IconButton button = (IconButton)findViewById(R.id.search); 
    button.setIconPadding(10); 

Phân lớp này cũng hỗ trợ drawableRight. Nó không hỗ trợ nhiều hơn một drawable.

Nếu bạn muốn thêm nhiều tính năng, chẳng hạn như khả năng để xác định iconPadding trực tiếp trong cách bố trí XML của bạn, tôi có một library that supports this.

-3

tôi đã cố gắng này trong nhật thực và nó nói hùng hồn không có lỗi:

<Button android:id="@+id/test" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:background="@android:color/transparent" > 
<LinearLayout 
    android:orientation="vertical" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:layout_weight="1" 
    android:gravity="center" 
    android:background="@android:color/transparent" > 

    </LinearLayout> 
    </Button> 

Do đó, tôi cho rằng bạn có thể thêm một xem hình ảnh và văn bản trong một bố cục, bản thân bên trong một nút, và trung tâm bố trí.

Trân trọng.

+0

Chỉ cần ngang – Gangnus

+0

tôi sẽ nói nya nya nya, nếu bạn không phải là hoàn toàn đúng. – pouzzler

+0

Và bạn có nó theo chiều dọc :-) – Gangnus

0

Bạn cũng có thể xem xét sử dụng chế độ xem tùy chỉnh để tạo nút tùy chỉnh.

Điều này có thể ở bất kỳ đâu từ dễ đến vô cùng phức tạp.

Sẽ dễ dàng nếu tất cả những gì bạn cần làm là ghi đè onDraw(). Sẽ phức tạp hơn nếu bạn cần bố trí nhiều chế độ xem.

+0

Tôi sẽ chấp nhận câu trả lời này bởi vì nó là chính xác và cung cấp một giải pháp, mặc dù tôi không chắc chắn tôi có thể clasify nó như là một "thanh lịch hơn" giải pháp. Quan điểm của tôi là nó thực sự là một cảm giác phổ biến để mong đợi các văn bản và biểu tượng được tập trung khi bạn gọi setGravity (CENTER) và tạo các thành phần tùy chỉnh chỉ cho THAT là một chút của một overkill. – vap78

0

Đơn giản chỉ cần cách là viết Button trong LinearLayout. Một cái gì đó như

<LinearLayout 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:gravity="center"> 

      <Button 
       android:layout_width="wrap_content" 
       android:layout_height="wrap_content" 
       android:drawableLeft="@drawable/ic_left" 
       android:drawablePadding="5dp" 
       android:duplicateParentState="true" 
       android:text="Button text"/> 

     </LinearLayout> 
Các vấn đề liên quan