幅を「親を埋める」に設定したAndroidボタンのアイコンとテキストを中央に配置する方法


118

アイコンとテキストを中央に配置したAndroidボタンが欲しいのですが。drawableLeft属性を使用して画像を設定しています。これは、ボタンの幅がの場合に適切に機能しますが、最大幅"wrap_content"にストレッチする必要があるため、width を使用します"fill_parent"。これにより、アイコンがボタンの左側にまっすぐに移動します。アイコンとテキストの両方をボタンの中央に配置します。

私はパディングを設定しようとしましたが、これは固定値を与えることしかできないので、私が必要とするものではありません。アイコンとテキストを中央に揃える必要があります。

<Button 
    android:id="@+id/startTelemoteButton" 
    android:text="@string/start_telemote"
    android:drawableLeft="@drawable/start"
    android:paddingLeft="20dip"
    android:paddingRight="20dip"            
    android:width="fill_parent"
    android:heigh="wrap_content" />

どのようにしてそれを達成できるかについての提案はありますか?


これに対する簡単な解決策がない可能性はありますか?そこにアイコンのある9patchボタンのimgを試す必要がありますか?
jloriente

これは解決策かもしれません。ボタンのテキストはローカライズされますか、それとも静的ですか?
Octavian A. Damiean

ローカライズされています。これに対する他の解決策はありませんか?9パッチでなんとかできましたが、ロケールの変更時に問題が発生しました。
jloriente

ドローアブルTOPでボタンを使用し、それにパディングを追加するのはどうですか?
フランチェスコ

不適切なフレームワークの設計
Muhammad Babar 2015

回答:


75

android:drawableLeftは常にandroid:paddingLeftを左の境界からの距離として維持します。ボタンがandroid:width = "wrap_content"に設定されていない場合、ボタンは常に左側にぶら下がります。

Android 4.0(APIレベル14)では、android:drawableStart属性を使用して、テキストの先頭にドローアブルを配置できます。私が思いついた唯一の下位互換性のあるソリューションは、ImageSpanを使用してText + Image Spannableを作成することです。

