I have this layout:
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RadioGroup
android:id="#+id/MyTabs"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<RadioButton ... />
<RadioButton ... />
</RadioGroup>
<SquareImageView
android:layout_height="match_parent" />
</LinearLayout>
and here's the code for the SquareImageView:
public class SquareImageView extends ImageView {
public SquareImageView(Context context) {
super(context);
}
public SquareImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SquareImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int size = getMeasuredHeight();//Math.min(getMeasuredWidth(), getMeasuredHeight());
setMeasuredDimension(size, size);
}
}
Now, what I want to achieve is this:
I want the RadioGroup to occupy as much space as possible. The height of the LinearLayout should adapt to the required height of the RadioGroup. Each RadioButton should occupy 50% of the RadioGroup. The SquareImageView should adapt it's height to match the height of the LinearLayout, and it's width should also adapt to make it square.
Is this even possible?
The RadioGroup is no problem on it's own, but the tricky part is the square ImageView because I cannot get it to adapt it's width automatically. It is square, but I need to set the width of it manually. If I do not set a width manually it seems to be square (in the Eclipse Preview Layout Manager) but it ends up outside of the screen and the RadioGroup occupies the entire screen width. If I set a too wide width there is dead space to the right of it.
Tried fiddling with all kinds of settings but nothing gets it quite right. I would like to avoid setting dimensions in absolute values, and rather let the height of the RadioGroup determine the rest of the Views' dimensions...
Try this:
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RadioGroup
android:id="#+id/MyTabs"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weig="1" >
<RadioButton
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
... />
<RadioButton
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
... />
</RadioGroup>
<SquareImageView
android:layout_width="0dp"
android:layout_height="match_parent" />
</LinearLayout>
You can try below steps:
1, Set the layout as below:
<RadioGroup
android:id="#+id/MyTabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="1" >
<RadioButton
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.5"
... />
<RadioButton
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.5"
... />
</RadioGroup>
<SquareImageView
android:layout_width="0dp"
android:layout_height="match_parent" />
2, Once the view loads, programatically find the height of linear layout and then programatically set the width of the squareview to this same value to make it a square
3, Find the width of the screen and then set the width of the radio group to the difference between screen width and above sqaureview width so that it occupies the remaining screen width.
Related
Hopefully I'm not being completely thick here, but I'm unable to align the baseline of a TextView to a Guideline in a ConstraintLayout. It appears the guideline does not have a baseline, which is pretty annoying. Does anyone know how I might achieve this? Here's a bit of layout xml that doesn't work (this is within a ConstraintLayout):
<TextView
android:id="#+id/textToAlignBaseline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:maxLines="1"
android:paddingRight="6dp"
android:textAppearance="#style/TextStyles.Body"
app:layout_constraintBaseline_toBaselineOf="#+id/guidelineBottomMargin"
app:layout_constraintLeft_toLeftOf="parent" />
<Button
android:id="#+id/buttonToAlignBottom"
android:layout_width="wrap_content"
android:layout_height="39dp"
android:layout_marginRight="20dp"
android:background="#drawable/selector_button_bg"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:text="#string/clickme"
android:textAppearance="#style/TextStyles.Body"
app:layout_constraintBottom_toTopOf="#+id/guidelineBottomMargin"
app:layout_constraintRight_toRightOf="parent" />
<android.support.constraint.Guideline
android:id="#+id/guidelineBottomMargin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_end="20dp" />
I had this question when I tried to implement a two-line list according to Material Design, where the "Two-line item" baseline should be 32dp from the top:
It looks like a plain View or Guideline doesn't have a baseline because it returns -1 from getBaseline. So what I ended up with is using an invisible TextView like this:
<TextView
android:id="#+id/guideline"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="32dp"
android:textSize="0sp"
android:visibility="invisible"
app:layout_constraintTop_toTopOf="parent" />
And then use app:layout_constraintBaseline_toBaselineOf="#id/guideline" for aligning the other view to it.
I think I might have come up with a solution, I tried extending Baseline and returning 0 from 'getBaseline' but that was never called, so I tried extending AppCompatButton instead and returning 'getMeasuredHeight' from 'getBaseline' instead (just like ImageView does when 'baselineAlignBottom' is used) and this seems to work correctly now. The TextView just needs changing to align its baseline to the button instead of the guideline. I need to clean it up with attributes similar to ImageView but this is what I've got for now:
public class ButtonBottomBaseline extends android.support.v7.widget.AppCompatButton {
public ButtonBottomBaseline(Context context) {
super(context);
}
public ButtonBottomBaseline(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ButtonBottomBaseline(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public int getBaseline() {
return getMeasuredHeight();
}
}
I've found a workaround to align the text following exactly the Material Design guideline as mentioned by #robinst .
Firstly add an ImageView, with 0 as layout_width, your desired baseline as layout_height, no src and baselineAlignBottom set to true:
<ImageView
android:id="#+id/typeTextBaseline"
android:layout_width="0dp"
android:layout_height="24dp"
android:baselineAlignBottom="true"
android:visibility="invisible"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
Then you can align your TextView's baseline to this ImageView's baseline:
<TextView
android:id="#+id/typeTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:textAppearance="#style/TextAppearance.MaterialComponents.Overline"
app:layout_constraintBaseline_toBaselineOf="#id/typeTextBaseline"
app:layout_constraintStart_toStartOf="parent" />
I found this workaround when searching all implementations of View's getBaseline method, and the ImageView's implementation is as follow:
public int getBaseline() {
if (mBaselineAlignBottom) {
return getMeasuredHeight();
} else {
return mBaseline;
}
}
So, once you set baselineAlignBottom to true, the ImageView's baseline becomes its bottom edge and it is magically served as a guideline now:)
I have the following GridView defined w/stretchMode set to "columnWidth".
<GridView android:id="#+id/grid"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:columnWidth="160dp"
android:numColumns="auto_fit"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
android:stretchMode="columnWidth"
android:listSelector="#drawable/list_selector"
/>
Each item in the GridView is structured as follows.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="2dp"
>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<ImageView android:id="#+id/videoGridItemImage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
/>
<TextView android:id="#+id/videoGridItemDuration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="#88000000"
android:textColor="#F1F1F1"
android:textAppearance="#android:style/TextAppearance.Small"
android:padding="2dp"
/>
</FrameLayout>
<TextView android:id="#+id/videoGridItemTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="left"
android:textAppearance="#android:style/TextAppearance.Medium"
android:textColor="#F1F1F1"
android:maxLines="1"
android:background="#88000000"
android:paddingLeft="2dp"
android:paddingRight="2dp"
/>
<TextView android:id="#+id/videoGridItemSubtitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="left"
android:textStyle="italic"
android:textColor="#666"
android:textAppearance="#android:style/TextAppearance.Small"
android:maxLines="1"
android:background="#88000000"
android:paddingLeft="2dp"
android:paddingRight="2dp"
/>
</LinearLayout>
In the GridView's adapter, I'm async loading and displaying the images by passing the url and reference of the ImageView to a dedicated class. The class downloads the image into a bitmap and then updates the ImageView using setImageBitmap(). This workflow functions as expected; however, my images aren't filling the entire width of the ImageView. There's a small amount of paddding on the left/right sides. I realize that I can use scaleType="fitXY", but this isn't ideal as it skews the images. Setting the src attribute of ImageView to a local image scales just fine with stretchMode="columnWidth". My guess is that the ImageView is scaling to the original columnWidth and not the stretched/dynamic width. Does anyone have any insight as to why this is occurring and/or how to fix? Thanks in advance for your help.
You have two options:
Set your ImageView's layout_width to wrap_content. The ImageView will resize based on the size of the image and your column will adjust accordingly.
Set your ImageView's scaleType to centerCrop. This will try to fit the image into the imageview without skewing it and will just cut off any excess that doesn't fit. This will leave no blank space.
I had the same issue. My solution was to override the ImageView (in my case) FrameLayout to set it's height prior to image download. I wanted square tiles enforced in my GridView, and accomplished like so:
public class SquareFrameLayout extends FrameLayout {
public SquareFrameLayout(Context context) {
super(context);
}
public SquareFrameLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SquareFrameLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}
}
Each GridView item is this:
<com.my.client.ui.layout.SquareFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/discovery_tile"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ImageView
android:id="#+id/my_image"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="centerCrop"
android:cropToPadding="true"
android:contentDescription="#string/my_desc" />
</com.my.client.ui.layout.SquareFrameLayout>
Then in the GridView I used this:
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:name="com.my.client.ui.MyFragment"
android:id="#+id/my_gridview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:numColumns="3"
android:verticalSpacing="0px"
android:horizontalSpacing="0px"
android:stretchMode="columnWidth"
android:gravity="fill" />
In my horizontal LinearLayout I have a TextEdit and an ImageButton. The ImageButton is as high as the TextEdit.
I'd like that the ImageButton is exactly as wide as it's long.
At the moment it looks like the width of the ImageButton is like when there is no scaling (ImageButton width [px] = unscaled drawable width [px]):
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<EditText
android:id="#+id/txtName"
android:layout_width="1dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<ImageButton
android:id="#+id/btSet"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:scaleType="fitEnd"
android:src="#drawable/pin2" />
</LinearLayout>
How it should look like:
Try this, I think this should work:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:orientation="horizontal" >
<ImageButton
android:id="#+id/btSet"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:scaleType="centerInside"
android:adjustViewBounds="true"
android:src="#drawable/pin2" />
<EditText
android:id="#+id/txtName"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_toLeftOf="#id/btSet" />
</RelativeLayout>
Explaination: centerInside will assure that the image will scale proportionally within the bounds of the ImageButton. adjustViewBounds="true" will...well, adjust the view's bounds, if the image needed to be scaled.
try adding
adjustViewBounds="true"
to the ImageButton, that should clip the excess width
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<EditText
android:id="#+id/txtName"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<ImageButton
android:id="#+id/btSet"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:src="#drawable/pin" />
</LinearLayout>
Use
android:scaleType="fitCenter"
or android:scaleType="centerInside"
in the ImageButton in xml File.
I might be a bit late to the party.
However there's an easy way to achieve this behavior by overriding the onMeasure().
Here's how it'd look like :
public class MySquareImageButton extends ImageButton {
public MySquareImageButton(Context context) {
super(context);
}
public MySquareImageButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MySquareImageButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//(1)if you want the height to match the width
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
//(2)if you want the width to match the height
//super.onMeasure(heightMeasureSpec, heightMeasureSpec);
}
}
And then you'd simply replace your XML's ImageButton with this custom one :
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<EditText
android:id="#+id/txtName"
android:layout_width="1dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<com.whatever_your_package.MySquareImageButton
android:id="#+id/btSet"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:scaleType="fitEnd"
android:src="#drawable/pin2" />
</LinearLayout>
You'd simply put wrap_content to width or height, depending on which one you want to dictate the size of your button.
In the case you want your button to wrap its height to the image, and that the width simply matches the height, you'd use
android:layout_width="wrap_content"
android:layout_height="wrap_content"
and use
//(2)if you want the width to match the height
//super.onMeasure(heightMeasureSpec, heightMeasureSpec);
I had the same problem.
I was trying to create something that looked like this:
But what I was getting was this:
The ImageButton was getting stretched horizontally.
All the top answers didn't work for me. But I noticed people mentioning layout_weight and just looked it up out of curiosity and found the following on Android docs:
Layout Weight
LinearLayout also supports assigning a weight to individual children with the android:layout_weight attribute. This attribute assigns an "importance" value to a view in terms of how much space it should occupy on the screen. A larger weight value allows it to expand to fill any remaining space in the parent view. Child views can specify a weight value, and then any remaining space in the view group is assigned to children in the proportion of their declared weight. Default weight is zero.
For example, if there are three text fields and two of them declare a weight of 1, while the other is given no weight, the third text field without weight will not grow and will only occupy the area required by its content. The other two will expand equally to fill the space remaining after all three fields are measured. If the third field is then given a weight of 2 (instead of 0), then it is now declared more important than both the others, so it gets half the total remaining space, while the first two share the rest equally
So basically, if you set the layout_width to be 0 for an element, it'll appear according to the dimensions of its content.
If you set it to anything else, the element will fight for extra space in the parent element that contains it; with more weighted elements taking up more space.
So, when I set layout_width = 0 for both TextView and ImageButton in my example, neither of them takes up any extra space and they both huddle up to the left.
But when I set it to 1 for TextView and 0 for ImageButton, the ImageButton doesn't take any more space than required by its content; while the TextView takes up all the extra space and pushes ImageButton to the right.
Just the way I want it.
Initially, what had happened was both the elements were set to have a default layout_weight of 1 and hence both were equally competing for the extra space.
Simply use the weightSum to devide the size of controls accordingly...
<?xml version="1.0" encoding="utf-8" ?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="1.0" >
<EditText
android:id="#+id/txtName"
android:layout_weight="0.8"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:inputType="text"
android:singleLine="true"/>
<ImageButton
android:id="#+id/btSet"
android:layout_weight="0.2"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:scaleType="fitEnd"
android:src="#drawable/pin2" />
</LinearLayout>
</LinearLayout>
Hope it will help you.
as you want your ImageButton is stretchable & exactly as wide as it's long, its better to use NinePatch Image. you may find help form here Draw 9-patch & How does Android’s nine-patch tool work ?
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="1.0" >
<EditText
android:id="#+id/txtName"
android:layout_weight="0.75" // this work like percentage adjust as u want 70 or 75
android:layout_height="wrap_content"
android:layout_width="0dp"
android:inputType="text"
android:singleLine="true"/>
<ImageButton
android:id="#+id/btSet"
android:layout_weight="0.25" // this work like percentage adjust as u want 25 or 30
android:layout_height="wrap_content"
android:layout_width="0dp"
android:scaleType="fitEnd"
android:src="#drawable/pin2" />
</LinearLayout>
Just add the following line to your ImageButton and the extra background will fade away:
android:layout_gravity="center|clip_horizontal"
hope this works
Just ran into something like this and the other suggestions didn't help. What did help was setting the padding in the ImageButton:
android:padding="5dp"
Besides that, I didn't touch the original layout. The button became square on the 3 emulators that I tested (3.2, 4.4.2, 5.1)
I tried myself,it works
Simply do the Following...
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:id="#+id/editText1"
android:layout_width="0dp"
android:layout_weight="5"
android:layout_height="wrap_content"
android:inputType="text"/>
<ImageButton
android:id="#+id/imageButton"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent" />
</LinearLayout>
Use Layout Weight ratio 5:1 inside a LinearLayout for EditText and ImageButton
You Can resize the Image button using px... like below...
`android:layout_width="5px"
android:layout_height="5px"`
I have a custom view like this
public class ButtonBar extends HorizontalScrollView
{
public View mButtonRows;
public ButtonBar(Context context, AttributeSet attrs)
{
super(context, attrs);
LayoutInflater inflater = (LayoutInflater)
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mButtonRows = inflater.inflate(R.layout.toolbar, null);
// button click handling code goes here
addView(mButtonRows);
}
}
which is included in my main xml like this
<com.example.ButtonBar
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_below="#+id/pagecontent" />
and inflates an xml file like this:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/ButtonsRow"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="#+id/button1"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_weight="0.3"
android:text="button1"
/>
<Button
android:id="#+id/button2"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_weight="0.3"
android:text="button2"
/>
<Button
android:id="#+id/button3"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_weight="0.3"
android:text="button3"
/>
</LinearLayout>
(It currently only has three buttons, but more are going to be needed in later versions, hence the HorizontalScrollView.)
Looking in hierarchyviewer, the custom view does seem to be screen wide, but the LinearLayout is only as wide as the buttons it contains (about 2/3 of the screen at the current button size), despite having the fill_parent width set; the buttons don't stretch. If I set the LinearLayout's background to #android:drawable/bottom_bar (which is a png the width of the screen), the buttons properly resize; I realise I could do the same thing by creating my own images to match, but I'd much rather do it without if possible.
What am I doing wrong?
ETA: if I change HorizontalScollView to ScrollView, it works fine. Do HSVs just not allow their children to "fill_parent"?
ETA2: Setting android:fillViewport="true" in the main xml fixed it!
Setting android:fillViewport="true" in the main xml fixed it!
If you change to this, for each of the buttons, does it work?
android:layout_width="0px"
android:layout_weight="1"
I have 5 square ImageButtons that I want to have lined up side by side on the bottom of the screen. I have each one set (different id's) as:
<ImageButton
android:id="#+id/box1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:scaleType="fitXY"
android:layout_weight="1"
android:layout_margin="1dp"
/>
and I have the background assigned in main java like this:
int[] imageIds = new int[] {R.id.box1,R.id.box2,R.id.box3,R.id.box4,R.id.box5};
for(int i = 0; i<5; i++){
imageButtons[i] = (ImageButton) findViewById(imageIds[i]);
imageButtons[i].setBackgroundResource(R.drawable.blank);
}
What I would like to have it do is scale the width to fit neatly side-by-side at the bottom of the screen (which it does now ok), but have the height automatically scale to match the width as well. is this possible? I don't want to use setImageSource because then it puts a border around the imagebutton.
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/layoutButtons">
<com.package.SquareButton
android:layout_height="fill_parent"
android:layout_width="0dip"
android:layout_weight="1"
<ImageView
android:id="#+id/box1"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:scaleType="centerInside"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"/>
</com.package.SquareButton>
<com.package.SquareButton
android:layout_height="fill_parent"
android:layout_width="0dip"
android:layout_weight="1"
<ImageView
android:id="#+id/box2"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:scaleType="centerInside"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"/>
</com.package.SquareButton>
.........
</LinearLayout>
And then add this custom button class:
public class SquareButton extends LinearLayout {
public SquareButton(Context context) {
super(context);
}
public SquareButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
// This is used to make square buttons.
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}
}
I have had a similar headache in trying to get my buttons in a row. The solution I found was to use ImageButton and the android:src property (setImageSource in code) in combination with android:background="#null"
As I understand it the background of an image button doesn't get affected by the adjustViewBounds, it is only the imageView which you set in android:src.
The default behavior is then to give you a square button with the imageView in the middle of it. You can override that by setting the background to #null, which leaves you with only the image.
You can then use either a LinearLayout or a table to layout your buttons. I did everything in XML and used the following layout to create a row of two buttons at the bottom of the screen that scale up or down maintaining the aspect ratio with different device screens sizes. Hope this helps.
<TableLayout
android:id="#+id/tableLayout2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="20dip"
android:stretchColumns="*">
<TableRow>
<ImageButton
android:id="#+id/button_one"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:layout_weight="0.5"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
android:onClick="clickOne"
android:background="#null"
android:src="#drawable/button_one_drawable" />
<ImageButton
android:id="#+id/button_two"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:layout_weight="0.5"
android:adjustViewBounds="true"
android:scaleType="centerInside"
android:onClick="clickTwo"
android:background="#null"
android:src="#drawable/button_two_drawable" />
</TableRow>
</TableLayout>
Instead of
android:scaleType="fitXY"
use:
android:scaleType="centerInside"
EDIT1: Try this one:
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/layoutToInflateButtons"
>
<ImageButton
android:id="#+id/box1"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:scaleType="centerInside"
android:layout_weight="1"
android:layout_margin="1dp"
/>
</LinearLayout>
You can use Google's Percent Relative Layout that helps you to manage view aspect ratio.
You can use it like this
<android.support.percent.PercentRelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageButton
android:id="#+id/box1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:scaleType="fitXY"
app:layout_aspectRatio="100%"
android:layout_weight="1"
/>
</android.support.percent.PercentFrameLayout>
The aspect ratio 100% will make width same as height.
example:
android:layout_width="300dp"
app:layout_aspectRatio="178%"
a width 178% of the height. This is the format the layout_aspectRatio expects
You can read it in detail here
I am sure you want to have that 5 buttons of EQUAL width/height. If this is the case then take LinearLayout and put all those 5 buttons with layout_width="0dip" and layout_weight="1"
For example:
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/layoutButtons">
<ImageButton
android:id="#+id/box1"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:scaleType="centerInside"
android:layout_height="wrap_content"
android:layout_width="0dip"
android:layout_weight="1"/>
<ImageButton
android:id="#+id/box2"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:scaleType="centerInside"
android:layout_height="wrap_content"
android:layout_width="0dip"
android:layout_weight="1"/>
.........
</LinearLayout>
After checking Google I/O sample application from this year I've found that Google is using dimen values for specifying varios heights or widths based on the screen type. For details you can check the source code from http://code.google.com/p/iosched/.
You can specify the height of the button for exemple in values-xhdpi or values-sw720dp as:
<resources>
<dimen name="button_height">50dp</dimen>
</resources>
And then you can just use this dimen value when specifying the height:
android:layout_height="#dimen/button_height"
Set the width of the ImageButtons to fill_parent and use scaletype fitStart for the images that hug the left margin, and fitEnd for the ones on the right. Should do the trick, at least as far as your example image goes. You may have some spacing issues if the proportional width of the images exceed the screen width, but it should work for you.
ViewGroup.LayoutParams params = imageButtonName.getLayoutParams();
// Changes the height(or width) and width(or height) to the specified
params.height = layout.getWidth();
Look into making a custom ImageButton. I like this because its one class. Here is a button that adjusts its height based on the image aspect ratio. I imagine you can tweak to your needs :
public class AspectImageButton extends ImageButton {
public AspectImageButton(Context context) {
super(context);
// TODO Auto-generated constructor stub
this.getDrawable();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = getMeasuredWidth();
Drawable d=this.getDrawable(); //grab the drawable
float fAspectRatio=(float)d.getIntrinsicWidth()/(float)d.getIntrinsicHeight();
float fHeight=(float)width/fAspectRatio;//get new height
setMeasuredDimension(width, (int)fHeight);
}
public AspectImageButton(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public AspectImageButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
}
then in xml just use it like this:
<com.package.AspectImageButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="#drawable/home_1b"
android:background="#null"
android:scaleType="fitXY"
android:adjustViewBounds="true" />