Android: Resizing custom views. Parent is resized but width/height changes not passed down to child view
Asked Answered
A

1

11

I am currently trying to make a game based on the old school battleship board game using android. I am kinda just messing around at the moment trying to get a feel for it and for the components that I may need to make the game.

Basically what I have at the moment in my layout xml file is the following:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<org.greene.battleship.BoardView
    android:id="@+id/board_view"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:clickable="true" />
    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
        <org.greene.battleship.ShipView
            android:id="@+id/ships_view"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:clickable="true" />
    </RelativeLayout>
</RelativeLayout>

I want the BoardView to only take up a certain portion of the screen i.e. the view should be size of the content that I want to create in this view. Which in this case is a 2D board. This is done by overriding the onMeasure() method from extending View. The view's width is kept the same but the height is given the same value as the width giving a perfect square.

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){

    int parent_width = MeasureSpec.getSize(widthMeasureSpec);
    this.setMeasuredDimension(parent_width, parent_width);
    Log.d("BOARD_VIEW", "BoardView.onMeasure : width = " + this.getMeasuredWidth() + ", height = " 
            + this.getMeasuredHeight());
}

I check to see if the views dimensions have changed by overriding the views onSizeChanged() function and checking the values there.

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh){
    Log.d("BOARD_VIEW", "BoardView.onSizeChanged : width = " + w + ", height = " + h);
    board = new Board(w, h, game_activity);
    super.onSizeChanged(w, h, oldw, oldh);

}

As can be seen from the layout file, I then have a RelativeLayout view group that holds another custom view called ShipView as a child. And ideally what I want to have happen is when I go to measure its dimensions, its dimensions have been confined to what has been set in onMeasure. I check the dimensions of the ShipView via its onMeasure() method in a similar way.

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){

    int parent_width = MeasureSpec.getSize(widthMeasureSpec);
    int parent_height = MeasureSpec.getSize(heightMeasureSpec);

    Log.d("SHIP_VIEW", "ShipView.onMeasure : width = " + parent_width + ", height = " + parent_height);

    this.setMeasuredDimension(parent_width, parent_height);

    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

The log files show me the following (the onMeasure() method seems to get called more than once but all the values are the same so I wont bother showing the multiple logs as the values are all the same) :

05-04 16:36:19.428: DEBUG/BOARD_VIEW(405): BoardView.onMeasure : width = 320, height = 320
05-04 16:36:19.939: DEBUG/BOARD_VIEW(405): BoardView.onSizeChanged : width = 320, height = 320
05-04 16:36:20.429: DEBUG/SHIP_VIEW(405): ShipView.onMeasure : width = 320, height = 430

It seems that when I get the dimensions via the ShipViews onMeasure() nothing has changed and ignores the dimension restrictions I have set. I am not sure whether it has something to do with the RelativeLayout of the ShipView. Do I have to set the LayoutParams for that since they have changed? I thought that if you change the views dimension of the parent it would have been passed down to the children.

Whether this is the right way to go about doing this for a game of this sort is definitely up for discussion but either way I would like to know how it can be done (I presume it can..?). Any help would be much appreciated.

Anthropologist answered 4/5, 2011 at 15:51 Comment(4)
Does leaving the layout_height attributes out of your custom controls in the xml (given you're setting them anyway) make a difference?Cartography
I have seen people doing that on my travels through the forums, so I will check that out and get back to you. I have feeling though that it has something to do with overriding the onLayout() function as I seen mention of it as well.Anthropologist
Sorry for the delay! Nope that didn't do it! However, I did get the desired dimensions being passed down to the child in the end but this led to child not being drawn at all for some reason. Maybe my approach is wrong in what I am trying to do. So I am going to take a step back, read more documentation and maybe come to a better approach to the problem. If I find the solution to what I was trying to do I will post it back here as someone may have a similar problem one day!Anthropologist
I'd certainly like to know how if you find out!Cartography
O
5

Credit to this question:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    // let the super class handle calculations
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    // set again the dimensions, this time calculated as we want
    setMeasuredDimension(getMeasuredWidth(), getMeasuredWidth() / 2);
    // this is required because the children keep the super class calculated dimensions (which will not work with the new MyFrameLayout sizes) 
    final int count = getChildCount();
    for (int i = 0; i < count; i++) {
        final View v = getChildAt(i);
        // this works because you set the dimensions of the ImageView to FILL_PARENT          
        v.measure(MeasureSpec.makeMeasureSpec(getMeasuredWidth(),
                MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(
                getMeasuredHeight(), MeasureSpec.EXACTLY));
    }
}
Ostentation answered 14/12, 2015 at 7:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.