Button button = (Button) findViewById(R.id.button);
Spannable buttonLabel = new SpannableString(" Button Text");
buttonLabel.setSpan(new ImageSpan(getApplicationContext(), R.drawable.icon,      
    ImageSpan.ALIGN_BOTTOM), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
button.setText(buttonLabel);

私の場合、ボタンのandroid:gravity属性も中央に表示されるように調整する必要がありました。

<Button
  android:id="@+id/button"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:minHeight="32dp"
  android:minWidth="150dp"
  android:gravity="center_horizontal|top" />

いいね。最終行はbutton.setText(buttonLabel)
AlexD '19

1
Unicodeには、Androidの文字列と互換性のある文字アイコンの広範なセットがあります。許容できるものが見つかれば、これは簡単な解決策であり、テキストサイズに合わせて調整されるという追加のボーナスがあります。たとえば、メールアイコン用のエンベロープと、通話ボタン用のいくつかの異なる電話があります。
GLee 2013年

1
私はこれが誰にとってもうまく機能していたのか混乱しています。私にとっては、2つのアイコンが描画されます...左に1つ、テキストの上部に表示される中央に1つ。
ジャスティン

11
drawableStartが機能しません。このスレッドを参照してください:stackoverflow.com/questions/15350990/… また、spannableを使用してテキストを設定すると、スタイルが無視されるようです。
Dapp、2015年

11
drawableStartは機能せず、rtlをサポートするためにAPIレベル17で追加されました
Silvia H

35

私はこの質問に答えるのが遅いのを知っていますが、これは私を助けました:

<FrameLayout
            android:layout_width="match_parent"
            android:layout_height="35dp"
            android:layout_marginBottom="5dp"
            android:layout_marginTop="10dp"
            android:background="@color/fb" >

            <Button
                android:id="@+id/fbLogin"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_gravity="center"
                android:background="@null"
                android:drawableLeft="@drawable/ic_facebook"
                android:gravity="center"
                android:minHeight="0dp"
                android:minWidth="0dp"
                android:text="FACEBOOK"
                android:textColor="@android:color/white" />
        </FrameLayout>

私はここからこの解決策を見つけました:Android UIの苦労:テキストとアイコンを中央に配置したボタンを作成する

ここに画像の説明を入力してください


6
この問題は、ボタンがフレームレイアウトの幅ではないことです。
Clive Jefferies 2014

29

使った Buttonの代わりにLinearLayoutましたOnClickListener私が使用する必要がある、のLinearLayoutにも正常に動作します。

<LinearLayout
    android:id="@+id/my_button"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/selector"
    android:gravity="center"
    android:orientation="horizontal"
    android:clickable="true">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginRight="15dp"
        android:adjustViewBounds="true"
        android:scaleType="fitCenter"
        android:src="@drawable/icon" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="Text" />

</LinearLayout>

27

以前の回答はすべて古くなっているようです

あなたは使用することができMaterialButton、アイコンの重力を設定することができますされ、今。

 <com.google.android.material.button.MaterialButton
        android:id="@+id/btnDownloadPdf"
        android:layout_width="0dp"
        android:layout_height="56dp"
        android:layout_margin="16dp"
        android:gravity="center"
        android:textAllCaps="true"
        app:backgroundTint="#fc0"
        app:icon="@drawable/ic_pdf"
        app:iconGravity="textStart"
        app:iconPadding="10dp"
        app:iconTint="#f00"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        tools:text="Download Pdf" />

ここに画像の説明を入力してください

マテリアルコンポーネントを使用するには、明らかに次のことが必要です。

依存関係を追加する implementation 'com.google.android.material:material:1.3.0-alpha01'(最新バージョンを使用)

テーマにMaterial Componentsテーマを拡張させる

<style name="AppTheme" parent="Theme.MaterialComponents.Light">
...
</style>

それができない場合は、Material Bridgeテーマから拡張してください。

<style name="AppTheme" parent="Theme.MaterialComponents.Light.Bridge">
...
</style>

ありがとう!あなたは私の日を救った!
正常に動作し

9

次のように左右にパディングを追加して調整します。

<Button
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:id="@+id/btn_facebookact_like"
            android:text="@string/btn_facebookact_like"
            android:textColor="@color/black"
            android:textAllCaps="false"
            android:background="@color/white"
            android:drawableStart="@drawable/like"
            android:drawableLeft="@drawable/like"
            android:gravity="center"
            android:layout_gravity="center"
            android:paddingLeft="40dp"
            android:paddingRight="40dp"
            />

paddingLeftとpaddingRightは、私のセンタリングに役立ちました。簡単な解決のための賛成票。
Arrie、

2
幅が動的であるという事実をどのように管理しますか?画面を回転させると、すべてのアイコンが中央に正しく配置されませんか?私は実際にこの問題に直面しています
ジャックス

これが最良の答えです!
Dody Rachmat Wicaksono

8

最近同じ問題にぶつかった。より安い解決策を見つけようとしたので、これを思いつきました。

   <LinearLayout
        android:id="@+id/linearButton"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/selector_button_translucent_ab_color"
        android:clickable="true"
        android:descendantFocusability="blocksDescendants"
        android:gravity="center"
        android:orientation="horizontal" >

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:contentDescription="@string/app_name"
            android:src="@drawable/ic_launcher" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/app_name"
            android:textColor="@android:color/white" />
    </LinearLayout>

次に、OnClickListeneronを呼び出しますLinearLayout

これは非常に一般的な問題のように思われるので、これが誰かを助けることを願っています。:)


1
これは良い考えですが、悪い解決策です。drawableLeft属性を使用して、1つのTextViewで同じことを実現できます。これにより、テキストの左側にドローアブルを表示できます。
muetzenflo 2014

