将drawableLeft与按钮文本对齐

Ran*_* Ma 49 android android-layout

这是我的布局:

在此输入图像描述

我面临的问题是可绘制的复选标记.我如何在文本旁边对齐它们,它们都在按钮的中心?这是XML:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".PostAssignmentActivity" >

    <LinearLayout
        style="?android:attr/buttonBarStyle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:orientation="horizontal" >

        <Button
            style="?android:attr/buttonBarButtonStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:drawableLeft="@drawable/ic_checkmark_holo_light"
            android:text="Post" />

        <Button
            style="?android:attr/buttonBarButtonStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Cancel" />
    </LinearLayout>

</RelativeLayout>
Run Code Online (Sandbox Code Playgroud)

应用android:gravity ="center_vertical"拉动文本并将其绘制在一起,但随后文本不再在中心对齐.

Bri*_*ell 67

解决方案1

设置android:paddingLeft在第一个按钮内.这将迫使drawableLeftpaddingLeft量到右侧.这是快速/黑客的解决方案.

解决方案2

而不是使用ButtonView,使用包含textview和imageview的LinearLayout.这是一个更好的解决方案.它为复选标记的定位提供了更大的灵活性.

用以下代码替换ButtonView.您需要使用LinearLayoutTextView使用,buttonBarButtonStyle以便选择时背景颜色正确且文本大小正确.您需要为子项设置android:background="#0000",以便只有LinearLayout处理背景着色.

<LinearLayout
    style="?android:attr/buttonBarButtonStyle"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:orientation="horizontal" >
    <ImageView 
        style="?android:attr/buttonBarButtonStyle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:clickable="false"
        android:background="#0000"
        android:src="@drawable/ic_checkmark_holo_light"/>
    <TextView
        style="?android:attr/buttonBarButtonStyle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" 
        android:clickable="false"
        android:background="#0000"
        android:text="Done" />
</LinearLayout>
Run Code Online (Sandbox Code Playgroud)

这是我尝试这个时拍摄的一些截图.

在此输入图像描述 在此输入图像描述 在此输入图像描述

  • 具有嵌套LinearLayouts的深层视图层次结构在ListViews中出于性能原因是一个坏主意.我不认为这应该是一个问题. (5认同)

Gre*_*nis 32

如果不提出不可接受的权衡,这些解决方案都不能正常工作(创建一个带有视图的布局?不是一个好主意).那么为什么不自己动手呢?这就是我得到的:

在此输入图像描述

attrs.xml用这个创建一个:

<resources>
    <declare-styleable name="IconButton">
        <attr name="iconSrc" format="reference" />
        <attr name="iconSize" format="dimension" />
        <attr name="iconPadding" format="dimension" />
    </declare-styleable>
</resources>
Run Code Online (Sandbox Code Playgroud)

这允许在我们的新视图中创建具有特定大小的图标,文本填充和图像.视图代码如下所示:

public class IconButton extends Button {
    private Bitmap mIcon;
    private Paint mPaint;
    private Rect mSrcRect;
    private int mIconPadding;
    private int mIconSize;

