How to split a String text (the blue one) between two TextViews so that it starts in one TextView and continues in the other one when there is no more room left.
The maximum width of the two TextViews is not the same.
An example would be filling a form. The black text is static (two labels).
Another approche could be having only one TextView (for the blue text) that has padding left and right but only for the first line.
For each padding, the padding size would equal the label width.
you should do it programmatically
int textSize = 16;
textView2.setTextSize(textSize);
textView1.setTextSize(textSize);
final float scale = getResources().getDisplayMetrics().density;
int dpWidthInPx = (int) (100 * scale);
int countTv1Chars = dpWidthInPx / textSize;
String tv1String = string.substring(0, countTv1Chars);
String tv2String = string.substring(countTv1Chars, string.length() - 1);
textView1.setText(tv1String);
textView2.setText(tv2String);
in xml
<TextView
android:id="#+id/tv1"
android:lines="1"
android:layout_width="100dp"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/tv2"
android:lines="1"
android:layout_width="100dp"
android:layout_height="wrap_content" />
Related
I have a TextView and I would like for the text to wrap around at most 1 line if it is too long.
I tried:
android:minLines="1"
android:maxLines="2"
but these work only if the text has actual new lines.
If I use:
android:lines="2"
it works but when the text has few chars the textview still takes space for 2 lines.
Is there a way to solve this?
Textview must have width if you want use maxLines param.
Try this maybe it works:
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:minWidth="50dp"
android:maxLines="1"
Also you can use android:maxLength if your Textview's parent has a max or constant size
Edit base on comments:
set TextView width in runtime
String myString = "test";
textView.measure(0, 0);
View parent = (View) textView.getParent();
parent.measure(0, 0);
int currentWidth = textView.getWidth();
int maxAvailableWidth = parent.getWidth();
int finalWidth = (int) (myString.length() * textView.getTextSize() * factor); // factor is depends on your typeface
if(finalWidth > maxAvailableWidth)
finalWidth = maxAvailableWidth;
textView.setWidth(finalWidth);
Thanks
I've tried this in my code and it works. you will need to use only maxlines and set width to match_parent
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="2"/>
Output:
Try:
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:ellipsize="end"
android:maxLines="1"
A sprite on my android game is set to fall by 5 pixels every 100 milliseconds, this works fine the only problem is that the ImageView itself is only 53dp high, if I make it any bigger the image inside scales with it. Since the ImageView is only 53dp high the image disappears after 1100 milliseconds as it scrolls outside the boundaries of the imageview.
I need the layout height of the ImageView to fill_parent but I need the image to stay the same size instead of scaling with it, here's my current code:
<ImageView
android:id="#+id/blueman"
android:layout_width="0dip"
android:layout_height="53dp"
android:paddingRight="300dp"
android:layout_weight="0.03"
android:src="#drawable/fall" />
Thanks in advance :)
since you didn't give the full code of the layout, I'll make some assumptions...
you're talking about setting your sprite's height to the screen's height without scaling?
There should be a difference between your screen size (that is the root layout item) and the sprites in it. I guess you declared your layout as...:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="?gameBackground"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="#+id/btTap"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="14dp"
android:layout_marginTop="350dp"
android:background="#drawable/tap"
android:visibility="visible" />
<Button
android:id="#+id/btCellR1C1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="490dp"
android:layout_marginTop="155dp"
android:background="#drawable/cell_red" />
The only thing I had to cope with, was the scaling of my sprites depending on the device's resolution with such a method:
public static void scaleView(View view, int top, int left, int width,
int height) {
top = Math.round(top * scaleY);
left = Math.round(left * scaleX);
width = Math.round(width * scaleX);
height = Math.round(height * scaleY);
LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
params.height = height;
params.width = width;
params.topMargin = top;
params.leftMargin = left;
view.setLayoutParams(params);
view.setSoundEffectsEnabled(false);
}
Please give us more details to help you
Best regards
Serge
I have two textviews like this:
=======================
= TextView1 TextView2 =
=======================
And I would like to detect when the textviews are too long such that they are displayed like this:
=======================
= TextView1 =
= TextView2 =
=======================
currently for longer text, it is displayed like this:
=======================
= TextView1 Text =
= View2 =
=======================
how can I do this, such that when the text is short the textviews are side by side and when it is too long, the second textview is not splitted but moved to the second line?
I tought at a solution to create a single textview and build the text according to length (text 1 + padding + text 2 if short, and text 1 + "\n" + text 2 if long) but I do not like this solution.
Is there any way to detect if the second text will be split such that to change the orientation of the layout that contains the textviews from horizontal cu vertical?
UPDATE
This is my xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center">
<TextView
android:id="#+id/my_text_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:padding="10dp"
android:text="#string/text1"/>
<TextView
android:id="#+id/my_text_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginRight="5dp"/>
</LinearLayout>
I have found a better solution. Changed my textviews into autoresizable textviews (more info here)
Also, each textview is in a separate layout, to make sure both textviews are resized to the same value.
My xml looks like this:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/value_linear_layout"
android:gravity="center">
<LinearLayout
android:layout_width="wrap_content"
android:layout_weight="1"
android:layout_height="wrap_content">
<com.mihaela.view.AutoResizeTextView
android:id="#+id/my_text_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_weight="1"
android:layout_height="wrap_content">
<com.mihaela.view.AutoResizeTextView
android:id="#+id/my_text_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout>
and I have implemented the OnTextResizeListener from AutoResizeTextView to do this:
public class TextWidthResizeListener implements OnTextResizeListener {
#Override
public void onTextResize(TextView textView, float oldSize, float newSize) {
TextPaint paint = textView.getPaint();
if (paint.measureText(textView.getText().toString()) > (valueLinearLayout.getWidth() / 2)){
valueLinearLayout.setOrientation(LinearLayout.VERTICAL);
}
}
}
where valueLinearLayout is:
valueLinearLayout = (LinearLayout)findViewById(R.id.value_linear_layout);
This solution best fits for me, as the textviews are dimensioned when they are side by side until a minimum size. When the minimum size is reached, and the text still does not fit, the textviews will be aligned one under another.
Also, this idea with the listener can be applied to non-resizable textviews also.
I will set this answer as the correct one.
You should use a single, multi-line TextView and set the text as follows :
mTextView.setText(text1+" "+text2);
or
mTextView.setText(text1+"\n"+text2);
depending on your particular needs.
EDIT: you could specify your text in html, and then use Html.fromHtml(htmlString) and display this text in your TextView.
String text1 ="<font color=\"red\">This is some text!</font>"
String text2="<font color=\"blue\">This is some other text!</font>"
textView.setText(Html.fromHtml(text1+ "<br/>"+ text2);
I made a slightly different version of the accepted answer. I did not alter my layout xml in any way and did not use onTextResize() or AutoResizeTextView as that seemed an overkill for my situation. I needed my LinearLayout to switch from Horizontal orientation to Vertical orientation if the device's language setting caused a long string to be used.
Layout
<LinearLayout
android:id="#+id/customer_care_bottom_layout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="horizontal"
android:layout_marginBottom="#dimen/lmargin_bottom_10">
<TextView
android:id="#+id/customer_care_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/CUSTOMER_CARE_TITLE" />
<TextView
android:id="#+id/customer_care_number_information"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/CUSTOMER_CARE_INFORMATION"/>
</LinearLayout>
Java
private void setCustomerServiceLayoutOrientationBasedOnTextWidth() {
TextPaint paint = customer_care_number_text.getPaint();
TextView tvCustomerCareTitle = (TextView) findViewById(R.id.customer_care_title);
TextView tvCustomerCareInformation = (TextView) findViewById(R.id.customer_care_information);
int halfCustomerServiceLayoutWidth = getScreenWidth() / 2;
boolean isCustomerCareTitleTooLong = paint.measureText(tvCustomerCareTitle.getText().toString()) > customerServiceLayoutWidth;
boolean isCustomerCareInformationTooLong = paint.measureText(tvCustomerCareInformation.getText().toString) > customerServiceLayoutWidth;
if (isCustomerCareTitleTooLong || isCustomerCareInformationTooLong) {
LinearLayout llCustomerCareBottom = (LinearLayout) findViewById(R.id.customer_care_bottom_layout);
llCustomerCareBottom.setOrientation(LinearLayout.VERTICAL);
}
}
private int getScreenWidth() {
int screenWidth;Display display = getWindowManager().getDefaultDisplay();
if (Build.VERSION.SDK_INT < 13) {
screenWidth = display.getWidth();
} else {
Point point = new Point();
display.getSize(point);
screenWidth = point.x;
}
return screenWidth;
}
This question already has an answer here:
Combine image and text to drawable
(1 answer)
Closed 9 years ago.
I am working in Android. I want to make a SeekBar. In thumb of SeekBar i want to show progress (probably on a TextView aligned over thumb which moves along with thumb).
This is my XML for SeekBar and TextView.
<SeekBar
android:id="#+id/ProgressBar01"
android:layout_width="fill_parent"
android:paddingLeft="10px"
android:paddingRight ="10px"
android:layout_height="70dp"
android:layout_below="#+id/incentives_textViewBottemLeft"
android:max="10"
android:progressDrawable="#drawable/incentive_progress"
android:secondaryProgress="0"
android:thumb="#drawable/incentives_progress_pin"
android:focusable="false" />
<TextView
android:id="#+id/incentives_textViewAbove_process_pin"
android:layout_width="fill_parent"
android:layout_height="20dp"
android:layout_below="#+id/incentives_textViewBottemLeft"
android:layout_marginTop="11dp"
android:text=""
android:textStyle="bold"
android:textColor="#FFe4e1"
android:textSize="15sp" />
and this my code to make align for text
int xPos = ((mSkbSample.getRight() - mSkbSample.getLeft()) / mSkbSample.getMax()) * mSkbSample.getProgress();
v1.setPadding(xPos+m,0,0,0);
v1.setText(String.valueOf(progress).toCharArray(), 0, String.valueOf(progress).length());
But text is not displaying into center of that thumb. Please suggest me what should i do for this.
If I understand your question right, you want to place text inside of the thumb on a seekbar like so:
The Android Seekbar doesn't expose any public or protected methods that allows you to set a text in the thumb. So you can't implement a solution with the Android SeekBar as is.
As a solution, you can write your own CustomSeekBar.
The Android SeekBar extends AbsSeekBar. It's in AbsSeekBar that the thumb's position is set, like so:
private void setThumbPos(int w, Drawable thumb, float scale, int gap) {
int available = w - mPaddingLeft - mPaddingRight;
int thumbWidth = thumb.getIntrinsicWidth();
int thumbHeight = thumb.getIntrinsicHeight();
available -= thumbWidth;
// The extra space for the thumb to move on the track
available += mThumbOffset * 2;
//Determine horizontal position
int thumbPos = (int) (scale * available);
//Determine vertical position
int topBound, bottomBound;
if (gap == Integer.MIN_VALUE) {
Rect oldBounds = thumb.getBounds();
topBound = oldBounds.top;
bottomBound = oldBounds.bottom;
} else {
topBound = gap;
bottomBound = gap + thumbHeight;
}
//Set the thumbs position
thumb.setBounds(thumbPos, topBound, thumbPos + thumbWidth, bottomBound);
}
and in AbsSeekBar's onDraw() method, the thumb is drawn:
mThumb.draw(canvas);
To implement your own SeekBar, you first create a CustomSeekBar class that extends AbsSeekBar. You then override AbsSeekBar's setThumPos() method in your CustomSeekBar class, and there set the position of your own custom thumb.
Your custom thumb would be a View or ViewGroup,e.g. LinearLayout, with a background drawable and a TextView for the percentage progress text.
You then have to decide how to write the percentage progress to the custom thumb. You could write the percentage progress text on the thumb in a new writeTextOnThumb method() called inside setThumbPos(), or you could expose it as a public method in your CustomSeekBar's API.
Before getting into the details of a solution, I will just mention something that you have probably already considered: The user, when moving the SeekBar, typically has her finger positioned over the thumb, and therefore would likely cover up any text you might put there, at least while the Seekbar is being moved. Now, perhaps you are moving the SeekBar programmatically, or perhaps you are happy enough for the user to view the SeekBar once she has finished moving it and has removed her finger, or perhaps you can count on your user to slide her finger below the SeekBar after she starts to slide it, so as to reveal the thumb. But if that is not the case, then you might want to position the text somewhere that the user's finger is likely not to be.
The approach described below should allow you to position text anywhere in the SeekBar that you like, including over the thumb. To allow this, it overrides the SeekBar's basic onDraw() method, rather than overriding a method that deals specifically with drawing the thumb.
Here is a rough version of a class that draws text onto a SeekBar using the above approach:
public class SeekBarWithText extends SeekBar {
private static final int textMargin = 6;
private static final int leftPlusRightTextMargins = textMargin + textMargin;
private static final int maxFontSize = 18;
private static final int minFontSize = 10;
protected String overlayText;
protected Paint textPaint;
public SeekBarWithText(Context context) {
super(context);
Resources resources = getResources();
//Set up drawn text attributes here
textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
textPaint.setTypeface(Typeface.DEFAULT_BOLD);
textPaint.setTextAlign(Align.LEFT);
}
//This attempts to ensure that the text fits inside your SeekBar on a resize
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
setFontSmallEnoughToFit(w - leftPlusRightTextMargins)));
}
//Finds the largest text size that will fit
protected void setFontSmallEnoughToFit(int width) {
int textSize = maxTextSize;
textPaint.setTextSize(textSize);
while((textPaint.measureText(sampleText) > width) && (textSize > minTextSize)) {
textSize--;
textPaint.setTextSize(textSize);
}
}
//Clients use this to change the displayed text
public void setOverlayText(String text) {
this.overlayText = text;
invalidate();
}
//Draws the text onto the SeekBar
#Override
protected synchronized void onDraw(Canvas canvas) {
//Draw everything else (i.e., the usual SeekBar) first
super.onDraw(canvas);
//No text, no problem
if(overlayText.length() == 0) {
return;
}
canvas.save();
//Here are a few parameters that could be useful in calculating where to put the text
int width = this.getWidth() - leftPlusRightTextMargins;
int height = this.getHeight();
//A somewhat fat finger takes up about seven digits of space
// on each side of the thumb; YFMV
int fatFingerThumbHangover = (int) textPaint.measureText("1234567");
float textWidth = textPaint.measureText(overlayText);
int progress = this.getProgress();
int maxProgress = this.getMax();
double percentProgress = (double) progress / (double) maxProgress;
int textHeight = (int) (Math.abs(textPaint.ascent()) + textPaint.descent() + 1);
int thumbOffset = this.getThumbOffset();
//These are measured from the point textMargin in from the left of the SeekBarWithText view.
int middleOfThumbControl = (int) ((double) width * percentProgress);
int spaceToLeftOfFatFinger = middleOfThumbControl - fatFingerThumbHangover;
int spaceToRightOfFatFinger = (width - middleOfThumbControl) - fatFingerThumbHangover;
int spaceToLeftOfThumbControl = middleOfThumbControl - thumbOffset;
int spaceToRightOfThumbControl = (width - middleOfThumbControl) - thumbOffset;
int bottomPadding = this.getPaddingBottom();
int topPadding = this.getPaddingTop();
//Here you will use the above and possibly other information to decide where you would
// like to draw the text. One policy might be to draw it on the extreme right when the thumb
// is left of center, and on the extreme left when the thumb is right of center. These
// methods will receive any parameters from the above calculations that you need to
// implement your own policy.
x = myMethodToSetXPosition();
y = myMethodToSetYPosition();
//Finally, just draw the text on top of the SeekBar
canvas.drawText(overlayText, x, y, textPaint);
canvas.restore();
}
}
check this put trees of relative layout to put text on top of seekbar
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/relativeLayout0" >
<Button
android:id="#+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="#+id/button1"
android:layout_alignBottom="#+id/button1"
android:layout_alignParentRight="true"
android:text="Button" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/button1"
android:layout_marginBottom="0dp"
android:layout_toRightOf="#+id/button1" >
<SeekBar
android:id="#+id/seekBar1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true" />
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/seekBar1"
android:layout_alignParentRight="true"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<RelativeLayout
android:id="#+id/relativeLayout1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true" >
</RelativeLayout>
<TextView
android:id="#+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="#+id/relativeLayout1"
android:layout_centerHorizontal="true"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
</RelativeLayout>
enter code here
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"`enter code here`
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="24dp"
android:text="Button" />
</RelativeLayout>
This is my very first post at Stackoverflow. Before I make my question, I just want to say that this is a great resource of information and I find the community extremely helpful.
I hope to be able to share my Android development knowledge with everyone else as well.
I have been developing for Android for 6 months now and, although I have learned very much, I still greatly struggle when it comes to layout/design.
I have one layout.xml file that contains a Relative layout. Inside this layout, I have three buttons. I want those three buttons to have a certain width size that would grow or shrink depending on the device's screen size/density.
This is the xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/relativeLayout1123123213"
android:layout_width="fill_parent"
android:layout_height="#dimen/actionbar_height"
android:orientation="horizontal">
<Button
android:id="#+id/btnLogin"
android:layout_width="100dp"
android:layout_height="50dp"
android:background="#drawable/button"
android:drawableLeft="#drawable/balloon_overlay_close"
android:gravity="center"
android:text="Earned" />
<Button
android:id="#+id/btnLogin2"
android:layout_width="113dp"
android:layout_height="50dp"
android:layout_alignParentTop="true"
android:layout_toRightOf="#+id/btnLogin"
android:background="#drawable/button"
android:drawableLeft="#drawable/balloon_overlay_close"
android:gravity="center"
android:text="In Progress" />
<Button
android:id="#+id/btnLogin3"
android:layout_width="107dp"
android:layout_height="50dp"
android:layout_alignParentTop="true"
android:layout_toRightOf="#+id/btnLogin2"
android:background="#drawable/button"
android:drawableLeft="#drawable/balloon_overlay_close"
android:gravity="center"
android:text="Done" />
</RelativeLayout>
I hard coded the width values, considering that I have different text sizes in each button... so that should obviously affect the width as well...
My question is... is there any intelligent way to accomplish this? Maybe programatically, when I know the current device's screen size?
Thanks everyone!
Felipe
====================================================
UPDATED SECTION
Hey guys,
Thanks for your help so far.
I have added the LinearLayout and the weight as per recommendation, but I am still not exactly getting what I want. It's almost there, but not quite.
My new xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="#dimen/actionbar_height"
android:orientation="horizontal"
android:gravity="center" android:weightSum="1">
<Button
android:id="#+id/btnLogin"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#drawable/button"
android:drawableLeft="#drawable/balloon_overlay_close"
android:gravity="center"
android:text="#string/bottonbar_earned"
android:layout_weight=".10"/>
<Button
android:id="#+id/btnLogin2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".10"
android:background="#drawable/button"
android:drawableLeft="#drawable/balloon_overlay_close"
android:gravity="center"
android:text="#string/bottonbar_inprogress" />
<Button
android:id="#+id/btnLogin3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#drawable/button"
android:drawableLeft="#drawable/balloon_overlay_close"
android:gravity="center" android:text="#string/bottonbar_redeemed"
android:layout_weight=".90"/>
</LinearLayout>
This is the result link
Can you see the end of the right side? I don't think the weight is distributed like it should, although I set a .90 weight to the third button.
What do you guys think?
What you can do is use android:layout_weight attribute on buttons, but you need to place them into a LinearLayout. If you need to have RelativeLayout, then you can place the LinearLayout inside it.
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:weightSum="1.0" >
<Button
android:text="left"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight=".30" />
<Button
android:text="center"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight=".40" />
<Button
android:text="right"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight=".30" />
</LinearLayout>
If you could do it in xml itself, I wouldn't recommend doing it programmatically. You can add something like :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center" style="android:style/ButtonBar" >
<Button android:text="Ok" android:id="#+id/bookOkBtn"
android:layout_width="0dp" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_marginRight="10dp" />
<Button android:text="Return" android:id="#+id/bookReturnBtn"
android:layout_width="0dp" android:layout_height="wrap_content"
android:layout_weight="1"/>
</LinearLayout>
Making android:layout_width="0" & android:layout_weight=1 uses all the available space width wise.
If you want height-wise also, then specify dip in android:layout_height="100dip" and check your desired height.
If this also doesn't fit your needs and dynamic setting is only the solution, then have added Answer for that too.
UPDATED :
Have a look at this code :
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:orientation="horizontal" android:gravity="center"
android:layout_marginTop="15dp" style="android:style/ButtonBar">
<Button android:id="#+id/browseAddBtn" android:text="Add" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:layout_marginRight="10dp" />
<Button android:id="#+id/browseViewBtn" android:text="Edit" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:layout_marginRight="10dp" />
<Button android:id="#+id/browseDelBtn" android:text="Delete" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:layout_marginRight="10dp" />
<Button android:id="#+id/browseReturnBtn" android:text="Return" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" />
</LinearLayout>
RESULTS
Image shows results of above code and also on changing the layout_weight as mentioned in file respectively. My parent layout is also LinearLayout & has no padding or margins set.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" android:orientation="vertical">
This sounds more like a case for a LinearLayout than a RelativeLayout. If you specify a LinearLayout as the parent with a total layout weight of 3 and have each of your Buttons specify a layout weight of 1 they should end up precisely as you desire on any screen.
I had same situation where I had to set sizes of buttons based on screen sizes and density. I calculate the size of buttons based on the actual space for the application I get.
I would suggest you to use LinearLAyout instead of RelativeLayout, but as you have some experience, you must be aware of the differences and ease of usage with Linear rather than Relative layouts.
In my XML I have root LinearLayout & 2 inner LinearLayout (row1 & row2). Each row has 3 butttons.
In my onCreate I get above 3 of them using findViewById.
Using the LayoutParams and the screen's size and densty, I calcualte the size of buttons and text sizes.
Algorithm :
Get Screen height & Width
Deduct the padding & margins you use
Deduct height of Title bar
Now, you have got your full available space. Divide it horizontally & vertically as you need
This will give you size of 1 button
Set the same size to all buttons
Based on buttons width & height & density figure out the text size
You can start up with this, if you need help I will be there. Feel free to ask.
UPDATED : CODE ADDED :-
These methods are added in a class named "Utility" and made static to access the methods in whole project easily :
public static ScreenInfo scrnInfo = new ScreenInfo();
public static void calculateChildSize(LinearLayout root, LinearLayout.LayoutParams row1Params, LinearLayout.LayoutParams row2Params, DisplayMetrics metrics) {
int height, width;
int childWidth, childHeight;
//gets screen dimensions
height = metrics.heightPixels; //480
width = metrics.widthPixels; //320
scrnInfo.setScreenHeight(height);
scrnInfo.setScreenWidth(width);
//Log.i("MY", "Actual Screen Height = " + height + " Width = " + width);
// Get height/width after deducting Padding of all 4 sides
height = height - (root.getPaddingBottom() + root.getPaddingTop()); // 480-70
width = width - (root.getPaddingLeft() + root.getPaddingRight()); // 320-70
//Log.i(TAG, "Actual Area after Padding W = " + width + " H = " + height);
int bottomMargin = row1Params.bottomMargin; //15
bottomMargin = (row1Params.bottomMargin %2) == 0 ? row1Params.bottomMargin : row1Params.bottomMargin+1;
// Actual Height/Width of child
childWidth = (int)(width);
childHeight = (int)(height /2) - (bottomMargin/2);
childHeight -= scrnInfo.getTitleBarHeight();
scrnInfo.setRowHeight(childHeight);
row1Params.height = childHeight;
row1Params.width = childWidth;
row1Params.bottomMargin = (bottomMargin/2);
row2Params.height = childHeight;
row2Params.width = childWidth;
row2Params.topMargin = (bottomMargin/2);
scrnInfo.setChild1LayoutParams(row1Params);
scrnInfo.setChild2LayoutParams(row2Params);
calcTileWidthHeight(childWidth);
calcTileTextSize();
//android.util.Log.i(TAG, "Child W = " + childWidth + " H = " + childHeight + " Tile W = " + scrnInfo.getTileWidth() + " Tile Text Size = " + getTileTextSize());
return;
}
public static void calcTileWidthHeight(int childWidth) {
int margin = 8;
scrnInfo.setTileWidth(((childWidth/3)-margin));
}
public static void findTitleBarHeight(Window win) {
Rect rect = new Rect();
win.getDecorView().getWindowVisibleDisplayFrame(rect);
int statusHeight = rect.top;
int contentViewTop = win.findViewById(Window.ID_ANDROID_CONTENT).getTop();
int titleHeight = contentViewTop - statusHeight;
scrnInfo.setTitleBarHeight(titleHeight); // SET TitleBarHeight
//Log.i(Utility.TAG, "titleHeight = " + titleHeight + " statusHeight = " + statusHeight + " contentViewTop = " + contentViewTop);
return;
}
public static void calcTileTextSize() {
// current is 11 on W = 75 => its small
int w = scrnInfo.getTileWidth();
float ts = 11f;
if (w >= 51 && w <= 70) // Port LDPI W - 54 H -98
ts = 15f;
// Screen 320 * 480 Medium dense
else if (w >= 71 && w <= 80) // Port MDPI
ts = 13f;
else if (w >= 81 && w <= 110) // Land LDPI W - 81 H - 58
ts = 15f;
else if (w >= 111 && w <= 220) // Landscape - Perfect
ts = 18f;
else if (w >= 221 && w <= 250)
ts = 20f;
setTileTextSize(ts);
}
ScreenInfo class contains setters/getters for following members :
public class ScreenInfo {
private int titleBarHeight, screenHeight, screenWidth;
private int rowHeight;
private LinearLayout.LayoutParams child1LayoutParams, child2LayoutParams;
private int _6tiles_Width; // Width of a Tile where 3 tiles on 2rows r shown
NOW comes actual implementation in Activity :
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.datapage);
root = (LinearLayout) findViewById(R.id.dataroot);
row1 = (LinearLayout) findViewById(R.layout.datarow1);
row2 = (LinearLayout) findViewById(R.layout.datarow2);
btn1 = (Button) findViewById(R.id.relationBtn);
btn2 = (Button) findViewById(R.id.productBtn);
btn3 = (Button) findViewById(R.id.bankBtn);
btn4 = (Button) findViewById(R.id.locationBtn);
btn5 = (Button) findViewById(R.id.curencyBtn);
btn6 = (Button) findViewById(R.id.dataReturnBtn);
root.post(new Runnable() {
public void run() {
Utility.findTitleBarHeight(getWindow());
// CALCULATE THE SIZE OF INNER LAYOUTS
//calculateChildSize();
LinearLayout.LayoutParams row1Params = (android.widget.LinearLayout.LayoutParams) row1.getLayoutParams();
LinearLayout.LayoutParams row2Params = (android.widget.LinearLayout.LayoutParams) row2.getLayoutParams();
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
Utility.calculateChildSize(root, row1Params, row2Params, metrics);
row1.setLayoutParams(Utility.scrnInfo.getChild1LayoutParams());
row2.setLayoutParams(Utility.scrnInfo.getChild2LayoutParams());
RefreshComponents();
}
});
}
protected void RefreshComponents() {
// Set background of the root
root.setBackgroundColor(Utility.getBackgroundColor());
// set Gradient Colors & text color of all buttons
RefreshGradientButtons();
}
protected void RefreshGradientButtons() {
GradientDrawable btnGradient = Utility.getButtonDrawable();
int i = -1;
for(i=0; i < row1.getChildCount(); i++) {
Button btn = (Button)row1.getChildAt(i);
btn.setBackgroundDrawable(btnGradient);
btn.setTextColor(Utility.getTextColor());
btn.setTextSize(Utility.getTileTextSize());
}
for(i=0; i < row2.getChildCount(); i++) {
Button btn = (Button)row2.getChildAt(i);
btn.setBackgroundDrawable(btnGradient);
btn.setTextColor(Utility.getTextColor());
btn.setTextSize(Utility.getTileTextSize());
}
}
Whenever screen is changed from Portrait to Landscape or vice-versa OR if at all density is changed at runtime, onCeate is called every such time. Hence this code is added in onCreate(), so the calculations and settings can be appropriately on spot.
In my app, this works like a charm in versions from 1.5 to 3.2 and all density's.
You will have to make changes for your requirement accordingly. As your design is just 3 buttons in a row, while my design for the above code is like Tiles on screen. 2 rows n 3 buttons in each row. I have kept the logs I had added as it will help you to debug and figure out your solution.
This will work 100%.
*I would still recommend to give a try to : just create a new xml and in LinearLayout as parent, add your LinearLayout of buttons and see. Does that work ? While executing try it in both the modes. In your LinearLayout try removing weightSum. According to me, this requirement should be achieved in xml itself. *
BEST LUCK.