@muetzenfloうん、そうだね。しかし、textViewを親の幅と一致させると、テキストを中央に配置しても、ドローアブルは左端に移動します。私が間違っているかどうか私に知らせてください。問題はそれだけです。
Ankit Popli 14

申し訳ありません。私はまさにこの問題のためにここに来て、あまりにも多くのことを試した後、フォーカスを失いました:)私は木の森を見なかったと思います。私のせい!
muetzenflo 2014

7

左のドローアブルに対応するために、それ自体を測定して描画するカスタムボタンを使用できます。ここで例と使用法を見つけてください

public class DrawableAlignedButton extends Button {

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

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

public DrawableAlignedButton(Context context, AttributeSet attrs, int style) {
    super(context, attrs, style);
}

private Drawable mLeftDrawable;

@Override
    //Overriden to work only with a left drawable.
public void setCompoundDrawablesWithIntrinsicBounds(Drawable left,
        Drawable top, Drawable right, Drawable bottom) {
    if(left == null) return;
    left.setBounds(0, 0, left.getIntrinsicWidth(), left.getIntrinsicHeight());
    mLeftDrawable = left;
}

@Override
protected void onDraw(Canvas canvas) {
    //transform the canvas so we can draw both image and text at center.
    canvas.save();
    canvas.translate(2+mLeftDrawable.getIntrinsicWidth()/2, 0);
    super.onDraw(canvas);
    canvas.restore();
    canvas.save();
    int widthOfText = (int)getPaint().measureText(getText().toString());
    int left = (getWidth()+widthOfText)/2 - mLeftDrawable.getIntrinsicWidth() - 2;
    canvas.translate(left, (getHeight()-mLeftDrawable.getIntrinsicHeight())/2);
    mLeftDrawable.draw(canvas);
    canvas.restore();
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    int height = getMeasuredHeight();
    height = Math.max(height, mLeftDrawable.getIntrinsicHeight() + getPaddingTop() + getPaddingBottom());
    setMeasuredDimension(getMeasuredWidth(), height);
}
}

使用法

<com.mypackage.DrawableAlignedButton
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:drawableLeft="@drawable/my_drawable"
        android:gravity="center"
        android:padding="7dp"
        android:text="My Text" />

リンクは、時間オーバー死ぬかもしれないとあなたは、(それはあまりにも長くはない場合)、好ましい方法でなければなりませんあなたの答えのコードを含めることができます
ルーカス・クヌース

2
あまり正確ではないが、私はそれを
理解

テキストは右に移動しますが、十分ではありません(画像がテキストに重なっています)。また、他のカスタムビューのソリューションと同様に、長いテキストを正しく受け入れません。
CoolMind 2018年

5

これは3年前に書いた私のソリューションです。ボタンにはテキストと左アイコンがあり、フレーム内にあり、ここでは実際のボタンであり、fill_parentによって拡大できます。もう一度テストすることはできませんが、当時は機能していました。おそらくButtonを使用する必要はなく、TextViewで置き換えることができますが、今はテストしないので、ここではあまり機能を変更しません。

<FrameLayout
    android:id="@+id/login_button_login"
    android:background="@drawable/apptheme_btn_default_holo_dark"
    android:layout_width="fill_parent"
    android:layout_gravity="center"
    android:layout_height="40dp">
    <Button
        android:clickable="false"
        android:drawablePadding="15dp"
        android:layout_gravity="center"
        style="@style/WhiteText.Small.Bold"
        android:drawableLeft="@drawable/lock"
        android:background="@color/transparent"
        android:text="LOGIN" />
</FrameLayout>

1
今、私はこの解決策だけではなかったことが
わかり

4

私はこの質問が少し古いことを知っていますが、おそらくあなたはまだヒントや回避策を開いています:

