tags:

views:

70

answers:

3

Hi all; please excuse the crude photoshop job. but this image should show pretty succinctly what I'm trying to do:

buttons

In a nutshell, I want the buttons evenly spaced along the height of my screen, and I'd like them to be all the same size. Is there a reasonable way to do this?

+2  A: 

You can try something like this:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout android:id="@+id/FrameLayout01" android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  xmlns:android="http://schemas.android.com/apk/res/android" android:layout_weight="1">

<Button android:text="@+id/Button01" android:id="@+id/Button01" 
android:layout_width="wrap_content" android:layout_height="wrap_content" 
android:layout_gravity="top|left">
</Button>
<Button android:text="@+id/Button02" android:id="@+id/Button02" 
android:layout_width="wrap_content" android:layout_height="wrap_content" 
android:layout_gravity="top|right"></Button>
<Button android:text="@+id/Button03" android:id="@+id/Button03"
android:layout_width="wrap_content" android:layout_height="wrap_content" 
android:layout_gravity="left|center_vertical"></Button>
<Button android:text="@+id/Button04" android:id="@+id/Button04" 
android:layout_width="wrap_content" android:layout_height="wrap_content" 
android:layout_gravity="right|center_vertical"></Button>
<Button android:text="@+id/Button05" android:id="@+id/Button05" 
android:layout_width="wrap_content" android:layout_height="wrap_content" 
android:layout_gravity="bottom|left"></Button>
<Button android:text="@+id/Button06" android:id="@+id/Button06" 
android:layout_width="wrap_content" android:layout_height="wrap_content" 
android:layout_gravity="bottom|right"></Button>

</FrameLayout>

And if you need more than three rows, you can define a LinearLayout and fill it with FrameLayout where every frame contains two buttons.

Asahi
+1  A: 

Hi; thanks for the ideas; they helped me focus on the problem.

Sometimes, however, you just have to bite the bullet and do it in code. Here's a quick-and-dirty implementation as a custom ViewGroup. Might have been easier to just do this in onCreate(), after setting the layout, but this worked for me.

/**
 * $Id$
 *
 * SideLayout.java - Quick-and-dirty button layout
 *
 * Author: Edward A. Falk
 *         [email protected]
 *
 * Date: Aug 2010
 *
 * Overview: this container widget takes its children and lays
 * them out in two columns, on the left and right edges of the
 * parent.  Children are evenly spaced and forced to be all the
 * same size.
 */

import java.lang.Math;
import android.view.View;
import android.view.ViewGroup;
import android.content.Context;
import android.util.AttributeSet;

public class SideLayout extends ViewGroup {

    private int max_wid, max_hgt;

    public SideLayout(Context ctx) {
      super(ctx);
    }

    public SideLayout(Context ctx, AttributeSet attrs) {
      super(ctx, attrs);
    }

    public SideLayout(Context ctx, AttributeSet attrs, int defStyle) {
      super(ctx, attrs, defStyle);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        final int num_children = getChildCount();

        // Since this is a special-purpose widget, this is brute simple.  All
        // of our children will have sizes of wrap_content, so we query them
        // all, then make a second pass assigning their final sizes.

        max_wid = 0;
        max_hgt = 0;
        for( int i = 0; i < num_children; ++i )
        {
            final View child = getChildAt(i);
            if( child != null && child.getVisibility() != View.GONE )
            {
                measureChild(child, widthMeasureSpec, heightMeasureSpec);
                max_wid = Math.max(max_wid, child.getMeasuredWidth());
                max_hgt = Math.max(max_hgt, child.getMeasuredHeight());
            }
        }

        // Make a second pass, tell children the actual size they got.
        for( int i = 0; i < num_children; ++i )
        {
            final View child = getChildAt(i);
            if( child != null && child.getVisibility() != View.GONE )
            {
                child.measure(
                  MeasureSpec.makeMeasureSpec(max_wid, MeasureSpec.EXACTLY),
                  MeasureSpec.makeMeasureSpec(max_hgt, MeasureSpec.EXACTLY));
            }
        }

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b)
    {
        final int num_children = getChildCount();
        int x,y;

        if( num_children <= 0 )
          return;

        // Split the children into two groups, left and right.  Each
        // column is evenly-spaced.

        int wid = r - l;
        int hgt = b - t;
        int nrow = (num_children + 1) / 2;
        int margin = (hgt - max_hgt * nrow) / (nrow + 1);

        int i = 0;
        for( int col = 0; col < 2; ++col ) {
            x = col == 0 ? 0 : wid - max_wid;
            y = margin;
            for( int row = 0; row < nrow; ++row, ++i ) {
                if( i < num_children ) {
                    final View child = getChildAt(i);
                    if( child != null && child.getVisibility() != View.GONE )
                      child.layout(x, y, x+max_wid, y+max_hgt);
                }
                y += margin + max_hgt;
            }   
        }   
    }   
}
Edward Falk
p.s. if anybody has criticisms on my code, I'm interested in hearing them.
Edward Falk
A: 

You could use a GridView for this: http://developer.android.com/reference/android/widget/GridView.html

aschmack
Thanks, but GridView is an AdapterView; its contents come from an Adapter.Or is there a way to use GridView with fixed content?
Edward Falk
You'd want to create a wrapper class with things such as Button label, drawable, onClick function (extends OnClickListener). Then make an array of these objects and set it as the adapter. Then you'd manage the creation of views/buttons in getView()
aschmack