6

I made a custom Viewgroup which i need to use in my application, but i need to put it in a ScrollView. When the layout is made only with my custom ViewGroup everything works fine, but when I put it in a ScrollView i can't see anything. My layout:

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/scrollView1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >

    <com.example.test.CustomLayout
        android:id="@+id/layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    </com.example.test.CustomLayout>

</ScrollView>

My viewgroup:

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            /* do something and call for each child             
                    View v = getChildAt(i);
                    v.measure(wspec, hspec);
                    */

        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));

    }

    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        // TODO Auto-generated method stub
        //do something and call layout on every child 
    }

UPDATE: My CustomLayout class

public class CustomLayout extends ViewGroup{

    /*My params*/

    public CustomLayout(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
    }

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

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

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        // TODO Auto-generated method stub
            //do something and call layout on every child 
    }

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
                /* do something and call for each child             
                        View v = getChildAt(i);
                        v.measure(wspec, hspec);
                        */

            setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));

    }

}

UPDATE 2: Sorry but I made some other tries and it looks like if I have the viewgroup in a scrollview on the onMeasure method i got heightMeasureSpec = 0, then if I put the viewgroup in any other layout, i got an integer. Maybe this would help?

e_ori
  • 845
  • 1
  • 11
  • 29

5 Answers5

6

I got it, I had to measure the Viewgroup myself, or else i got no height at all.
So:

int heightMeasured = 0;
/*for each child get height and
heightMeasured += childHeight;*/


//If I am in a scrollview i got heightmeasurespec == 0, so
if(heightMeasureSpec == 0){
heightMeasureSpec = MeasureSpec.makeMeasureSpec(heightMeasured, MeasureSpec.AT_MOST);
}

setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), getDefaultSize(this.getSuggestedMinimumHeight(), heightMeasureSpec));

Now for me it works.

e_ori
  • 845
  • 1
  • 11
  • 29
0
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/scrollView1"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

try to change android:layout_height to match_parent

Simo
  • 1,200
  • 1
  • 16
  • 26
0

You're using wrap_content for the height:

<com.example.test.CustomLayout
    android:id="@+id/layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >

Which would resolve to 0px afaik as there is no content - try giving you're component a default minimum height

Graeme
  • 25,714
  • 24
  • 124
  • 186
  • Done that, still I don't see anything – e_ori Apr 16 '13 at 10:11
  • Is your Custom Layout drawing anything? Try setting android:background="@android:color/black" on your view - does this give you a black box? – Graeme Apr 16 '13 at 10:37
  • Yes, there is the scrollview, it turns all black if i put that background. – e_ori Apr 16 '13 at 13:10
  • Can you add the background to your CustomLayout (not the ScrollView)? – Graeme Apr 16 '13 at 13:12
  • Uhm... I tried and nothing is black... It looks like it doesen't draw it – e_ori Apr 16 '13 at 13:15
  • try removing your onMeasure() method - it's the only thing I can see which would make things a bit... wobbly. – Graeme Apr 16 '13 at 13:20
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/28316/discussion-between-dlock-and-graeme) – e_ori Apr 16 '13 at 13:24
  • UPDATE 2: Sorry but I made some other tries and it looks like if I have the viewgroup in a scrollview on the onMeasure method i got heightMeasureSpec = 0, then if I put the viewgroup in any other layout, i got an integer. Maybe this would help? – e_ori Apr 16 '13 at 14:49
0

Check this would work perfect!

 public class MaxHeightScrollView extends ScrollView {

    public static int DEFAULT_MAX_HEIGHT = -1;
    private int maxHeight = DEFAULT_MAX_HEIGHT;

    public MaxHeightScrollView(Context context) {
        super(context);
    }

    public MaxHeightScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray a = context.getTheme().obtainStyledAttributes(
                attrs,
                R.styleable.ScrollMaxHeight,
                0, 0);
        try {
            setMaxHeight(a.getInt(R.styleable.ScrollMaxHeight_maxHeight, 0));
        } finally {
            a.recycle();
        }
    }

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

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        try {
            int heightSize = MeasureSpec.getSize(heightMeasureSpec);
            if (maxHeight != DEFAULT_MAX_HEIGHT
                    && heightSize > maxHeight) {
                heightSize = maxHeight;
                heightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.AT_MOST);
                getLayoutParams().height = heightSize;

            } else {
                heightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.AT_MOST);
                setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec)
                        , getDefaultSize(this.getSuggestedMinimumHeight(), heightMeasureSpec));
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }

    public void setMaxHeight(int maxHeight) {
        this.maxHeight = maxHeight;
    }


}

make attr.xml in values folder and add below code

<resources>
   <declare-styleable name="ScrollMaxHeight">
        <attr name="maxHeight" format="integer"/>
    </declare-styleable>
</resources>

Use like this

<com.yourapppackage.customviews.MaxHeightScrollView
    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="wrap_content"
    app:maxHeight="200"
    android:fadeScrollbars="false"
    android:gravity="center_horizontal">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        ...........
         ............
    </LinearLayout>

</com.yourapppackage.customviews.MaxHeightScrollView>
Hardik
  • 17,179
  • 2
  • 35
  • 40
-1

You are also using this contructor below, right? Because this is the one get called when you create your view in xml.

public CustomLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
        // Do your stuff
}
yahya
  • 4,810
  • 3
  • 41
  • 58