Como adicionar elementos a uma listaVer dinamicamente no Android

326

Alguém pode explicar ou sugerir um tutorial para criar um listView no android?

Aqui estão os meus requisitos:

  • Eu deveria poder adicionar novos elementos dinamicamente pressionando um botão.
  • Deve ser simples o suficiente para entender (possivelmente sem nenhuma melhoria de desempenho ou vista de conversão, por exemplo)

Eu sei que existem algumas perguntas sobre esse tópico, postadas aqui no StackOverflow, mas não consegui encontrar nenhuma que respondesse à minha pergunta. Obrigado!

user555217
fonte
3
A resposta atualmente mais votada por Shardul é considerada de alta qualidade e os usuários expressaram que acham que ela deve ser aceita. Você pode aceitar?
Matt Welke

Respostas:

583

Crie um layout XML primeiro na res/layout/main.xmlpasta do seu projeto :

<?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 é um layout simples, com um botão na parte superior e uma exibição de lista na parte inferior. Observe que o ListViewtem o ID @android:id/listque define o padrão que ListViewum ListActivitypode usar.

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 é o layout de item de lista padrão fornecido pelo Android e você pode usar esse layout de estoque para coisas não complexas.

listItemsé uma lista que contém os dados mostrados no ListView. Toda a inserção e remoção deve ser feita listItems; as alterações listItemsdevem ser refletidas na exibição. Isso é tratado por ArrayAdapter<String> adapter, que deve ser notificado usando:

adapter.notifyDataSetChanged();

Um adaptador é instanciado com 3 parâmetros: o contexto, que poderia ser seu activity/listactivity; o layout do seu item de lista individual; e, finalmente, a lista, que são os dados reais a serem exibidos na lista.

Shardul
fonte
2
Não entendo como o ListView se anexa à nossa atividade aqui.
Breedly
7
@ Breedly Porque é uma ListActivity e não uma Atividade que possui um layout com um ListView . Você não precisa encontrar a visualização do ID. Como você pode ler sobre a referência: ListActivity is an activity that includes a ListView as its only layout element by default. [...] (it) hosts a ListView object. Portanto, por padrão, os métodos (como setAdapter , etc) estão "dentro" da Classe.
fllo
Vamos mostrar felicidade quando a resposta certa é obtida: /
support_ms
1
Se o elemento ArrayList for mais complicado, como carregar da Internet e cada item contiver vídeo de imagem e algo assim, essa abordagem enfrentaria um impacto no desempenho?
Zionpi 18/02/16
1
Como eu poderia implementar isso em um fragmento?
Oamar Kanji
64

ao invés de

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

você pode ligar diretamente

adapter.add("New Item");
venkat530
fonte
@gumuruh o próprio adaptador é mutável, para que possamos adicionar ou remover diretamente objetos que chamarão o notifyDatasetChanged () e getView () do listView automaticamente. Isso reduz a linha extra de código.
venkat530
adicionando ao adaptador automaticamente, ligue notifyDatasetChanged ()? Ah eu vejo. Obrigado @ venkat530. Mas e a lista em si? Quero dizer, se, digamos, em primeiro lugar, ele criou uma lista de matriz usada como um contêiner de dados para o adaptador. E agora você acabou de adicionar um item diretamente ao adaptador e não à lista de matrizes. Os dados da lista de matrizes são atualizados / intocados?
Gmuruh
1
@gumuruh a segunda é a melhor prática porque é sincronizada.
Ricardo
1
@gumuruh da experimentação superficial e o código-fonte ArrayAdapter [ github.com/android/platform_frameworks_base/blob/master/core/… , parece que o conjunto de dados subjacente também será modificado.
CCJ
Consegui que a resposta de Shardul funcionasse, depois a quebrei e não consegui descobrir como consertá-la. Por um capricho, pensei em experimentar isso e pronto, funciona de novo! Muito obrigado! No entanto, não tenho idéia de como ou por que isso foi corrigido. Qualquer ideia?
precisa saber é o seguinte
55

Primeiro, você precisa adicionar um ListView, um EditText e um botão no seu activity_main.xml.

Agora, no seu 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();
        }
    });
}

Isso funciona para mim, espero ter ajudado você

Robert
fonte
4
Muito boa explicação e obrigado especialmente por explicar o item do adaptador - que parece aparecer magicamente nos exemplos de todos os outros. :)
raddevus
1
Este é o melhor exemplo que eu encontrei para este :)
Dinuka Salwathura
Esta resposta satisfez o que a pessoa pediu. Simples e limpo, sem melhorias complicadas. A resposta principal apresenta o ListActivity, que apenas os grandes mestres conhecem. Meu único problema agora é como adicionar itens de desenho e outras coisas às visualizações da lista. Parece-me que estou apenas adicionando strings.
Uma otimização pode ser criar um objeto de lista sem nome no adaptador e criar um ponteiro de 16 bits para um objeto de lista. O que não é necessário após a criação do adaptador, porque o adaptador possui um método add.
17

Se você deseja ter o ListView em um AppCompatActivity em vez de ListActivity, faça o seguinte (Modificando a resposta 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;
        }
    }
}

E no seu layout, em vez de usar, android:id="@android:id/list"você pode usarandroid:id="@+id/listDemo"

Então agora você pode ter um ListViewinterior normal AppCompatActivity.

srinivas
fonte
13

Código para o arquivo 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 o arquivo de layout 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>

ScreenShot

insira a descrição da imagem aqui

Amir Hosseinzadeh
fonte
0

A resposta curta: quando você cria um ListView, passa uma referência aos dados. Agora, sempre que esses dados forem alterados, eles afetarão a exibição da lista e, portanto, adicionarão o item a ele, depois que você ligar para adapter.notifyDataSetChanged () ;.

Se você estiver usando um RecyclerView, atualize apenas o último elemento (se você o adicionou no final da lista de objs) para economizar memória com: mAdapter.notifyItemInserted (mItems.size () - 1);

Oz Shabat
fonte
0

Esta é a resposta simples de como adicionar dados dinamicamente no listview 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")

    }
}

Aqui, acabei de explicar duas maneiras, podemos fazer isso de várias maneiras.

sirajudheen tk
fonte
Onde está a parte que você adicionou ao ListView?
Onie Maniego
@OnieManiego aqui, adicionei os itens ao listview de duas maneiras: você pode ver acima 1. listItems.add ("a") listItems.add ("b") listItems.add ("c") listItems.add ("d ") listItems.add (" e ") é a primeira maneira que adiciono 2. para (itens na matriz) listItems.add (itens) segunda maneira que adiciono todos os itens da matriz
sirajudheen tk
@OnieManiego espero que você entenda, se isso for útil para você pls upvote
sirajudheen tk