0

I've created a simple view that displays buttons with the same width and height and they match the screen width.

When i use this view inside linear layout it shows just fine.

I need this to be inside a vertical layout so when the buttons exceed screen height i want to be able to scroll to view more buttons.

However, putting this view inside the ScrollView makes my widget / view invisible. Something in my layout is wrong, probably. Please help.

Here's my view:

package com.uberaktiv.ui.layout;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;

public class MetroLikeLayout extends ViewGroup {

    private static final int PADDING_TO_EDGES = 2;
    private static final int PADDING_BETWEEN_ITEMS = 4;

    private int viewWidth = 0;
    private int childControlWidth = 0;
    private int childControlHeight = 0;
    private int numberOfGridRowItems = 2;

    public MetroLikeLayout(Context context) {
        super(context, null);
    }

    public MetroLikeLayout(Context context, AttributeSet attrs) {
        super(context, attrs, 0);
    }

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

    public void setNumberOfGridRowItems(int numGridRowItems) {
        this.numberOfGridRowItems = numGridRowItems;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
        int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
        viewWidth = parentWidth;
        childControlWidth = (viewWidth - (PADDING_TO_EDGES * 2) - (PADDING_BETWEEN_ITEMS * (numberOfGridRowItems - 1))) / numberOfGridRowItems;
        childControlHeight = childControlWidth;
        this.setMeasuredDimension(parentWidth, parentHeight);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int row = 0;
        int col = 0;
        for (int i = 0; i < getChildCount(); i++) {
            final View child = getChildAt(i);
            if (child.getVisibility() == GONE) {
                continue;
            }
            if ((i % numberOfGridRowItems) == 0) {
                row++;
                col = 1;
            }
            int left = PADDING_TO_EDGES + ((col - 1) * (childControlWidth + PADDING_BETWEEN_ITEMS));
            int top = PADDING_TO_EDGES + ((row - 1) * (childControlHeight + PADDING_BETWEEN_ITEMS));
            child.layout(left, top, left + childControlWidth, top + childControlHeight);
            col++;
        }
    }
}

Here's my Layout:

<LinearLayout android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:ubergrid="http://schemas.android.com/apk/res/com.uberaktiv.ui.layout.MetroLikeLayout">
    <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="above the table" android:layout_weight="0.0" />
    <ScrollView android:layout_width="match_parent" android:id="@+id/scrollView1" android:layout_height="fill_parent" android:layout_weight="1.0">
        <com.uberaktiv.ui.layout.MetroLikeLayout android:layout_width="fill_parent" android:layout_height="wrap_content">
            <Button android:text="Button 1" android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
            <Button android:text="Button 2" android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
            <Button android:text="Button 3" android:id="@+id/button3" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
            <Button android:text="Button 4" android:id="@+id/button4" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
            <Button android:text="Button 5" android:id="@+id/button5" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
        </com.uberaktiv.ui.layout.MetroLikeLayout>
    </ScrollView>
</LinearLayout>

The main activity is the most simple one:

public class MainActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
}

Please help as i'm getting frustrated and don't know what i'm doing wrong. As I've written above... if you replace the scroll view with another linear layout, or even just place the custom view right after the text widget, it all works.

Looking forward to your help and sorry for the big chunk of code and test.

Moshe

  • What is the xmlns:ubergrid="http://schemas.android.com/apk/res/com.uberaktiv.ui.layout.MetroLikeLayout" for? – Jack Aug 08 '11 at 21:29
  • Jack, this is used as part of defining your own custom attributes that you can enhance the layout and provide your own behavior, style or whatever. you can see a very good example of how it's done here: http://stackoverflow.com/questions/3441396/defining-custom-attrs – Moshe Bar-Nachoom Aug 09 '11 at 14:04

1 Answers1

0

Try putting the ScrollView inside the MetroLikeLayout around just the buttons like this...

<com.uberaktiv.ui.layout.MetroLikeLayout android:layout_width="fill_parent" android:layout_height="wrap_content">
    <ScrollView android:layout_width="match_parent" android:id="@+id/scrollView1" android:layout_height="fill_parent" android:layout_weight="1.0">
        <Button android:text="Button 1" android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
        <Button android:text="Button 2" android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
        <Button android:text="Button 3" android:id="@+id/button3" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
        <Button android:text="Button 4" android:id="@+id/button4" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
        <Button android:text="Button 5" android:id="@+id/button5" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
    </ScrollView>
</com.uberaktiv.ui.layout.MetroLikeLayout>
Squonk
  • 48,735
  • 19
  • 103
  • 135
  • Thanks MisterSquonk. I will try your solution, although I fear, at first glance it may not do. The MetroLikeLayout view goes over its direct children and positions them according to the calculated sizes, which allow the requested functionality. my initial thought is that my view will calculate and try resize and reposition of the scrollview and not the children. however, i will try and may need to change the code. Thanks for the help. – Moshe Bar-Nachoom Aug 09 '11 at 13:41
  • MisterSquonk, even though i prefer to understand what's the problem with my layout settings, i now thought of an idea in which i will programaticaly add a scroll view to my custom view and then loop through the children. but even just for academic reasons, I'd like to know what i'm missing in my layout above. – Moshe Bar-Nachoom Aug 09 '11 at 13:44