J'ai besoin exactement la même fonction décrite dans cette question. Voici ma solution et le code source: https://github.com/laoyang/android-dynamic-views. Et vous pouvez voir la vidéo de démonstration en action ici: http://www.youtube.com/watch?v=4HeqyG6FDhQ
Mise en page
Fondamentalement, vous aurez deux xml fichiers de mise en page:
- Horizontale LinearLayout "ligne de vue" avec un TextEdit, une Toupie et un ImageButton pour la suppression.
- Une verticale LinearLayout "conteneur view" avec juste un "Add new".
Contrôle
Dans le code Java, vous allez ajouter et de supprimer la ligne vues dans le récipient de façon dynamique, à l'aide de gonfler, addView, removeView, etc. Il y a quelques visibilité de contrôle pour une meilleure UX dans le stock Android app. Vous avez besoin d'ajouter un TextWatcher pour l'EditText vue dans chaque ligne: lorsque le texte est vide vous avez besoin de cacher le "Ajouter un nouveau" bouton et le bouton supprimer. Dans mon code, j'ai écrit un vide inflateEditRow(String) fonction d'aide pour la logique.
D'autres astuces
- Jeu android:animateLayoutChanges="true" dans le xml pour activer l'animation
- Utilisation personnalisée arrière-plan transparent avec "pressé" sélecteur pour activer les boutons visuellement les mêmes que ceux dans le stock Android app.
Le code Source
Le code Java de l'activité principale ( c'est Ce qui explique la logique, mais tout à fait quelques propriétés sont définies dans xml fichiers de mise en page, veuillez vous référer à la source Github pour 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);
}