Cómo agregar elementos a una lista Ver dinámicamente en Android

326

¿Alguien puede explicar o sugerir un tutorial para crear una vista de lista en Android?

Aquí están mis requisitos:

  • Debería poder agregar dinámicamente nuevos elementos presionando un botón.
  • Debería ser lo suficientemente simple de entender (posiblemente sin mejoras de rendimiento o convertview, por ejemplo)

Sé que hay bastantes preguntas sobre este tema, publicadas aquí en StackOverflow, pero no pude encontrar ninguna que respondiera a mi pregunta. ¡Gracias!

usuario555217
fuente
3
La respuesta actualmente más votada de Shardul se considera de alta calidad y los usuarios han expresado que creen que debe ser aceptada. ¿Puedes considerar aceptarlo?
Matt Welke

Respuestas:

583

Cree un diseño XML primero en la res/layout/main.xmlcarpeta de su proyecto :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
    <Button
        android:id="@+id/addBtn"
        android:text="Add New Item"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:onClick="addItems"/>
    <ListView
        android:id="@android:id/list"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:drawSelectorOnTop="false"
    />
</LinearLayout>

Este es un diseño simple con un botón en la parte superior y una vista de lista en la parte inferior. Tenga en cuenta que la ListViewtiene el identificador @android:id/listque define el valor por defecto ListViewuna ListActivitypuede utilizar.

public class ListViewDemo extends ListActivity {
    //LIST OF ARRAY STRINGS WHICH WILL SERVE AS LIST ITEMS
    ArrayList<String> listItems=new ArrayList<String>();

    //DEFINING A STRING ADAPTER WHICH WILL HANDLE THE DATA OF THE LISTVIEW
    ArrayAdapter<String> adapter;

    //RECORDING HOW MANY TIMES THE BUTTON HAS BEEN CLICKED
    int clickCounter=0;

    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.main);
        adapter=new ArrayAdapter<String>(this,
            android.R.layout.simple_list_item_1,
            listItems);
        setListAdapter(adapter);
    }

    //METHOD WHICH WILL HANDLE DYNAMIC INSERTION
    public void addItems(View v) {
        listItems.add("Clicked : "+clickCounter++);
        adapter.notifyDataSetChanged();
    }
}

android.R.layout.simple_list_item_1 es el diseño de elemento de lista predeterminado proporcionado por Android, y puede usar este diseño de stock para cosas no complejas.

listItemses una lista que contiene los datos que se muestran en ListView. Toda la inserción y extracción debe hacerse en listItems; los cambios en listItemsdeberían reflejarse en la vista. Eso es manejado por ArrayAdapter<String> adapter, lo que debe notificarse usando:

adapter.notifyDataSetChanged();

Un adaptador se instancia con 3 parámetros: el contexto, que podría ser su activity/listactivity; el diseño de su elemento de lista individual; y, por último, la lista, que son los datos reales que se mostrarán en la lista.

Shardul
fuente
2
No entiendo cómo ListView se une a nuestra actividad aquí.
Breedly
77
@Breedly porque es una ListActivity y no una actividad que tiene un diseño con ListView . No necesita encontrar la vista de la identificación. Como se puede leer en la referencia: ListActivity is an activity that includes a ListView as its only layout element by default. [...] (it) hosts a ListView object. Entonces, por defecto, los métodos (como setAdapter , etc.) están "dentro" de la Clase.
fllo
Vamos a mostrar felicidad cuando se obtiene la respuesta correcta: /
support_ms
1
Si el elemento en ArrayList es más complicado, como la carga desde Internet y cada elemento contiene video de imagen y algo así, ¿este enfoque enfrentaría un impacto en el rendimiento?
zionpi
1
¿Cómo podría implementar esto en un fragmento?
Oamar Kanji
64

en vez de

listItems.add("New Item");
adapter.notifyDataSetChanged();

puedes llamar directamente

