2

I want a Button like this:

+-----------------------+
|                       |
|        +-----+        |
|        |Image|        |
|        +-----+        |
|          Text         |
|                       |
|                       |
+-----------------------+

EDIT: Explanation to the picture: I want the COMBINATION of Image and text centered (text ALWAYS below the image)

I want the Button to stretch to a parent object (to make the whole area the button click area) and still align imgage AND text at center.

I achieve only top center alignment with folowing code, but I don't get the desired behaviour...

<Button
    android:id="@+id/btInfo"
    android:paddingTop="20dp"
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:gravity="top|center_horizontal"                   
    android:layout_weight="1"
    android:background="@drawable/border_button_main_menu"
    android:drawableTop="@drawable/bt_info"
    android:onClick="onClick"
    android:text="@string/info"
    android:textColor="@drawable/bt_white_red_text"
    android:textSize="15dp" />

changing android:gravity="top|center_horizontal" to android:gravity="center_vertical|center_horizontal" only leads to image centered at top and text centered at bottom...


---- EDIT2 -----

Wanted behaviour:

1) look as described (Image and text is a optical group and the group is centered in the button)

2) text should be part of the button (I want the onclick behaviour to work with selectors)


---- EDIT3 -----

added my own solution... but thanks to all that tried to help

prom85
  • 16,896
  • 17
  • 122
  • 242

6 Answers6

3

Use the Following Code, your problem will be solve.

<Button
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_alignBottom="@+id/foreground"
    android:layout_alignLeft="@+id/foreground"
    android:layout_alignRight="@+id/foreground"
    android:layout_alignTop="@+id/foreground"
    android:background="@android:drawable/dialog_frame"
    android:onClick="clickedMe" />

   <RelativeLayout
       android:id="@+id/foreground"
       android:layout_width="fill_parent"
       android:layout_height="wrap_content"
       android:layout_alignParentBottom="true"
       android:layout_alignParentTop="true" >

       <TextView
           android:id="@+id/button_text"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:layout_alignParentBottom="true"
           android:layout_centerHorizontal="true"
           android:layout_marginBottom="112dp"
           android:text="@string/hello_world" />

       <ImageView
           android:id="@+id/imageView1"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:layout_above="@+id/button_text"
           android:layout_centerHorizontal="true"
           android:paddingBottom="10dip"
           android:paddingTop="10dip"
           android:src="@drawable/ic_launcher" />

   </RelativeLayout>

</RelativeLayout>

------------- EDIT --------------------

oNclick Method:

final TextView text = (TextView) findViewById(R.id.button_text);
    RelativeLayout foreground = (RelativeLayout) findViewById(R.id.foreground);
    foreground.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            Log.d(TAG, "clicked");
            Toast.makeText(getApplicationContext(), "Clicked...!!!",
                    Toast.LENGTH_LONG).show();
            text.setTextColor(Color.RED);
        }
    });
