Android:调整自定义视图的大小。父级已调整大小,但宽度/高度更改未传递到子视图

发布于 2024-11-05 05:41:06 字数 2962 浏览 0 评论 0原文

我目前正在尝试使用 Android 制作一款基于老式战舰棋盘游戏的游戏。我现在只是在闲逛,试图了解它以及我制作游戏可能需要的组件。

基本上我目前在布局 xml 文件中的内容如下:

<?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>

我希望 BoardView 仅占据屏幕的特定部分,即视图应该是我想要在此视图中创建的内容的大小。在本例中是 2D 板。这是通过覆盖扩展 View 的 onMeasure() 方法来完成的。视图的宽度保持相同,但高度的值与宽度相同,从而形成完美的正方形。

@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());
}

我通过重写视图 onSizeChanged() 函数并检查其中的值来检查视图尺寸是否已更改。

@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);

}

从布局文件中可以看出,我有一个relativelayout视图组,其中包含另一个名为ShipView的自定义视图作为子视图。理想情况下,我想要发生的是,当我去测量它的尺寸时,它的尺寸被限制在 onMeasure 中设置的范围内。我以类似的方式通过其 onMeasure() 方法检查 ShipView 的尺寸。

@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);
}

日志文件向我显示以下内容( onMeasure() 方法似乎被多次调用,但所有值都相同,因此我不会费心显示多个日志,因为值都相同):

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

似乎当我得到通过 ShipViews onMeasure() 的尺寸没有任何改变,并且忽略我设置的尺寸限制。我不确定这是否与ShipView的RelativeLayout有关。由于布局参​​数已更改,我是否必须为此设置布局参数?我认为如果您更改父级的视图维度,它将传递给子级。

对于此类游戏来说,这是否是正确的方法绝对有待讨论,但无论哪种方式,我都想知道如何做到这一点(我认为可以..?)。任何帮助将不胜感激。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

等风来 2024-11-12 05:41:06

归功于这个问题

@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));
    }
}

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));
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文