Jak dodawać elementy do listy Wyświetlaj dynamicznie w Androidzie

326

Czy ktoś może wyjaśnić lub zasugerować samouczek, aby utworzyć ListView w Androidzie?

Oto moje wymagania:

  • Powinienem być w stanie dynamicznie dodawać nowe elementy, naciskając przycisk.
  • Powinien być wystarczająco prosty do zrozumienia (na przykład bez poprawy wydajności lub konwersji)

Wiem, że jest wiele pytań na ten temat, zamieszczonych tutaj na StackOverflow, ale nie mogłem znaleźć odpowiedzi na moje pytanie. Dzięki!

użytkownik555217
źródło
3
Obecnie najlepiej głosowana odpowiedź Shardul jest uważana za wysoką jakość, a użytkownicy wyrazili opinię, że powinni ją zaakceptować. Czy możesz to zaakceptować?
Matt Welke,

Odpowiedzi:

583

Najpierw utwórz układ XML w folderze projektu res/layout/main.xml:

<?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>

Jest to prosty układ z przyciskiem u góry i widokiem listy na dole. Zauważ, że ListViewma identyfikator, @android:id/listktóry definiuje domyślny, ListViewktórego ListActivitymożna użyć.

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 jest domyślnym układem elementów listy dostarczanym przez system Android. Tego układu podstawowego można użyć do niezłożonych rzeczy.

listItemsjest listą zawierającą dane pokazane w ListView. Wszelkie wstawianie i usuwanie powinno odbywać się w dniu listItems; zmiany listItemspowinny zostać odzwierciedlone w widoku. Jest to obsługiwane przez ArrayAdapter<String> adapter, o czym należy powiadomić za pomocą:

adapter.notifyDataSetChanged();

Adapter jest tworzony z 3 parametrami: kontekstem, którym może być twój activity/listactivity; układ indywidualnej pozycji na liście; i na koniec lista, która jest rzeczywistymi danymi do wyświetlenia na liście.

Shardul
źródło
2
Nie rozumiem, w jaki sposób ListView wiąże się z naszą działalnością tutaj.
Breedly,
7
@Breedly Ponieważ jest to ListActivity, a nie działanie, które ma układ z ListView . Nie musisz znajdować widoku identyfikatora. Jak można przeczytać na odniesienie: ListActivity is an activity that includes a ListView as its only layout element by default. [...] (it) hosts a ListView object. Tak więc domyślnie metody (jak setAdapter itp.) Znajdują się „wewnątrz” klasy.
fllo
Pokażmy szczęście, gdy
otrzymamy
1
Jeśli element ArrayList jest bardziej skomplikowany, np. Ładowanie z Internetu, a każdy element zawiera obraz wideo i coś w tym rodzaju, czy to podejście miałoby wpływ na wydajność?
zionpi
1
Jak mogę to zaimplementować we fragmencie?
Oamar Kanji,
64

zamiast

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

możesz bezpośrednio zadzwonić

adapter.add("New Item");
venkat530
źródło
@ gumuruh sam adapter jest modyfikowalny, dzięki czemu możemy bezpośrednio dodawać lub usuwać obiekty, które będą automatycznie wywoływać powiadomieniaDatasetChanged () i getView () listView. Zmniejsza to dodatkową linię kodu.
venkat530
więc dodając do adaptera automatycznie wywołujemy powiadomienieDatasetChanged ()? Rozumiem. Dzięki @ venkat530. Ale co z samą listą? To znaczy, jeśli powiedzmy najpierw, że stworzył listę arraylist, która była używana jako pojemnik danych dla adaptera. A teraz po prostu dodajesz element bezpośrednio do adaptera zamiast do listy arraylist. Czy dane tablicy arraylist są aktualizowane / nietknięte?
gumuruh
1
@ gumuruh drugi jest najlepszą praktyką, ponieważ jest zsynchronizowany.
Ricardo
1
@ gumuruh z pobieżnych eksperymentów i kodu źródłowego ArrayAdapter [ github.com/android/platform_frameworks_base/blob/master/core/… , wygląda na to, że podstawowy zestaw danych również zostanie zmodyfikowany.
CCJ,
Dostałem odpowiedź Shardula, a potem ją złamałem i nie mogłem wymyślić, jak ją naprawić. Pod wpływem kaprysu myślałem, że spróbuję tego i voila, to znowu działa! Dziękuję Ci bardzo! Chociaż nie mam pojęcia, jak i dlaczego to naprawiło. Dowolny pomysł?
donutguy640,
55

Najpierw musisz dodać ListView, EditText i przycisk do pliku activity_main.xml.

Teraz w swoim 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();
        }
    });
}