ボタン画像を背景、またはボタン自体をレイアウトの最初の要素として、RelativeLayout「wrap_content」を作成します。LinearLayoutを取得し、「layout_centerInParent」と「wrap_content」に設定します。次に、DrawableをImageviewとして設定します。最後に、テキスト(ロケール)でTextViewを設定します。

したがって、基本的には次のような構造になります。

RelativeLayout
  Button
    LinearLayout
      ImageView
      TextView

またはこのように:

RelativeLayout with "android-specific" button image as background
  LinearLayout
    ImageView
    TextView

この解決策には対処すべき要素がたくさんあることはわかっていますが、独自のカスタムボタンを非常に簡単に作成し、テキストとドローアブルの正確な位置を設定することもできます:)


このアプローチはうまく機能します。私の場合、必要なのは、TextViewを含むRelativeLayoutだけでした。RelativeLayoutは背景を取得し、TextViewはdrawableLeftアイコンを取得します。次にコードで:onClickListenerをRelativeLayoutにアタッチし、必要に応じてTextViewのfindViewByIdを個別に追加します
Stan Kurdziel

最初に提案された構造では、「ボタンをViewGroupにキャストできません」という例外が発生します。
Youngjae

4

それを解決する私の方法は、<View ../>動的にサイズ変更する軽量要素でボタンを囲むことを 含みました。以下は、これで実現できることのいくつかの例です。

Dev-iLによるデモ

例3のボタンのクリック可能な領域は2と同じ(つまり、スペースを含む)であり、間に「クリックできない」ギャップがない例4とは異なります。

コード:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <TextView
        android:layout_marginStart="5dp"
        android:layout_marginLeft="5dp"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="5dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textStyle="bold"
        android:text="Example 1: Button with a background color:"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="20dp"
            android:paddingEnd="20dp"
            android:layout_weight="0.3"/>
        <!-- Play around with the above 3 values to modify the clickable 
             area and image alignment with respect to text -->
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
    </LinearLayout>

    <TextView
        android:layout_marginStart="5dp"
        android:layout_marginLeft="5dp"
        android:layout_marginTop="20dp"
        android:layout_marginBottom="5dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textStyle="bold"
        android:text="Example 2: Button group + transparent layout + spacers:"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
    </LinearLayout>

    <TextView
        android:layout_marginStart="5dp"
        android:layout_marginLeft="5dp"
        android:layout_marginTop="20dp"
        android:layout_marginBottom="5dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textStyle="bold"
        android:text="Example 3: Button group + colored layout:"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@android:color/darker_gray">
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
        <Button
            style="?android:attr/buttonBarButtonStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
        <Button
            style="?android:attr/buttonBarButtonStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
        <Button
            style="?android:attr/buttonBarButtonStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
    </LinearLayout>

    <TextView
        android:layout_marginStart="5dp"
        android:layout_marginLeft="5dp"
        android:layout_marginTop="20dp"
        android:layout_marginBottom="5dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textStyle="bold"
        android:text="Example 4 (reference): Button group + no spacers:"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@android:color/darker_gray">
        <Button
            style="?android:attr/buttonBarButtonStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <Button
            style="?android:attr/buttonBarButtonStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <Button
            style="?android:attr/buttonBarButtonStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>   
    </LinearLayout>
</LinearLayout>


2

カスタムウィジェットを作成できます。

JavaクラスIButton:

public class IButton extends RelativeLayout {

private RelativeLayout layout;
private ImageView image;
private TextView text;

public IButton(Context context) {
    this(context, null);
}

public IButton(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
}

public IButton(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);

    LayoutInflater inflater = (LayoutInflater) context
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View view = inflater.inflate(R.layout.ibutton, this, true);

    layout = (RelativeLayout) view.findViewById(R.id.btn_layout);

    image = (ImageView) view.findViewById(R.id.btn_icon);
    text = (TextView) view.findViewById(R.id.btn_text);

