Gregor
Gregor

Reputation: 275

Dynamic button text size

I wanna know how to make the button text size fill the height of a button. When using sp or dp size of text it is good for small screen resolution(4" screen for example), but on tablet screens(10") the button size is bigger, and button text looks very small) how can I solve this?

Upvotes: 0

Views: 7802

Answers (4)

GOTuser2673068
GOTuser2673068

Reputation: 31

You can try setting the button text size relative to the button height.

For example: In XML use weights for buttons to fill all the screen (regardless of screen size):

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/LinearLayout1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity" >

 <Button
    android:id="@+id/button1"
    android:layout_width="fill_parent"
    android:layout_height="0dp"
    android:layout_weight="1"/>

 <Button
    android:id="@+id/button2"
    android:layout_width="fill_parent"
    android:layout_height="0dp"
    android:layout_weight="1" />

</LinearLayout>

You set height of the button text (for example 1/3 of the button height) after the layout is drawn by overriding onwindowfocuschanged:

  @Override
  public void onWindowFocusChanged (boolean hasFocus) { // the layout is set                
     button1 = (Button)findViewById(R.id.button1);
     int text_height = button1.getHeight()/3;   // define text_height as 1/3 of button height in px
     button1.setTextSize(TypedValue.COMPLEX_UNIT_PX, text_height);  // set text height in px

     button2 = (Button)findViewById(R.id.button2);
     int text_height = button2.getHeight()/3;                   
     button2.setTextSize(TypedValue.COMPLEX_UNIT_PX, text_height);  
  }

Upvotes: 1

Gregor
Gregor

Reputation: 275

I figure it out!

I created folders: values-ldpi

values-small

values-normal

values-large

values-xlarge

In each folder I created dimens.xml file.

For example dimens.xml file in values-small looks like this:

<resources>


 <dimen name="text_button">10sp</dimen>

</resources>

dimens.xml file in values-normal like this:

<resources>


<dimen name="text_button">12sp</dimen>

</resources>

Then instead of using button text size with unit(10sp,10px,10dp) you just point it to text_button.

Upvotes: 0

K_Anas
K_Anas

Reputation: 31466

You could overload the onDraw() method in a child of Button.This example shows how to use getTextBounds() from the android Paint class to determine the size text will be when drawn. With this information you can calculate a textSize and textScaleX to use to get your text the size you want.

The goal is to find values for the textSize and textScaleX that will adjust our text size to fill our View. Instead of calculating this every time onDraw is called, we will watch for size changes and calculate the values up front. To do this we override onSizeChanged to get the new view width and height.

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);

    // save view size
    mViewWidth = w;
    mViewHeight = h;

    // first determine font point size
    adjustTextSize();
    // then determine width scaling
    // this is done in two steps in case the
    // point size change affects the width boundary
    adjustTextScale();
}

From onSizeChanged you have to call two methods. First one to determine the textSize we use the getTextBounds() method of the Paint object to determine a size for the text at a known textSize. From there we do a simple calculation to determine what textSize would be used to result in the text bounds that we want.

void adjustTextSize() {
    mTextPaint.setTextSize(100);
    mTextPaint.setTextScaleX(1.0f);
    Rect bounds = new Rect();
    // ask the paint for the bounding rect if it were to draw this
    // text
    mTextPaint.getTextBounds(mText, 0, mText.length(), bounds);

    // get the height that would have been produced
    int h = bounds.bottom - bounds.top;

    // make the text text up 70% of the height
    float target = (float)mViewHeight*.7f;

    // figure out what textSize setting would create that height
    // of text
    float size  = ((target/h)*100f);

    // and set it into the paint
    mTextPaint.setTextSize(size);
}

The second method determines the textScaleX value in the same way. We find what the size would be with a textScaleX of 1.0, then do some simple math to determine what scale would result in the width of bounds that we want. This is done in a separate call call from the text size calculation just in case setting the textSize affects the result for scale. Changing textScaleX will definitely not change the height of the text drawn.

void adjustTextScale() {
    // do calculation with scale of 1.0 (no scale)
    mTextPaint.setTextScaleX(1.0f);
    Rect bounds = new Rect();
    // ask the paint for the bounding rect if it were to draw this
    // text.
    mTextPaint.getTextBounds(mText, 0, mText.length(), bounds);

    // determine the width
    int w = bounds.right - bounds.left;

    // calculate the baseline to use so that the
    // entire text is visible including the descenders
    int text_h = bounds.bottom-bounds.top;
    mTextBaseline=bounds.bottom+((mViewHeight-text_h)/2);

    // determine how much to scale the width to fit the view
    float xscale = ((float) (mViewWidth-getPaddingLeft()-getPaddingRight())) / w;

    // set the scale for the text paint
    mTextPaint.setTextScaleX(xscale);
}

The final detail is to determine where vertically in the view to paint the text. The boundary rect returned by getTextBounds can help with this. The bounds.top value will actually be a negative value, and it represents the size of the text not including the size of any descenders (parts of letters that extend below the base line). The bounds.bottom value is the size of the descenders. Using this information, we can decide how to position the text in the view. The y value in the call to drawText represents the baseline. Descenders will be drawn below this line. For this example, we adjust the y value so that we are showing the full descenders. This value is saved off as mTextBaseline and is used in onDraw.

@Override
protected void onDraw(Canvas canvas) {
    // let the ImageButton paint background as normal
    super.onDraw(canvas);

    // draw the text
    // position is centered on width
    // and the baseline is calculated to be positioned from the
    // view bottom
    canvas.drawText(mText, mViewWidth/2, mViewHeight-mTextBaseline, mTextPaint);
}

Upvotes: 1

Mohd Saleem
Mohd Saleem

Reputation: 94

Use the wrap_content in layout_height for a good things in comparison of sp and dp

Upvotes: 0

Related Questions