adapter.add("New Item");
venkat530
fuente
@gumuruh, el adaptador en sí es mutable, por lo que podemos agregar o quitar directamente objetos que llamarán a notifyDatasetChanged () y getView () de listView automáticamente. Esto reduce la línea adicional de código.
venkat530
Entonces, al agregar al adaptador, ¿llama automáticamente a notifyDatasetChanged ()? Oh ya veo. Gracias @ venkat530. ¿Pero qué hay de la lista misma? Quiero decir, si digamos en primer lugar, creó una lista de arrays que se utilizaba como contenedor de datos para el adaptador. Y ahora solo agrega un elemento directamente al adaptador en lugar de a la lista de arrays. ¿Los datos de la lista se actualizan / no se tocan?
gumuruh
1
@gumuruh el segundo es la mejor práctica porque está sincronizado.
Ricardo
1
@gumuruh de la experimentación superficial y el código fuente ArrayAdapter [ github.com/android/platform_frameworks_base/blob/master/core/… , parece que el conjunto de datos subyacente también se modificará.
CCJ
Obtuve la respuesta de Shardul, la rompí y no pude encontrar la manera de repararla. Por un capricho, pensé en probar esto, y listo, ¡funciona de nuevo! ¡Muchas gracias! Sin embargo, no tengo idea de cómo o por qué lo solucionó. ¿Alguna idea?
donutguy640
55

Primero, debe agregar un ListView, un EditText y un botón en su activity_main.xml.

Ahora, en su ActivityMain:

private EditText editTxt;
private Button btn;
private ListView list;
private ArrayAdapter<String> adapter;
private ArrayList<String> arrayList;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    editTxt = (EditText) findViewById(R.id.editText);
    btn = (Button) findViewById(R.id.button);
    list = (ListView) findViewById(R.id.listView);
    arrayList = new ArrayList<String>();

    // Adapter: You need three parameters 'the context, id of the layout (it will be where the data is shown),
    // and the array that contains the data
    adapter = new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_spinner_item, arrayList);

    // Here, you set the data in your ListView
    list.setAdapter(adapter);

    btn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            // this line adds the data of your EditText and puts in your array
            arrayList.add(editTxt.getText().toString());
            // next thing you have to do is check if your adapter has changed
            adapter.notifyDataSetChanged();
        }
    });
}

Esto funciona para mí, espero haberte ayudado

Robert
fuente
44
Muy buena explicación y gracias especialmente por explicar el elemento del adaptador, que parece aparecer mágicamente en los ejemplos de todos los demás. :)
raddevus
1
Este es el mejor ejemplo que encontré para esto :)
Dinuka Salwathura
Esta respuesta satisfizo lo que la persona pidió. Simple y limpio sin mejoras complicadas. La respuesta principal en realidad presenta ListActivity, que solo los grandes maestros conocen. Mi único problema ahora es cómo agregar elementos dibujables y otras cosas a las vistas de la lista. Me parece que solo estoy agregando cadenas.
Una optimización podría ser crear un objeto de Lista sin nombre en el Adaptador que crear un puntero de 16 bits a un objeto de lista. Lo cual no es necesario después de crear el adaptador porque el adaptador tiene un método de agregar.
17

Si desea tener ListView en una AppCompatActivity en lugar de ListActivity, puede hacer lo siguiente (Modificar la respuesta de @ Shardul):

public class ListViewDemoActivity extends AppCompatActivity {
    //LIST OF ARRAY STRINGS WHICH WILL SERVE AS LIST ITEMS
    ArrayList<String> listItems=new ArrayList<String>();

    //DEFINING A STRING ADAPTER WHICH WILL HANDLE THE DATA OF THE LISTVIEW
    ArrayAdapter<String> adapter;

    //RECORDING HOW MANY TIMES THE BUTTON HAS BEEN CLICKED
    int clickCounter=0;
    private ListView mListView;

    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.activity_list_view_demo);

        if (mListView == null) {
            mListView = (ListView) findViewById(R.id.listDemo);
        }

        adapter=new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1,
                listItems);
        setListAdapter(adapter);
    }

    //METHOD WHICH WILL HANDLE DYNAMIC INSERTION
    public void addItems(View v) {
        listItems.add("Clicked : "+clickCounter++);
        adapter.notifyDataSetChanged();
    }

    protected ListView getListView() {
        if (mListView == null) {
            mListView = (ListView) findViewById(R.id.listDemo);
        }
        return mListView;
    }

    protected void setListAdapter(ListAdapter adapter) {
        getListView().setAdapter(adapter);
    }

    protected ListAdapter getListAdapter() {
        ListAdapter adapter = getListView().getAdapter();
        if (adapter instanceof HeaderViewListAdapter) {
            return ((HeaderViewListAdapter)adapter).getWrappedAdapter();
        } else {
            return adapter;
        }
    }
}