    if (attrs != null) {
        TypedArray attributes = context.obtainStyledAttributes(attrs,R.styleable.IButtonStyle);

        Drawable drawable = attributes.getDrawable(R.styleable.IButtonStyle_button_icon);
        if(drawable != null) {
            image.setImageDrawable(drawable);
        }

        String str = attributes.getString(R.styleable.IButtonStyle_button_text);
        text.setText(str);

        attributes.recycle();
    }

}

@Override
public void setOnClickListener(final OnClickListener l) {
    super.setOnClickListener(l);
    layout.setOnClickListener(l);
}

public void setDrawable(int resId) {
    image.setImageResource(resId);
}

}

レイアウトibutton.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/btn_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true" >

<ImageView
    android:id="@+id/btn_icon"
    android:layout_width="wrap_content"
    android:layout_height="fill_parent"
    android:layout_marginRight="2dp"
    android:layout_toLeftOf="@+id/btn_text"
    android:duplicateParentState="true" />

<TextView
    android:id="@+id/btn_text"
    android:layout_width="wrap_content"
    android:layout_height="fill_parent"
    android:layout_centerInParent="true"
    android:duplicateParentState="true"
    android:gravity="center_vertical"
    android:textColor="#000000" />
</RelativeLayout>

このカスタムウィジェットを使用するには:

<com.test.android.widgets.IButton
     android:id="@+id/new"
     android:layout_width="fill_parent"         
     android:layout_height="@dimen/button_height"
     ibutton:button_text="@string/btn_new"
     ibutton:button_icon="@drawable/ic_action_new" />

カスタム属性の名前空間を提供する必要があります xmlns:ibutton = "http://schemas.android.com/apk/res/com.test.android.xxx"。com.test.android.xxxは、アプリケーション。

xmlns:android = "http://schemas.android.com/apk/res/android"の下に配置するだけです。

最後に必要なのは、attrs.xmlのカスタム属性です。

attrs.xml内

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="IButtonStyle">
        <attr name="button_text" />
        <attr name="button_icon" format="integer" />
    </declare-styleable>

    <attr name="button_text" />

</resources>

RelativeLayoutの配置に関する潜在的な問題を回避したい場合は、より適切な配置のために、LinearLayout内にカスタムボタンをラップします。

楽しい!


2

同様の問題がありましたが、テキストもラップされたレイアウトもない中央ドローアブルが必要でした。解決策は、カスタムボタンを作成し、LEFT、RIGHT、TOP、BOTTOMに加えて1つのドローアブルを追加することでした。描画可能な配置を簡単に変更して、テキストに対して希望する位置に配置できます。

CenterDrawableButton.java

public class CenterDrawableButton extends Button {
    private Drawable mDrawableCenter;

    public CenterDrawableButton(Context context) {
        super(context);
        init(context, null);
    }

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

