e_ori
e_ori

Reputation: 899

ScrollView makes a custom layout invisible

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?

Upvotes: 6

Views: 3420

Answers (5)

Hardik
Hardik

Reputation: 17441

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>

Upvotes: 0

e_ori
e_ori

Reputation: 899

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.

Upvotes: 6

Graeme
Graeme

Reputation: 25864

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

Upvotes: 0

yahya
yahya

Reputation: 4860

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
}

Upvotes: -1

Simo
Simo

Reputation: 1230

<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

Upvotes: 0

Related Questions