在Android开发,阶级和XML布局之间的通信阶级、布局、通信、Android

2023-09-07 22:07:30 作者:后来会好吗哦

背景:我有previously问this问题关于如何从一个Java类通过一个实例变量给它相应的布局文件中Android开发类似的话题。事实证明,有没有简单的方法来做到这一点,所以下面是一个后续的问题找到让XML文件和类相互交谈的好办法。

Background: I have previously asked this question on the similar topic on how to pass an instance variable from a Java class to it corresponding layout file in Android development. It turns out there is no easy way to do this, so the following is a follow-up question finding a good way to let the xml file and the class talk to each other.

问题:我开发一个游戏(接近完成的Java Swing,现在把它变成一个Android应用程序)。它包含多个层次,每一个differenly大小的国际象棋棋盘和棋子 - 对所有意图和目的,它是一个国际象棋之谜的应用程序,在不同尺寸的电路板会显示一个新的难题后,玩家已经解决了previous拼图。业务逻辑是完整的,但我工作的图形。在比赛开始时,静态类 BoardFragment 及其相应的布局的XML文件(BoardContainer.class含) fragment_board.xml 应显示板尺寸(如GridLayout的),并对应于第一级,然后更新为级别完成棋子。为了澄清,code看起来有点像这样(跳到结尾看到我的实际问题):

Question: I am developing an game (nearly complete in Java Swing, now turning it into an Android app). It contains multiple levels, each with a differenly sized chess board and chess pieces - for all intents and purposes, it is a chess puzzle app that displays a new puzzle on a differently sized board after the player has solved the previous puzzle. The business logic is complete but I'm working on the graphics. At the game start, a static class BoardFragment (contained by BoardContainer.class) with its corresponding layout xml file fragment_board.xml should display the board size (as GridLayout) and chess pieces corresponding to the first level, which then updates as the level is completed. For clarification, the code looks somewhat like this (skip to the end to see my actual problem):

//Here is BoardFragment.class, static class contained by BoardContainer:

public static class BoardFragment extends Fragment {

     public BoardFragment() {
     }

     public int level=0;

     public void buttonPressed(View view) {
     //method that will advance the game and update "level" 
     //depending on which button was clicked
     }


         @Override
         public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.fragment_board,
                container, false);
         return rootView;
         }
     }

//This is fragment_board.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.exampletest.MainGame$BoardFragment" >

    <android.support.v7.widget.GridLayout
        xmlns:app="schemas.android.com/apk/res-auto"
        android:id="@+id/gridView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" 
        app:columnCount="4" >

        <ImageButton
            android:id="@+id/imageButton1"
            android:layout_width="49dp"
            android:layout_height="49dp"
            android:contentDescription="@null"
            android:onClick="buttonPressed"
            android:src="@drawable/grid11" />

        </android.support.v7.widget.GridLayout>

</RelativeLayout>

请注意,为了简便起见和空间中,只有一个图像按钮是当前在XML文件,但随着应用:列数等于4,就不会有16.事实上,数目应取决于在级别的实例变量对应的类(因此,如果水平== 5 那么也许应用程序:列数== 6 等等),但我敢不知道我怎么会commmunicate从类文件的XML。是否有可能呢?事实上,当水平完成后,无论是电路板尺寸和件数应改变。如果这被完成

Note that for simplicity and space, only one image button is currently in the xml file, but with app:columnCount equaling 4, there would be 16. In fact, the number should depend on the "level" instance variable in the corresponding class (so that if level==5 then perhaps app:columnCount==6 and so forth) but I'm not sure how I would commmunicate that from the class file to the xml. Is it possible at all? In fact, when the level is completed, both the board size and number of pieces should change. Should this be done by

拥有的XML片段文件为每个级别?那么previous的问题是解决了,但是对于很多层次,这将导致许多片段文件? - 是最好的做法

Having one xml fragment file for each level? Then the previous question is solved, but for many levels, it would lead to many fragment files - is that best practice?

有了这样的更新,水平完成一个片段xml文件?

Having one fragment xml file that updates as the level is completed?

我AP preciate任何帮助。

I appreciate any help.

推荐答案

正如在其他的答案,你需要在运行时动态地创建您的电路板布局。但是,您仍然可以定义自己的查看和它们在XML布局资源的属性,从而保持它们提供了$分离布局的非必要部分的优点C $ c和允许的特定配置的布局自动解决。

As mentioned in the other answers, you will need to create the layout for your board dynamically at runtime. However, you can still define your individual Views and their attributes in XML layout resources, thus retaining the advantages they provide of separating the non-essential parts of the layout from the code and allowing automatic resolution of configuration-specific layouts.

例如,您的布局可以适用于不同的布局资源,电路板和元件布局:

For example, your layout could be adapted to separate layout resources for the board and cell layouts:

fragment_board_grid.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.exampletest.MainGame$BoardFragment" >

    <android.support.v7.widget.GridLayout
        android:id="@+id/gridView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</RelativeLayout>

fragment_board_cell.xml

<ImageButton xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="49dp"
    android:layout_height="49dp"
    android:contentDescription="@null"
    android:onClick="buttonPressed"
    android:src="@drawable/grid11"
    tools:context="com.example.exampletest.MainGame$BoardFragment" />

这些现在可以动态地膨胀创造了板:

These can now be dynamically inflated to create a board:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_board_grid,
            container, false);
    GridLayout boardLayout = (GridLayout) rootView.findViewById(
            R.id.gridView);
    boardLayout.setColumnCount(columnsNum);
    boardLayout.setRowCount(rowsNum);
    for (int columnIndex = 0; columnIndex < columnsNum; columnIndex++) {
        for (int rowIndex = 0; rowIndex < rowsNum; rowIndex++) {
            ImageView cellView = (ImageView) inflater.inflate(
                    R.layout.fragment_board_cell, boardLayout, false);
            // Here you can customize it, add listeners, etc.
            boardLayout.addView(cellView);
        }
    }
    return rootView;
}

在启动一个新的水平,你将需要从头开始reinflate电路板布局。您可以通过两种方式接近这一点:

Upon starting the next level you will need to reinflate the board layout from scratch. You can approach this in two ways:

让你的片段重present特定板的每个实例。这将使片段的逻辑非常简单,只专注于一场比赛的水平。启动一个新的水平的逻辑将处理由它的活动,用一个新的实例替换现有的片段。这也将有可能使动画开始一个新的水平非常容易实现,因为 FragmentTransaction 取值对动画的内在支持的优势。 Android的布局技巧 3 通过合并优化

Make each instance of your Fragment represent a particular board. This would make the Fragment logic extremely simple and focused on only one game level. The logic for starting a new level would be handled by it's Activity, by replacing the existing Fragment with a new instance. This would also have the advantage of making animations for starting a new level extremely easy to implement, as FragmentTransactions have inherent support for animations.

片段搞定一切。这可能是由于创建将抬高对需求产生新的电路板布局的通用方法来实现并委托其从 onCreateView()回调,然后建立一个能删除当前的片段布局从它的一个方法家长和它与该板充气方法生成一个新的布局取代。布局root可以从 getView()方法得到(或者在支持库中它的第一个孩子,作为库包装了最初的片段,以便从被保存在活动阻止查看状态布局)。

Have the Fragment handle everything. This could be achieved by creating a generic method that would inflate a new board layout on demand and delegate to it from the onCreateView() callback, then implementing a method that would remove the current Fragment layout from it's parent and replace it with a fresh layout generated by the board-inflating method. The layout root can be gotten from the getView() method (or in case of the support library it's first child, as the library wraps the initial Fragment layout in order to block the View state from being saved by the Activity).