    public CenterDrawableButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public CenterDrawableButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context, attrs);
    }


    private void init(Context context, AttributeSet attrs){
        //if (isInEditMode()) return;
        if(attrs!=null){
            TypedArray a = context.getTheme().obtainStyledAttributes(
                    attrs, R.styleable.CenterDrawableButton, 0, 0);

            try {
                setCenterDrawable(a.getDrawable(R.styleable.CenterDrawableButton_drawableCenter));

            } finally {
                a.recycle();
            }

        }
    }

    public void setCenterDrawable(int center) {
        if(center==0){
            setCenterDrawable(null);
        }else
        setCenterDrawable(getContext().getResources().getDrawable(center));
    }
    public void setCenterDrawable(@Nullable Drawable center) {
        int[] state;
        state = getDrawableState();
        if (center != null) {
            center.setState(state);
            center.setBounds(0, 0, center.getIntrinsicWidth(), center.getIntrinsicHeight());
            center.setCallback(this);
        }
        mDrawableCenter = center;
        invalidate();
        requestLayout();
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if(mDrawableCenter!=null) {
            setMeasuredDimension(Math.max(getMeasuredWidth(), mDrawableCenter.getIntrinsicWidth()),
                    Math.max(getMeasuredHeight(), mDrawableCenter.getIntrinsicHeight()));
        }
    }
    @Override
    protected void drawableStateChanged() {
        super.drawableStateChanged();
        if (mDrawableCenter != null) {
            int[] state = getDrawableState();
            mDrawableCenter.setState(state);
            mDrawableCenter.setBounds(0, 0, mDrawableCenter.getIntrinsicWidth(),
                    mDrawableCenter.getIntrinsicHeight());
        }
        invalidate();
    }

    @Override
    protected void onDraw(@NonNull Canvas canvas) {
        super.onDraw(canvas);

        if (mDrawableCenter != null) {
            Rect rect = mDrawableCenter.getBounds();
            canvas.save();
            canvas.translate(getWidth() / 2 - rect.right / 2, getHeight() / 2 - rect.bottom / 2);
            mDrawableCenter.draw(canvas);
            canvas.restore();
        }
    }
}

attrs.xml

<resources>
    <attr name="drawableCenter" format="reference"/>
    <declare-styleable name="CenterDrawableButton">
        <attr name="drawableCenter"/>
    </declare-styleable>
</resources>

使用法

<com.virtoos.android.view.custom.CenterDrawableButton
            android:id="@id/centerDrawableButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:drawableCenter="@android:drawable/ic_menu_info_details"/>

ありがとう!それが私が探していたものです。
MistaGreen 2015

この質問で私を助けてください、stackoverflow.com / questions
35912539 /…

このソリューションは、ボタンの中央、中央のテキストの上にドローアブルを配置します。
CoolMind 2018年

1
<style name="captionOnly">
    <item name="android:background">@null</item>
    <item name="android:clickable">false</item>
    <item name="android:focusable">false</item>
    <item name="android:minHeight">0dp</item>
    <item name="android:minWidth">0dp</item>
</style>

<FrameLayout
   style="?android:attr/buttonStyle"
   android:layout_width="match_parent"
   android:layout_height="wrap_content" >

    <Button
       style="@style/captionOnly"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_gravity="center"
       android:drawableLeft="@android:drawable/ic_delete"
       android:gravity="center"
       android:text="Button Challenge" />
</FrameLayout>

FrameLayoutをLinearLayoutに配置し、方向をHorizo​​ntalに設定します。


1

ボタンをLinearLayoutの上に置くことができます

<RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="@dimen/activity_login_fb_height"
        android:background="@mipmap/bg_btn_fb">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center">
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/lblLoginFb"
                android:textColor="@color/white"
                android:drawableLeft="@mipmap/icon_fb"
                android:textSize="@dimen/activity_login_fb_textSize"
                android:text="Login with Facebook"
                android:gravity="center" />
        </LinearLayout>
        <Button
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/btnLoginFb"
            android:background="@color/transparent"
            />
    </RelativeLayout>

0

android:gravity = "center_horizo​​ntal"を実行するとどうなりますか?


5
動作しません。テキストはやや中央揃えですが、drawableLeftは左側に固定されています。
Peter Ajtai、2011年

0

私はandroid:gravity = "centre"でうまくいくと思います


6
私にはうまくいきません。テキストを中央揃えにしますが、drawableLeftは左端に残ります。
Peter Ajtai、2011年

同じ親の下でアイコンとテキストを宣言する必要があります。親にはandroid:gravity = "centre"を使用します
devanshu_kaushik

0

Rodjaによって提案されたように、4.0より前のバージョンでは、テキストをドローアブルで中央に配置する直接的な方法はありません。そして、実際にpadding_leftの値を設定すると、ドローアブルがボーダーから離れます。したがって、私の提案は、実行時にドローアブルが必要とする左ボーダーからのピクセル数を正確に計算し、setPaddingを使用してそれを渡すことです。 計算は次のようになります。