To działa dla mnie, mam nadzieję, że ci pomogłem

Robert
źródło
4
Bardzo dobre wyjaśnienie, a zwłaszcza dzięki za wyjaśnienie elementu adaptera - który wydaje się magicznie pojawiać w przykładach innych. :)
raddevus
1
To najlepszy przykład, jaki znalazłem na to :)
Dinuka Salwathura
Ta odpowiedź spełniła oczekiwania osoby. Prosty i czysty bez skomplikowanych ulepszeń. Najlepsza odpowiedź faktycznie wprowadza ListActivity, o której wiedzą tylko wielcy mistrzowie. Mój jedyny problem polega teraz na tym, jak dodawać rysunki i inne elementy do widoków na liście. Wydaje mi się, że dodaję tylko ciągi znaków.
Optymalizacją może być utworzenie nienazwanego obiektu List w adapterze niż 16-bitowy wskaźnik do obiektu listy. Co nie jest potrzebne po utworzeniu adaptera, ponieważ adapter ma metodę dodawania.
17

Jeśli chcesz mieć ListView w AppCompatActivity zamiast ListActivity, możesz wykonać następujące czynności (Modyfikowanie odpowiedzi @ 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;
        }
    }
}

A w twoim układzie zamiast używać android:id="@android:id/list"możesz użyćandroid:id="@+id/listDemo"

Teraz możesz mieć ListViewwnętrze normalne AppCompatActivity.

srinivas
źródło
12

Kod pliku 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();
            }
        });
    }
}

Kod pliku układu 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>

Zrzut ekranu

wprowadź opis zdjęcia tutaj

Amir Hosseinzadeh
źródło
0

Krótka odpowiedź: kiedy tworzysz ListView, przekazujesz mu odniesienie do danych. Teraz, ilekroć dane te zostaną zmienione, wpłynie to na widok listy, a tym samym doda do niej element, po wywołaniu adapter.notifyDataSetChanged () ;.

Jeśli używasz RecyclerView, zaktualizuj tylko ostatni element (jeśli dodałeś go na końcu listy obiektów), aby zaoszczędzić pamięć za pomocą: mAdapter.notifyItemInserted (mItems.size () - 1);

Oz Shabat
źródło
0

Jest to prosta odpowiedź, jak dynamicznie dodawać dane w widoku listy 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")

    }
}

Właśnie wyjaśniłem dwa sposoby, możemy to zrobić na wiele sposobów.

sirajudheen tk
źródło
Gdzie jest część, którą dodajesz do ListView?
Onie Maniego
@OnieManiego tutaj dodałem elementy do widoku listy na dwa sposoby, widać to powyżej 1. listItems.add („a”) listItems.add („b”) listItems.add („c”) listItems.add („d „) listItems.add („ e ”) jest to pierwszy sposób, w jaki dodałem 2. dla (elementów w tablicy) listItems.add (przedmiotów) drugi sposób dodałem wszystkie elementy z tablicy
sirajudheen tk
@OnieManiego mam nadzieję, że rozumiesz, jeśli to pomocne dla Ciebie pls głosowanie
Sirajudheen TK