Как установить макет динамически в 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
}
}