int paddingLeft = (button.getWidth() - drawableWidth - textWidth) / 2;

ドローアブルの幅は固定されており、それを調べたり、テキストの幅を計算したり推測したりできます。

最後に、画面密度でパディング値を乗算する必要があります。これは、 DisplayMetrics



0

パブリッククラスDrawableCenterTextViewはTextView {

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

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

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

@Override
protected void onDraw(Canvas canvas) {
    Drawable[] drawables = getCompoundDrawables();
    if (drawables != null) {
        Drawable drawableLeft = drawables[0];
        Drawable drawableRight = drawables[2];
        if (drawableLeft != null || drawableRight != null) {
            float textWidth = getPaint().measureText(getText().toString());
            int drawablePadding = getCompoundDrawablePadding();
            int drawableWidth = 0;
            if (drawableLeft != null)
                drawableWidth = drawableLeft.getIntrinsicWidth();
            else if (drawableRight != null) {
                drawableWidth = drawableRight.getIntrinsicWidth();
            }
            float bodyWidth = textWidth + drawableWidth + drawablePadding;
            canvas.translate((getWidth() - bodyWidth) / 2, 0);
        }
    }
    super.onDraw(canvas);
}

}


これは私にはまったくうまくいきませんでした。例を示してもらえますか?多分私はそれを正しく使用していません
Android開発者

0

汚い修正。

android:paddingTop="10dp"
android:drawableTop="@drawable/ic_src"

右のパディングを理解することは目的を解決します。ただし、さまざまな画面の場合は、異なるパディングを使用し、それをそれぞれの値フォルダーのdimensリソースに配置します。


0

使用RelativeLayout(コンテナ)とアンドロイド:layout_centerHorizo​​ntal = "true"を 、私のサンプル:

                <RelativeLayout
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1" >

                    <CheckBox
                        android:layout_width="wrap_content"
                        android:layout_height="match_parent"
                        android:layout_centerHorizontal="true"
                        android:layout_gravity="center"
                        android:layout_marginBottom="5dp"
                        android:layout_marginLeft="10dp"
                        android:layout_marginTop="5dp"
                        android:button="@drawable/bg_fav_detail"
                        android:drawablePadding="5dp"
                        android:text=" Favorite" />
                </RelativeLayout>

0

ボタンのテーマを保持する他の可能性。

<Button
            android:id="@+id/pf_bt_edit"
            android:layout_height="@dimen/standard_height"
            android:layout_width="match_parent"
            />

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_alignBottom="@id/pf_bt_edit"
            android:layout_alignLeft="@id/pf_bt_edit"
            android:layout_alignRight="@id/pf_bt_edit"
            android:layout_alignTop="@id/pf_bt_edit"
            android:layout_margin="@dimen/margin_10"
            android:clickable="false"
            android:elevation="20dp"
            android:gravity="center"
            android:orientation="horizontal"
            >

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:adjustViewBounds="true"
                android:clickable="false"
                android:src="@drawable/ic_edit_white_48dp"/>

            <TextView
                android:id="@+id/pf_tv_edit"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_marginLeft="@dimen/margin_5"
                android:clickable="false"
                android:gravity="center"
                android:text="@string/pf_bt_edit"/>

        </LinearLayout>

このソリューションでは、アクティビティテーマに@ color / your_color @ color / your_highlight_colorを追加すると、シャドウとリップルのあるLollipopにMatherialテーマを設定できます。以前のバージョンでは、ボタンを押すと、色とハイライトカラーが表示されます。

さらに、このソリューションでは、画像の自動サイズ変更

結果:最初はLollipopデバイス上で2番目:Pre lollipopデバイス上で3番目:Pre lollipopデバイスはボタンを押します

ここに画像の説明を入力してください


0