Y en tu diseño en lugar de usar android:id="@android:id/list"puedes usarandroid:id="@+id/listDemo"

Así que ahora puedes tener un ListViewinterior normal AppCompatActivity.

srinivas
fuente
13

Código para el archivo MainActivity.java.

public class MainActivity extends Activity {

    ListView listview;
    Button Addbutton;
    EditText GetValue;
    String[] ListElements = new String[] {
        "Android",
        "PHP"
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        listview = (ListView) findViewById(R.id.listView1);
        Addbutton = (Button) findViewById(R.id.button1);
        GetValue = (EditText) findViewById(R.id.editText1);

        final List < String > ListElementsArrayList = new ArrayList < String >
            (Arrays.asList(ListElements));


        final ArrayAdapter < String > adapter = new ArrayAdapter < String >
            (MainActivity.this, android.R.layout.simple_list_item_1,
                ListElementsArrayList);

        listview.setAdapter(adapter);

        Addbutton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {

                ListElementsArrayList.add(GetValue.getText().toString());
                adapter.notifyDataSetChanged();
            }
        });
    }
}

Código para el archivo de diseño activity_main.xml.

<RelativeLayout 
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:paddingBottom="@dimen/activity_vertical_margin"
  android:paddingLeft="@dimen/activity_horizontal_margin"
  android:paddingRight="@dimen/activity_horizontal_margin"
  android:paddingTop="@dimen/activity_vertical_margin"
  tools:context="com.listviewaddelementsdynamically_android_examples
    .com.MainActivity" >

  <Button
    android:id="@+id/button1"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_below="@+id/editText1"
    android:layout_centerHorizontal="true"
    android:text="ADD Values to listview" />

  <EditText
    android:id="@+id/editText1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_centerHorizontal="true"
    android:layout_marginTop="26dp"
    android:ems="10"
    android:hint="Add elements listView" />

  <ListView
    android:id="@+id/listView1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_below="@+id/button1"
    android:layout_centerHorizontal="true" >
  </ListView>

</RelativeLayout>

Captura de pantalla

ingrese la descripción de la imagen aquí

Amir Hosseinzadeh
fuente
0

La respuesta corta: cuando crea un ListView, le pasa una referencia a los datos. Ahora, cada vez que se modifiquen estos datos, afectará la vista de lista y, por lo tanto, agregará el elemento, después de que llame a adapter.notifyDataSetChanged () ;.

Si está utilizando un RecyclerView, actualice solo el último elemento (si lo ha agregado al final de la lista de objs) para guardar memoria con: mAdapter.notifyItemInserted (mItems.size () - 1);

Oz Shabat
fuente
0

Esta es la respuesta simple sobre cómo agregar datos dinámicamente en la vista de lista de Android Kotlin

class MainActivity : AppCompatActivity(){

    var listItems = arrayListOf<String>()
    val array = arrayOf("a","b","c","d","e")
    var listView: ListView? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.scrollview_layout)

        listItems.add("a")
        listItems.add("b")
        listItems.add("c")
        listItems.add("d")
        listItems.add("e")

        //if you want to add array items to a list you can try this for each loop
        for(items in array)
            listItems.add(items)
        Log.e("TAG","listItems array: $listItems")

    }
}

Aquí acabo de explicar dos maneras, podemos hacer esto de muchas maneras.

sirajudheen tk
fuente
¿Dónde está la parte que lo agrega a ListView?
Onie Maniego
@OnieManiego aquí agregué los elementos a listview de dos maneras, puede ver eso arriba 1. listItems.add ("a") listItems.add ("b") listItems.add ("c") listItems.add ("d ") listItems.add (" e ") esta es la primera forma en que agregué 2. para (elementos en la matriz) listItems.add (elementos) segunda forma en que agregué todos los elementos de la matriz
sirajudheen tk
@OnieManiego, espero que lo entiendas, si eso es útil para ti, por favor
vota