J'ai besoin de la même fonctionnalité que celle décrite dans cette question. Voici ma solution et mon code source: https://github.com/laoyang/android-dynamic-views . Et vous pouvez voir la démo vidéo en action ici: http://www.youtube.com/watch?v=4HeqyG6FDhQ
Disposition
Fondamentalement, vous aurez deux fichiers de mise en page xml:
- Une vue de ligne LinearLayout horizontale avec un
TextEdit
, un Spinner
et un ImageButton
pour la suppression.
- Une vue de conteneur LinearLayout verticale avec juste un bouton Ajouter un nouveau .
Contrôle
Dans le code Java, vous allez ajouter et supprimer des vues de ligne dans le conteneur de manière dynamique, en utilisant inflate, addView, removeView, etc. Il existe un contrôle de visibilité pour une meilleure UX dans l'application Android stock. Vous devez ajouter un TextWatcher pour la vue EditText dans chaque ligne: lorsque le texte est vide, vous devez masquer le bouton Ajouter un nouveau et le bouton Supprimer. Dans mon code, j'ai écrit une void inflateEditRow(String)
fonction d'assistance pour toute la logique.
Autres astuces
- Définir
android:animateLayoutChanges="true"
en XML pour activer l'animation
- Utilisez un arrière-plan transparent personnalisé avec le sélecteur enfoncé pour rendre les boutons visuellement identiques à ceux de l'application Android standard.
Code source
Le code Java de l'activité principale (cela explique toute la logique, mais de nombreuses propriétés sont définies dans des fichiers de mise en page xml, veuillez vous référer à la source Github pour une solution complète):
public class MainActivity extends Activity {
// Parent view for all rows and the add button.
private LinearLayout mContainerView;
// The "Add new" button
private Button mAddButton;
// There always should be only one empty row, other empty rows will
// be removed.
private View mExclusiveEmptyView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.row_container);
mContainerView = (LinearLayout) findViewById(R.id.parentView);
mAddButton = (Button) findViewById(R.id.btnAddNewItem);
// Add some examples
inflateEditRow("Xiaochao");
inflateEditRow("Yang");
}
// onClick handler for the "Add new" button;
public void onAddNewClicked(View v) {
// Inflate a new row and hide the button self.
inflateEditRow(null);
v.setVisibility(View.GONE);
}
// onClick handler for the "X" button of each row
public void onDeleteClicked(View v) {
// remove the row by calling the getParent on button
mContainerView.removeView((View) v.getParent());
}
// Helper for inflating a row
private void inflateEditRow(String name) {
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View rowView = inflater.inflate(R.layout.row, null);
final ImageButton deleteButton = (ImageButton) rowView
.findViewById(R.id.buttonDelete);
final EditText editText = (EditText) rowView
.findViewById(R.id.editText);
if (name != null && !name.isEmpty()) {
editText.setText(name);
} else {
mExclusiveEmptyView = rowView;
deleteButton.setVisibility(View.INVISIBLE);
}
// A TextWatcher to control the visibility of the "Add new" button and
// handle the exclusive empty view.
editText.addTextChangedListener(new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
// Some visibility logic control here:
if (s.toString().isEmpty()) {
mAddButton.setVisibility(View.GONE);
deleteButton.setVisibility(View.INVISIBLE);
if (mExclusiveEmptyView != null
&& mExclusiveEmptyView != rowView) {
mContainerView.removeView(mExclusiveEmptyView);
}
mExclusiveEmptyView = rowView;
} else {
if (mExclusiveEmptyView == rowView) {
mExclusiveEmptyView = null;
}
mAddButton.setVisibility(View.VISIBLE);
deleteButton.setVisibility(View.VISIBLE);
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
}
});
// Inflate at the end of all rows but before the "Add new" button
mContainerView.addView(rowView, mContainerView.getChildCount() - 1);
}