Как установить макет динамически в android

Ну, предположим, что есть действие под названием MainActivity, и есть два макета, называемых layout1 и layout2, у которых есть несколько кнопок. По умолчанию макет MainActivity layout1 выглядит следующим образом:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.layout1);

Теперь, что я на самом деле сделал, нажав кнопку в layout1, второй макет устанавливается следующим образом:

    someBtn1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            setContentView(R.layout.layout2);
        }
    });

Есть еще одна кнопка в layout2, чтобы вернуться к layout1, как показано ниже:

    someBtn2.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            setContentView(R.layout.layout1);
        }
    });

Проблема в том, что когда я вернулся к layout1, тогда OnClickListener из someBtn1 не работает. Кажется, мне нужно снова установить OnClickListener для someBtn1 из layout1. Как я могу написать код, чтобы они отлично работали с лучшими практиками?

Ответ 1

Лучше всего использовать использование фрагментов вместо изменения вида содержимого.

В вашем коде setContentView с макетами каждый раз воссоздают (раздувать) все ваши представления, поэтому вызов setContentView (R.layout.layout1) в прослушивателе кликов someBtn2 создаст новую кнопку без связанного с ней прослушивателя.

Если вы не хотите использовать фрагменты, вы можете сделать это:

private View view1, view2;

public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  view1 = getLayoutInflater().inflate(R.layout.layout1, null);
  view2 = getLayoutInflater().inflate(R.layout.layout2, null);
  setContentView(view1);

Слушатели будут:

someBtn1.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        setContentView(view2);
    }
});


someBtn2.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        setContentView(view1);
    }
});

Ответ 2

Если вы просто хотите поиграть с вашим текущим кодом, решение вашей проблемы заключается в том, что слушатели должны быть переоформлены при изменении макета следующим образом:

someBtn1.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        setContentView(R.layout.layout2);

        someBtn2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                setContentView(R.layout.layout1);
            }
        });
    }
});

someBtn2.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        setContentView(R.layout.layout1);

        someBtn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                setContentView(R.layout.layout2);
            }
        });
    }
});

Альтернативой тому, чтобы избежать объявления двух слушателей, является объявление двух методов для обработки изменений макета и использование свойства onClick кнопки в каждом из макетов, например:

public void setLayout1(View view) {
    setContentView(R.layout.layout1);
}

public void setLayout2(View view) {
    setContentView(R.layout.layout2);
}

В layout1.xml:

<Button
    android:id="@+id/someBtn1"
    android:onClick="setLayout2"/>

В layout2.xml:

<Button
    android:id="@+id/someBtn2"
    android:onClick="setLayout1"/>

Однако, если вы хотите следовать лучшим практикам, наилучшей практикой является не смешивать макеты в одной и той же деятельности, а вместо этого объявлять два разных вида деятельности (каждый со своим макетом) и вызывать одно действие или другое в зависимости от которая была нажата. Предположим, что вы находитесь в Activity1 и хотите вызвать Activity2, затем вернитесь к Activity1:

В Activity1.java:

someBtn1.setOnClickListener(new View.OnClickListener() {
     @Override
     public void onClick(View view) {
         startActivity(new Intent(this, Activity2.class));
     }
 });

В Activity2.java:

someBtn2.setOnClickListener(new View.OnClickListener() {
     @Override
     public void onClick(View view) {
         finish();
     }
 });

Ответ 3

Один из способов сделать это - загрузить оба представления в onCreate(...), а затем переключиться между ними, сделав тот, который вы не хотите невидимым. Что-то вроде следующего:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    LayoutParams default_layout_params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
    View view1 = inflater.inflate(R.layout.layout1, null);
    addContentView(view1, default_layout_params);           
    View view2 = inflater.inflate(R.layout.layout2, null);
    addContentView(view2, default_layout_params);
    view2.setVisibility(View.INVISIBLE);
    view1.setVisibility(View.VISIBLE);
    view1.bringToFront();

Ответ 4

В момент компоновки обратного вызова1 данные должны быть снова установлены.

Вы можете объединить оба макета в один, а затем использовать ViewFlipper для переключения между ними.

Ответ 5

Когда вы устанавливаете layout2, вы также должны настроить OnClickListener на someBtn1 и наоборот, я бы предложил что-то вроде этого. Но, как и в предыдущем ответе, в общем вы должны избегать смешивания макетов таким образом.

public class MainActivity extends Activity {

    private final View.OnClickListener setLayout1Listener = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
           setContentView(R.layout.layout2);
           ((Button)findViewById(R.id.Btn2Id)).setOnClickListener(setLayout2Listener);
           //do other stuff
        }
    };

    private final View.OnClickListener setLayout2Listener = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
           setContentView(R.layout.layout1);
           ((Button)findViewById(R.id.Btn1Id)).setOnClickListener(setLayout1Listener);
           //do other stuff
        }
    };



    @Override
    public void onCreate(final Bundle savedInstance) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout1);
        ((Button)findViewById(R.id.Btn1Id)).setOnClickListener(setLayout1Listener);
        //do other stuff
    }
}