2014-07-27 3 views
1

배경 : 이전에 this 질문 : 비슷한 주제에 대해 Java 클래스의 인스턴스 변수를 Android 개발의 해당 레이아웃 파일로 전달하는 방법에 대해 질문했습니다. 쉽게 할 수있는 방법이 없으므로 다음은 xml 파일과 클래스가 서로 이야기하게하는 좋은 방법을 찾는 후속 질문입니다.안드로이드 개발에서 클래스와 XML 레이아웃 사이의 통신

질문 : 게임을 개발 중입니다. (자바 스윙의 거의 완성품으로, 지금은 Android 앱으로 바꾸고 있습니다). 그것은 차별적 인 크기의 체스 판과 체스 조각이있는 여러 레벨을 포함합니다 - 모든 의도와 목적을 위해, 그것은 플레이어가 이전 퍼즐을 해결 한 후에 다른 크기의 보드에 새로운 퍼즐을 표시하는 체스 퍼즐 응용 프로그램입니다. 비즈니스 로직은 완전하지만 그래픽 작업을하고 있습니다. 게임 시작시 해당 레이아웃 xml 파일 fragment_board.xml이있는 정적 클래스 BoardFragment (BoardContainer.class에 포함됨)은 보드 크기 (GridLayout)와 첫 번째 레벨에 해당하는 체스 조각을 표시하고 레벨이 완료되면 업데이트됩니다. 설명을 위해, 코드가 다소 다음과 같다 (내 실제 문제를보고 끝으로 건너 뛰기) : 단순하고 공간을 하나의 이미지 만 버튼을 XML 파일에 현재이지만, 앱 것을

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

참고 : 실제로 숫자는 해당 클래스의 "level"인스턴스 변수에 따라 달라야합니다 (따라서 level==5 일 경우 app:columnCount==6 등). 그러나 나는 어떻게 그것을 commmunicate 할 것인지 확신하지 못합니다. 클래스 파일에서 XML로. 전혀 가능합니까? 사실, 레벨이 완료되면 보드 크기와 조각 수 모두가 변경되어야합니다. 이 작업을 수행해야합니까

  • 각 레벨마다 하나의 XML 프래그먼트 파일이 있습니까? 그런 다음 이전 질문은 해결되지만 많은 수준에서 많은 조각 파일로 이어질 것입니다.

  • 레벨이 완료되면서 하나의 조각 xml 파일이 업데이트됩니까?

감사합니다.

답변

2

, 런타임에 동적으로 보드의 레이아웃을 생성해야합니다 예를 들면 다음과 같습니다. 그러나 XML 레이아웃 리소스에서 자신의 속성 인 View과 그 속성을 정의 할 수 있으므로 레이아웃에서 필수적이지 않은 부분을 코드에서 분리하고 구성 별 레이아웃을 자동으로 해결할 수 있습니다.예를 들어

는, 레이아웃은 보드와 셀 레이아웃에 대해 별도의 레이아웃 리소스에 적용 할 수있다 :

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" /> 

다음은 보드를 만들기 위해 동적으로 팽창 될 수 있습니다.


@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해야합니다. 두 가지 방법으로이 문제를 접근 할 수
  1. Fragment 특정 보드를 대표하여 각 인스턴스를 확인합니다. 이렇게하면 Fragment 로직이 매우 단순 해지고 단 한 게임 레벨에만 집중할 수 있습니다. 새 레벨을 시작하는 논리는 Fragment을 새 인스턴스로 바꾸면 Activity에 의해 처리됩니다. 또한 FragmentTransaction에는 애니메이션에 대한 고유 한 지원이 있으므로 새로운 레벨을 시작하기위한 애니메이션을 매우 쉽게 구현할 수 있다는 이점이 있습니다.

  2. Fragment은 모든 것을 처리해야합니다. 요청시 새 보드 레이아웃을 부 풀리고 onCreateView() 콜백에서 위임 한 다음, 현재 Fragment 레이아웃을 부모 레이어에서 제거하고 새 레이아웃으로 대체하는 메소드를 구현하는 일반 메소드를 생성하여이를 달성 할 수 있습니다 보드 팽창 방법으로. 레이아웃 루트는 getView() 메소드에서 가져올 수 있습니다 (또는 Fragment 레이아웃이 Activity으로 저장되지 않도록 레이아웃을 래핑하므로 라이브러리가 첫 번째 자식 인 지원 라이브러리의 경우).