    public IconButton(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context, attrs);
    }

    public IconButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

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

    @Override
    protected void onDraw(Canvas canvas) {
        int shift = (mIconSize + mIconPadding) / 2;

        canvas.save();
        canvas.translate(shift, 0);

        super.onDraw(canvas);

        if (mIcon != null) {
            float textWidth = getPaint().measureText((String)getText());
            int left = (int)((getWidth() / 2f) - (textWidth / 2f) - mIconSize - mIconPadding);
            int top = getHeight()/2 - mIconSize/2;

            Rect destRect = new Rect(left, top, left + mIconSize, top + mIconSize);
            canvas.drawBitmap(mIcon, mSrcRect, destRect, mPaint);
        }

        canvas.restore();
    }

    private void init(Context context, AttributeSet attrs) {
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.IconButton);

        for (int i = 0; i < array.getIndexCount(); ++i) {
            int attr = array.getIndex(i);
            switch (attr) {
                case R.styleable.IconButton_iconSrc:
                    mIcon = drawableToBitmap(array.getDrawable(attr));
                    break;
                case R.styleable.IconButton_iconPadding:
                    mIconPadding = array.getDimensionPixelSize(attr, 0);
                    break;
                case R.styleable.IconButton_iconSize:
                    mIconSize = array.getDimensionPixelSize(attr, 0);
                    break;
                default:
                    break;
            }
        }

        array.recycle();

        //If we didn't supply an icon in the XML
        if(mIcon != null){
            mPaint = new Paint();
            mSrcRect = new Rect(0, 0, mIcon.getWidth(), mIcon.getHeight());
        }
    }

    public static Bitmap drawableToBitmap (Drawable drawable) {
        if (drawable instanceof BitmapDrawable) {
            return ((BitmapDrawable)drawable).getBitmap();
        }

        Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
        drawable.draw(canvas);

        return bitmap;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后它可以像这样使用:

<com.example.grennis.myapplication.IconButton
    android:layout_width="200dp"
    android:layout_height="64dp"
    android:text="Delete"
    app:iconSrc="@android:drawable/ic_delete"
    app:iconSize="32dp"
    app:iconPadding="6dp" />
Run Code Online (Sandbox Code Playgroud)

这适合我.


小智 15

这是一个干净简单的方法,没有做任何花哨的事情,以实现一个比图像和文本居中的内容宽得多的按钮的结果.

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:clickable="true"
    android:background="@drawable/button_background_selector">

    <Button
        android:layout_centerInParent="true"
        android:gravity="center"
        android:duplicateParentState="true"
        android:layout_width="wrap_content"
        android:text="New User"
        android:textSize="15sp"
        android:id="@android:id/button1"
        android:textColor="@android:color/white"
        android:drawablePadding="6dp"
        android:drawableLeft="@drawable/add_round_border_32x32"
        android:layout_height="64dp" />

</RelativeLayout>
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


Leo*_*der 15

您可以使用 <com.google.android.material.button.MaterialButton/>.
https://material.io/develop/android/components/material-button/

它最终允许设置图标重力。

 <com.google.android.material.button.MaterialButton
        android:layout_width="match_parent"
        android:layout_height="48dp"
        android:layout_marginStart="16dp"
        android:layout_marginEnd="16dp"
        android:gravity="center"
        android:text="Awesome button"
        app:icon="@drawable/your_icon"
        app:iconGravity="textStart" />
Run Code Online (Sandbox Code Playgroud)


Bob*_*son 10

在我们的例子中,我们想使用默认的Button类(继承其各种样式和行为),我们需要能够在代码中创建按钮.此外,在我们的例子中,我们可以有文本,图标(左侧可绘制)或两者.

当按钮宽度比wrap_content宽时,目标是将图标和/或文本作为一个组居中.

public class CenteredButton extends Button
{
    public CenteredButton(Context context, AttributeSet attrs, int defStyleAttr)
    {
        super(context, attrs, defStyleAttr);

        // We always want our icon and/or text grouped and centered.  We have to left align the text to
        // the (possible) left drawable in order to then be able to center them in our onDraw() below.
        //
        setGravity(Gravity.LEFT|Gravity.CENTER_VERTICAL);
    }

    @Override
    protected void onDraw(Canvas canvas)
    {
        // We want the icon and/or text grouped together and centered as a group.

        // We need to accommodate any existing padding
        //
        float buttonContentWidth = getWidth() - getPaddingLeft() - getPaddingRight();

        // In later versions of Android, an "all caps" transform is applied to buttons.  We need to get
        // the transformed text in order to measure it.
        //
        TransformationMethod method = getTransformationMethod();
        String buttonText = ((method != null) ? method.getTransformation(getText(), this) : getText()).toString();
        float textWidth = getPaint().measureText(buttonText);

        // Compute left drawable width, if any
        //
        Drawable[] drawables = getCompoundDrawables();
        Drawable drawableLeft = drawables[0];
        int drawableWidth = (drawableLeft != null) ? drawableLeft.getIntrinsicWidth() : 0;

        // We only count the drawable padding if there is both an icon and text
        //
        int drawablePadding = ((textWidth > 0) && (drawableLeft != null)) ? getCompoundDrawablePadding() : 0;

        // Adjust contents to center
        //
        float bodyWidth = textWidth + drawableWidth + drawablePadding;
        canvas.translate((buttonContentWidth - bodyWidth) / 2, 0);

        super.onDraw(canvas);
    }
}
Run Code Online (Sandbox Code Playgroud)


Ali*_*ran 8

这是我的代码,工作完美.

<Button
    android:id="@+id/button"
    android:layout_width="200dp"
    android:layout_height="50dp"
    android:layout_gravity="center"
    android:background="@drawable/green_btn_selector"
    android:gravity="left|center_vertical"
    android:paddingLeft="50dp"
    android:drawableLeft="@drawable/plus"
    android:drawablePadding="5dp"
    android:text="@string/create_iou"
    android:textColor="@color/white" />
Run Code Online (Sandbox Code Playgroud)

  • 这仅在按钮为设置大小时才有效. (5认同)
  • 出于可访问性原因,按钮也更好.使用辅助功能的用户不知道他们应该在其内部使用ImageView和TextView按下LinearLayout. (2认同)