私は、textViewをtextView使用してアイコンを中央paddingLeft揃えし、textViewをleft | centerVerticalに揃えています。私が使用したビューとアイコンの間の小さなギャップdrawablePadding

         <Button
            android:id="@+id/have_it_main"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/textbox"
            android:drawableLeft="@drawable/have_it"
            android:drawablePadding="30dp"
            android:gravity="left|center_vertical"
            android:paddingLeft="60dp"
            android:text="Owner Contact"
            android:textColor="@android:color/white" />

2
これは多くの画面では機能せず、機能した画面でのみandroid:paddingLeft機能します。
soshial

0

これは古い/閉じたスレッドである可能性がありますが、独自のソリューションを作成することを決定するまでは、どこでも検索しても有用なものは見つかりませんでした。ここに答えを探している人がいるなら、これを試してみてください

          <LinearLayout
            android:id="@+id/llContainer"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@drawable/selector"
            android:clickable="true"
            android:gravity="center"
            android:orientation="vertical"
            android:padding="10dp"
            android:textStyle="bold">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:text="This is a text" />

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/icon_image />


        </LinearLayout>

線形レイアウトはコンテナおよびセレクターを持つものとして機能するため、線形レイアウト全体をクリックすると、本来あるべき姿に見えます。両方を中央に配置したい場合は、相対的なinsteafを使用します。水平方向に中央揃えにする場合は、方向を水平に変更します。

注意してください しないでください追加することを忘れアンドロイド:クリッカブル=「true」を場所を取るための行動のためのあなたの主なコンテナ(相対または線形)へ。

再びこれは古いスレッドかもしれませんが、そこで誰かを助けるかもしれません。

-乾杯はそれが役立つことを願っています-happycodings。


0

カスタムビューのソリューションのいずれかを使用する場合は、長いテキストまたは複数行のテキストで失敗することが多いため、注意してください。私はいくつかの回答を書き直し、置き換えonDraw()、それが間違った方法であることを理解しました。


0

ドローアブルの開始/左揃えの解決策を見たことがありますが、ドローアブルの終了/右揃えはできません。そのため、この解決策を思いつきました。動的に計算されたパディングを使用して、ドローアブルとテキストを左側と右側の両方に揃えます。

class IconButton @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyle: Int = R.attr.buttonStyle
) : AppCompatButton(context, attrs, defStyle) {

    init {
        maxLines = 1
    }

    override fun onDraw(canvas: Canvas) {
        val buttonContentWidth = (width - paddingLeft - paddingRight).toFloat()

        val textWidth = paint.measureText(text.toString())

        val drawable = compoundDrawables[0] ?: compoundDrawables[2]
        val drawableWidth = drawable?.intrinsicWidth ?: 0
        val drawablePadding = if (textWidth > 0 && drawable != null) compoundDrawablePadding else 0
        val bodyWidth = textWidth + drawableWidth.toFloat() + drawablePadding.toFloat()

        canvas.save()

        val padding = (buttonContentWidth - bodyWidth).toInt() / 2
        val leftOrRight = if (compoundDrawables[0] != null) 1 else -1
        setPadding(leftOrRight * padding, 0, -leftOrRight * padding, 0)

        super.onDraw(canvas)
        canvas.restore()
    }
}

アイコンを設定する場所に応じて、レイアウトの重力を「center_vertical | start」または「center_vertical | end」に設定することが重要です。例えば:

<com.stackoverflow.util.IconButton
        android:id="@+id/cancel_btn"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:drawableStart="@drawable/cancel"
        android:drawablePadding="@dimen/padding_small"
        android:gravity="center_vertical|start"
        android:text="Cancel" />

この実装の唯一の問題は、ボタンにテキストを1行しか含めることができないことです。そうでない場合、テキストの領域がボタンを埋め、パディングは0になります。


-5

これを使って android:background="@drawable/ic_play_arrow_black_24dp"

背景を中央に配置したいアイコンに設定するだけです

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.