Android Boy
  • 4,335
  • 6
  • 30
  • 58
  • I added some edit to the first post... Solution is working, but it's splitting button from text, and I want the button click to work with selectors... – prom85 Dec 05 '12 at 13:33
  • yes... that's no problem, I know, but I also want the selector to work with the button clicks (changing colors of the text when clicking the button, in my case...)... without doing that in the code manually... because I'm using the button in many places... – prom85 Dec 05 '12 at 14:04
  • I didn't understand you requirement exactly. – Android Boy Dec 05 '12 at 14:10
  • If this answer help you then you should be checked. – Android Boy Dec 05 '12 at 14:19
  • actually, I wanted an XML Solution (because I'm using it in more places) which fulfills my requirements... First requirement: clicking the button should change text color (therefor I would use a selector) and second requirement: optical centered group of image with a text below... – prom85 Dec 05 '12 at 14:23
  • Your second Requirement is already fulfilled. For first requirement I edited the onClicklistener method. Please see it. – Android Boy Dec 05 '12 at 14:30
  • as I said, I'm using it in many locations, setting color in code is no solution for me (too much copy and paste) and therefore I wanted the selector to handle that (or something similar that works in xml).. that's why the text control is not working, selectors need states (pressed, focused, selected)... Only solution I found so far is extending the button control... which I will have to do... – prom85 Dec 05 '12 at 14:37
1

Try this:

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

<Button
android:id="@+id/btInfo"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@drawable/border_button_main_menu"
android:drawableTop="@drawable/bt_info"
android:onClick="onClick"
android:text="@string/info"
android:textColor="@drawable/bt_white_red_text"
android:textSize="15dp" />

</LinearLayout>
Ankush
  • 6,767
  • 8
  • 30
  • 42
  • that would only work programmatically, because I don't know the value beforehand... – prom85 Dec 05 '12 at 12:38
  • ok. What you can also do is instead of a button, you can use a linear layout and put the image and text inside it. You could then implement an onClickListener on the linearLayout and make it perform like the button – Ankush Dec 05 '12 at 12:48
  • thanks, that works I know... just was interested in finding an easy solution... and out of the box clicking behaviour and android button look... – prom85 Dec 05 '12 at 12:51
  • thanks for the help, but that's not the solution either... the combination of image and text should be always centered... it can't work with drawableTop or so, because there's no center value... I think, the solution is in setting a button in a relative layout over aother relative layout (with the image and text in it) that stretches over the complete relative layout... as described in a link someone postet here... thanks though for your help – prom85 Dec 05 '12 at 13:12
0

Call the setBackgroundDrawable() the text you will then add to the button will appear below the drawable!

Pavlos
  • 2,183
  • 2
  • 20
  • 27
  • maybe the Image is not "drawn" clear enough, I want the COMBINATION of Image and text" centered, text ALWAYS below the image... will add that info above – prom85 Dec 05 '12 at 12:39
0

I think the best way to achieve this kind of UI is using ImageButton instead of Button. But you can still achieve this by some hackish ways. One of them is here:

How to have Image and Text Center within a Button

You'll just have to mention inner RelativeLayout's orientation as "vertical" in the solution given in above link. I hope it helps.

May be this can help you too:

How to center icon and text in a android button with width set to "fill parent"

Community
  • 1
  • 1
Yogesh Somani
  • 2,624
  • 3
  • 21
  • 34
  • just tried ImageButton again and wondered why I didn't use it... now I remember, it seems to not support texts and I don't want to add the text to the pictures... but the link seems very good, will look into it... thanks – prom85 Dec 05 '12 at 12:59
  • to the first solution, there I have to code the ioptical click changes manually because the text is not part of the button... that's actually the reason why I'm looking for another solution... if I would not need that, I would anyway make a linear Layout or relative view and set the onclick listener... thanks anyways – prom85 Dec 05 '12 at 13:23
0

The output you are trying to achieve can not be done in that way using drawableTop.

reason why? - View can set background or drawable and while setting drawable Android gives only 4 options to set bounds of the drawable either top,left,right or bottom and nothing for center.

Now in your XML you are having view's height and width as MATCH_PARENT so every time the drawable set using drawableTOP or LEFT etc. it will go to that edge of the view. which is happening right now with you.

From Comments :

  1. Android OS is ultimately a Software.. and a software has always been developed within it's scope. The thing you are asking is out of scope so it's directly not supported by android using any default Form widget..

  2. I demonstrated that how the android have written the Drawable class and how you can use it so please try to understand the answer and not only the Solution to your problem.. by the way to get click of whole area you can write click on that LinearLayout instead of the button.

Solution will be :

<LinearLayout height = MATCH_PARENT and width = 0dp>

    <Button height and width = WRAP_CONTENT with drawableTop=image and gravity = center>

</LinearLayout>
MKJParekh
  • 34,073
  • 11
  • 87
  • 98
  • that's just a optical solution, as I mentioned, I want the whole area to be the click area of the button... LinearLayout area should be completely overlapped with the button in your case – prom85 Dec 05 '12 at 13:03
  • @prom85 I demonstrated that how the android have written the Drawable class and how you can use it so please try to understand the answer and not only the Solution to your problem.. by the way to get click of whole area you can write click on that LinearLayout instead of the button. – MKJParekh Dec 05 '12 at 13:05
  • I understand what you wrote... and I knew, that it can't work that way... I was just wondering if there's an easy solution to that, not using a custom buttom... (just posted the code to demonstrate I'm not looking for a solution for my question and haven't tried anything yet...) add a big edit to my first post as well... to show, what I want to achieve in the end – prom85 Dec 05 '12 at 13:27
  • @prom85 Android OS is ultimately a Software.. and a software has been developed within it's scope. The thing you are asking is out of scope so it's directly not supported by android using any default Form widget.. This is what I said and saying again. Just for other users who come to the post by searching.. for them I also have added the solution that how to get the behavior. – MKJParekh Dec 05 '12 at 13:36
  • I see your point... anyway, the solution is not what I'm looking for, it's the solution for something else... though, it fullfills most of my wishes, but not all of them... – prom85 Dec 05 '12 at 14:01
  • What solution.!! there is no build-in control support for the same and you have to trick your layout using combination of other control to create one and use it. – MKJParekh Dec 05 '12 at 14:05
  • I know... I was looking for a combination, but non of them serve all my requirements... – prom85 Dec 05 '12 at 14:21
0

My solution is now deriving from a button... that fullfills all my requirements... I don't know, if the measuring of the text is really exact that way, but it looks to be so... if not, everyone get's the idea behind and can adjust that...

Thanks for the help, though

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.StateListDrawable;
import android.util.AttributeSet;
import android.widget.Button;

public class CenterImageTextButton extends Button {

    private Paint mPaint = new Paint();
    private String mText = null;
    private float mTextSize = 0;

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

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

    @Override
    public void onDraw(Canvas canvas) {

        mText = getText().toString();
        mTextSize = getTextSize();

        mPaint.setStyle(Style.FILL); 
        mPaint.setColor(getCurrentTextColor());        

        // get image top
        Drawable drawable = getCompoundDrawables()[1];
        Drawable curDrawable = null;
        if (drawable instanceof StateListDrawable)
            curDrawable = ((StateListDrawable)drawable).getCurrent();
        else
            curDrawable = ((BitmapDrawable)drawable).getCurrent();
        Bitmap image = ((BitmapDrawable)curDrawable).getBitmap();

        // call default drawing method without image/text
        setText("");
        setCompoundDrawables(null, null, null, null);
        super.onDraw(canvas);
        setText(mText);
        setCompoundDrawables(null, drawable, null, null);

        // get measurements of button and Image
        int width = getMeasuredWidth();
        int height = getMeasuredHeight();
        int imgWidth = image.getWidth();
        int imgHeight = image.getHeight();

        // get measurements of text
        //float densityMultiplier = getContext().getResources().getDisplayMetrics().density;
        //float scaledPx = textSize * densityMultiplier;
        //paint.setTextSize(scaledPx);
        mPaint.setTextSize(mTextSize);
        float textWidth = mPaint.measureText(mText);

        // draw Image and text
        float groupHeight = imgHeight + mTextSize;
        canvas.drawBitmap(image, (width - imgWidth) / 2, (height - groupHeight) / 2, null);
        canvas.drawText(mText, (width - textWidth) / 2, mTextSize + (height - groupHeight) / 2 + imgHeight, mPaint);    
    }
}
prom85
  • 16,896
  • 17
  • 122
  • 242