-1

다음과 같은 버튼을 3x4 격자로 표시하고 사용자가 메뉴 항목을 클릭하여 격자 크기를 변경할 수있는 응용 프로그램을 작성했습니다. 문제는 "deleteSomething"함수로 이상하게 발생한다는 것입니다. 이 특정 부분에 대한 이상한 것이 있습니다앱이 removeView에서 다운 됨

package com.example.myapplication; 

import android.os.Bundle; 
import android.support.v7.app.AppCompatActivity; 
import android.view.Gravity; 
import android.view.Menu; 
import android.view.MenuItem; 
import android.widget.Button; 
import android.widget.LinearLayout; 

public class MainActivity extends AppCompatActivity { 

    LinearLayout.LayoutParams params; 
    LinearLayout linearLayout; 
    int _row; 
    int column; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     linearLayout = new LinearLayout(this); 
     linearLayout.setOrientation(LinearLayout.VERTICAL); //Can also be done in xml by android:orientation="vertical" 
     params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.FILL_PARENT); 
     params.weight = 1.0f; 
     params.gravity = Gravity.TOP; 
     //layout.setBackgroundColor(0xFFFFFFFF); 
     _row=3; 
     column=4; 
     update(); 

    } 


    public void update(){ 
     for (int i = 0; i < _row; i++) { 
      LinearLayout row = new LinearLayout(this); 
      row.setLayoutParams(params); 

      for (int j = 0; j < column; j++) { 
       Button btnTag = new Button(this); 
       btnTag.setLayoutParams(params); 
       btnTag.setText("Button " + (j + 1 + (i * column))); 
       btnTag.setId(j + 1 + (i * column)); 
       if ((i+j) % 2 == 0) { 
        btnTag.setBackgroundColor(0xFFFF0000); 
       } else { 
        btnTag.setBackgroundColor(0x00000000); 
       } 

       row.addView(btnTag); 
      } 
      linearLayout.addView(row); 
     } 

     setContentView(linearLayout); 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     menu.add(Menu.NONE, 1, Menu.NONE, "Item name"); 
     menu.add(Menu.NONE, 2, Menu.NONE, "Item name"); 
     return true; 
    } 

    public void deleteSomething(){ 

     ((LinearLayout) linearLayout.getChildAt(1)).removeViewAt(0); 
     ((LinearLayout) linearLayout.getChildAt(1)).removeViewAt(1); 
     ((LinearLayout) linearLayout.getChildAt(1)).removeViewAt(2); 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 

     switch (item.getItemId()) { 
      case MENU_ITEM_ITEM1: 
       deleteSomething(); 
       //linearLayout.removeAllViews(); 
       //_row=4; 
       //column=5; 
       //update(); 
       return true; 
      case 2: 
       deleteSomething(); 
       //linearLayout.removeAllViews(); 
       _row=6; 
       column=3; 
       update(); 
      default: 
       return false; 
     } 


    } 
} 

: 아래의 전체 코드입니다

public void deleteSomething(){ 

      ((LinearLayout) linearLayout.getChildAt(1)).removeViewAt(0); 
      ((LinearLayout) linearLayout.getChildAt(1)).removeViewAt(1); 
      ((LinearLayout) linearLayout.getChildAt(1)).removeViewAt(2); 
     } 

주석으로 처음 두 행은 두 번째 행의 세 번째 버튼은 문제없이 삭제 얻을은; 두 번째 버튼을 주석 처리하면 두 번째 버튼의 첫 번째 두 버튼이 문제없이 삭제됩니다. 그러나 세 줄을 모두 포함하면 드롭 다운 메뉴에서 첫 번째 항목을 클릭하면 응용 프로그램이 즉시 중단됩니다.

이유를 아는 사람이 있습니까?

답변

0

먼저, 나는 dharms '설명을 인정하고 싶습니다. 그/그녀의 응답없이, 나는이 해결책을 생각해 낼 수 없을 것입니다. 그/그녀의 설명이 도움이되지만, 그/그녀의 제안 된 솔루션이 올바르지 않습니다.이

public void deleteSomething(){ 

    ((LinearLayout) linearLayout.getChildAt(1)).removeViewAt(0); 
    ((LinearLayout) linearLayout.getChildAt(1)).removeViewAt(1); 
    ((LinearLayout) linearLayout.getChildAt(1)).removeViewAt(2); 
} 

에 변경 :

public void deleteSomething(){ 
    for (int i = _row-1; i >= 0; i--) { 
     for (int j = column - 1; j >= 0; j--) { 
      ((LinearLayout) linearLayout.getChildAt(i)).removeViewAt(j); 
     } 
    } 
} 

기본적인 아이디어는 우리가 삭제할 때 ID를 변경하지 않는다는 것입니다, 따라서 우리는이 난 다음에 올바른 솔루션을 게시합니다 그들의 ID를 역 참조 할 수 있습니다.

0

문제점

귀하의 문제는 인덱스에 의해 뷰를 참조하고있다. 보기를 제거 할 때마다 하위 수가 줄어 듭니다.

있는 LinearLayout 3 아이들과 함께 시작 : : 이제 당신의 예를 살펴 보자
[A, B는 C]

먼저 전화를
((LinearLayout) linearLayout.getChildAt(1)).removeViewAt(0);

이제있는 LinearLayout은 두 자녀가 있습니다
를 [ B, C]

다음 호출을 실행
((LinearLayout) linearLayout.getChildAt(1)).removeViewAt(1);

,

이제있는 LinearLayout 아이가 1 명 있습니다 [B]


은 인덱스 2 자녀 (현재 크기 1)의 범위 밖에 있기 때문에이 예외가 발생 다음 호출을
(LinearLayout) linearLayout.getChildAt(1)).removeViewAt(2);

을 실행합니다.



먼저 제거하려는 뷰에

잡아 참조 솔루션. 그런 다음 removeView(View view)을 사용하여 LayoutGroup에서 모두 제거하십시오. 다음은 데모 용으로 그렇게 할 수있는 방법의 간단한 예입니다 : 모든

LinearLayout layout = (LinearLayout) linearLayout.getChildAt(1); 
View a = layout.getChildAt(0); 
View b = layout.getChildAt(1); 
View c = layout.getChildAt(2); 
layout.removeView(a); 
layout.removeView(b); 
layout.removeView(c); 
+0

행을 삭제하려고하지 않습니다. 나는 acutally 행 내에서 단추를 삭제하려고 해요. –

+0

최선의 방법은 해당 ID를 뒤로 참조하는 것입니다. –

+0

이것은 간단한 예입니다. 순차적으로 자식 뷰 세트를 삭제하고 있다면,'removeViews (int start, int count)'라는 더 좋은 선택이 될 수있는 추가적인 메소드가있다. 특정 순서가 아닐 수있는 뷰를 제거하려는 경우이 예제를 다룹니다. – dharms