+0

고마워, 이건 최고 품질의 대답이다. 나는 이클립스에서 ("android.support.v7.widget.GridLayout"을 가진 영원한 문제들) 오랫동안 실행시키지 못했고, 지금은 나를 넘어서서 새로운 .xml 파일들을 찾을 수 없다. Android Studio로 전환하면서 모든 것을 설치하고 실행하는 즉시이 방법을 시도해 보겠습니다. – Sid

+0

"cell"변수가 정의되지 않았습니다. "cellView"를 의미합니까? 그럼에도 불구하고 왜 null 포인터 예외가 발생하는지, 확실하지는 않습니다. – Sid

+0

@Sid : 예, "cellView"를 의미했습니다. 원래는 "셀"이라고 이름을 정했고 이름을 바꿀 때 참조를 업데이트하는 것을 잊었습니다 (게시 입력 상자에 코드를 직접 작성했습니다). 나는 그것을 바로 잡았다. _that_ 라인에서'NullPointerException'을 얻는다면,'boardLayout'이 null이라는 것을 의미합니다. 그리드 레이아웃 리소스에 "gridView"라는 id를 가진'View'가 없다는 것을 의미합니다. – corsair992

1
당신은 항상 아니라 귀하의 의견은 XML 파일 예를 들어

의 사용을 통해 자연에서 정적 일 필요없이 동적으로 수준에 따라 코드에 뷰를 만들 수

...

//the layout you will work with 
GridLayout layout = (GridLayout) findViewById(R.id.gridLayout); 

//properties for button 
Button btn = new Button(this); 
btn.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); //this will depend how you want the view to look 
btn.setText("My button created programmatically"); 
btn.setId(someId); 

//add button to the layout 
layout.addView(btn); 

if(level == whateverlevel){ //pseudo code here obviously 
    //make a new button/buttons in here like above and add it to your view depending on your level 
} 
+0

다른 화면 크기로도 작업 할 수 있습니까? 이 코드 스 니펫이 BoardFragment의 onCreateView 메소드에 있어야하나요? – Sid

+0

@Sid, 그렇습니다. 그래도 적절한 레이아웃 "params"를 설정하여 다양한 화면 크기에서 작동하는 뷰를 프로그래밍 방식으로 만들 수 있습니다. 또한 ... 예,이 코드는 onCreateView에 포함됩니다. "createBoard (int level)"도우미 메소드를 작성하는 것이 좋습니다 ... onCreateView에서이 도우미를 호출하고 레벨 번호를 전달하십시오. –

+0

그레이트는 가장 도움이되었습니다. 이 글을 읽는 다른 누군가를 위해, 나는이 가이드가 시작하는 것이 좋다라고 생각한다 : http://www.techotopia.com/index.php/Creating_an_Android_User_Interface_in_Java_Code. 다양한 화면 크기에 대해 다른 레이아웃 매개 변수를 설정하는 방법은 프로그래밍 방식으로 화면 크기를 어떻게 알 수 있습니까? "isScreenSizeLarge()"와 같은 if 문에 넣을 수있는 메서드가 있습니까? (XML 파일의 경우, "large"또는 "xlarge"와 같은 다른 폴더를 가질 수 있으며 모바일은 화면 크기에 따라 올바른 폴더를 선택합니다). – Sid

1

레이아웃을 동적으로 처리하는 좋은 방법은 프로그래밍 방식으로 레이아웃을 생성하는 것입니다. XML 파일에 모든 것을 배치하는 것만 큼 쉽지는 않지만 유연성을 제공합니다.

다른 답변에서 언급 한 바와 같이

How to create a RelativeLayout programmatically with two buttons one on top of the other?

+0

감사합니다. 지금은 이것에 대해 읽고 있습니다 (복잡합니다!). 한 가지 질문 : xml을 사용할 때 Android를 사용하면 각 화면 크기에 대해 여러 레이아웃을 생성 할 수 있습니다. 당신의 방법으로 그것을 할 수있는 좋은 방법이 있습니까? – Sid

관련 문제