Android ListView z różnymi układami dla każdego wiersza

Próbuję określić najlepszy sposób na posiadanie pojedynczego widoku listy, który zawiera różne układy dla każdego wiersza. Wiem, jak utworzyć niestandardowy wiersz + Niestandardowy adapter tablicy, aby obsługiwać Niestandardowy wiersz dla całego widoku listy, ale jak Mogę zaimplementować wiele różnych stylów wierszy w widoku listy?

Author: w.donahue, 2011-01-23

6 answers

Ponieważ wiesz, ile typów układów byś miał - możliwe jest użycie tych metod.

getViewTypeCount() - ta metoda zwraca informację ile typów wierszy masz na liście

getItemViewType(int position) - Zwraca informację, jakiego typu układu należy użyć na podstawie pozycji

Następnie nadmuchujesz układ tylko wtedy, gdy jest null i określasz typ za pomocą getItemViewType.

Spójrz na ten samouczek w celu uzyskania dalszych informacji.

Aby osiągnąć pewne optymalizacje w strukturze, którą opisałeś w komentarzu, sugerowałbym:

  • Przechowywanie widoków w obiekcie o nazwie ViewHolder. ZwiÄ™kszyÅ‚oby to prÄ™dkość, ponieważ nie bÄ™dziesz musiaÅ‚ wywoÅ‚ywać findViewById() za każdym razem w metodzie getView. Zobacz List14 w wersji demonstracyjnej API .
  • Utwórz jeden ogólny ukÅ‚ad, który bÄ™dzie zgodny ze wszystkimi kombinacjami wÅ‚aÅ›ciwoÅ›ci i ukryje niektóre elementy, jeÅ›li bieżąca pozycja go nie ma.
Mam nadzieję, że to ci pomoże. Jeśli możesz podać jakiś stub XML ze strukturą danych i informacje, jak dokładnie chcesz to odwzorować w wierszu, byłbym w stanie dać ci dokładniejszą radę. Przez pixel.
 413
Author: Cristian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-20 12:47:47

Wiem, jak utworzyć niestandardowy wiersz + Niestandardowy adapter tablicy, aby obsługiwać Niestandardowy wiersz dla całego widoku listy. Ale w jaki sposób jeden widok listy może obsługiwać wiele różnych stylów wierszy?

Znasz już podstawy. Wystarczy, że Twój niestandardowy adapter zwróci inny układ/widok na podstawie dostarczonych informacji o wierszu / kursorze.

A ListView może obsługiwać wiele stylów wierszy, ponieważ wywodzi się z AdapterView :

Adapterview is a view których dzieci są określone przez Adapter.

Jeśli spojrzysz na Adapter , zobaczysz metody, które uwzględniają używanie widoków specyficznych dla wiersza:

abstract int getViewTypeCount()
// Returns the number of types of Views that will be created ...

abstract int getItemViewType(int position)
// Get the type of View that will be created ...

abstract View getView(int position, View convertView, ViewGroup parent)
// Get a View that displays the data ...

Dwie ostatnie metody podaj pozycję więc możesz użyć tego do określ rodzaj widoku należy użyć dla tego rzędu.


Oczywiście generalnie nie używasz AdapterView i Adaptera bezpośrednio, ale raczej używać lub czerpać z jednej z ich podklas. Podklasy adaptera mogą dodawać dodatkowe funkcje, które zmieniają sposób uzyskiwania niestandardowych układów dla różnych wierszy. ponieważ widok używany dla danego wiersza jest napędzany przez adapter, sztuką jest zwrócenie przez adapter żądanego widoku dla danego wiersza. sposób, w jaki to zrobić, różni się w zależności od konkretnego adaptera.

Na przykład, aby użyć ArrayAdapter,

  • override getView() aby nadmuchać, wypeÅ‚nić i zwrócić żądany widok dla danej pozycji. Metoda getView() zawiera możliwość ponownego wykorzystania widoków za pomocÄ… parametru convertView.

Ale aby używać pochodnych CursorAdapter,

  • override newView() aby nadmuchać, wypeÅ‚nić i zwrócić żądany widok dla bieżącego stanu kursora (tj. bieżącego "wiersza") [musisz również nadpisać bindView Aby widget mógÅ‚ ponownie wykorzystać widoki]

Jednakże, aby użyć SimpleCursorAdapter,

  • zdefiniuj SimpleCursorAdapter.ViewBinder za pomocÄ… metody setViewValue(), aby napompować, wypeÅ‚nić i zwrócić żądany widok dla danego wiersza (bieżący stan kursora) i "kolumny"danych. Metoda może definiować tylko" specjalne "widoki i odwoÅ‚ywać siÄ™ do standardowego zachowania SimpleCursorAdapter dla "normalnych" powiÄ…zaÅ„.

Poszukaj konkretnych przykładów / samouczków dla rodzaju adapter, którego używasz.

 62
Author: Bert F,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-24 02:58:02

Spójrz w poniższy kod.

Najpierw tworzymy własne układy. W tym przypadku cztery typy.

Parzyste.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:background="#ff500000"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/text"
        android:textColor="@android:color/white"
        android:layout_width="match_parent"
        android:layout_gravity="center"
        android:textSize="24sp"
        android:layout_height="wrap_content" />

 </LinearLayout>
Dziwne.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:background="#ff001f50"
    android:gravity="right"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/text"
        android:textColor="@android:color/white"
        android:layout_width="wrap_content"
        android:layout_gravity="center"
        android:textSize="28sp"
        android:layout_height="wrap_content"  />

 </LinearLayout>

Biały.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:background="#ffffffff"
    android:gravity="right"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/text"
        android:textColor="@android:color/black"
        android:layout_width="wrap_content"
        android:layout_gravity="center"
        android:textSize="28sp"
        android:layout_height="wrap_content"   />

 </LinearLayout>
Czarny.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:background="#ff000000"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/text"
        android:textColor="@android:color/white"
        android:layout_width="wrap_content"
        android:layout_gravity="center"
        android:textSize="33sp"
        android:layout_height="wrap_content"   />

 </LinearLayout>

Następnie tworzymy pozycję listview. W naszym przypadku, ze sznurkiem i typem.

public class ListViewItem {
        private String text;
        private int type;

        public ListViewItem(String text, int type) {
            this.text = text;
            this.type = type;
        }

        public String getText() {
            return text;
        }

        public void setText(String text) {
            this.text = text;
        }

        public int getType() {
            return type;
        }

        public void setType(int type) {
            this.type = type;
        }

    }

Następnie tworzymy uchwyt widoku. Jest to zdecydowanie zalecane, ponieważ system operacyjny Android zachowuje odniesienie do układu, aby ponownie użyć elementu, gdy zniknie i pojawi się z powrotem na ekran. Jeśli nie używasz tego podejścia, za każdym razem, gdy element pojawi się na ekranie System Operacyjny Android utworzy nowy i spowoduje wyciek pamięci aplikacji.

public class ViewHolder {
        TextView text;

        public ViewHolder(TextView text) {
            this.text = text;
        }

        public TextView getText() {
            return text;
        }

        public void setText(TextView text) {
            this.text = text;
        }

    }

Na koniec tworzymy nasz własny adapter zastępujący getViewTypeCount () i getItemViewType (int position).

public class CustomAdapter extends ArrayAdapter {

        public static final int TYPE_ODD = 0;
        public static final int TYPE_EVEN = 1;
        public static final int TYPE_WHITE = 2;
        public static final int TYPE_BLACK = 3;

        private ListViewItem[] objects;

        @Override
        public int getViewTypeCount() {
            return 4;
        }

        @Override
        public int getItemViewType(int position) {
            return objects[position].getType();
        }

        public CustomAdapter(Context context, int resource, ListViewItem[] objects) {
            super(context, resource, objects);
            this.objects = objects;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {

            ViewHolder viewHolder = null;
            ListViewItem listViewItem = objects[position];
            int listViewItemType = getItemViewType(position);


            if (convertView == null) {

                if (listViewItemType == TYPE_EVEN) {
                    convertView = LayoutInflater.from(getContext()).inflate(R.layout.type_even, null);
                } else if (listViewItemType == TYPE_ODD) {
                    convertView = LayoutInflater.from(getContext()).inflate(R.layout.type_odd, null);
                } else if (listViewItemType == TYPE_WHITE) {
                    convertView = LayoutInflater.from(getContext()).inflate(R.layout.type_white, null);
                } else {
                    convertView = LayoutInflater.from(getContext()).inflate(R.layout.type_black, null);
                }

                TextView textView = (TextView) convertView.findViewById(R.id.text);
                viewHolder = new ViewHolder(textView);

                convertView.setTag(viewHolder);

            } else {
                viewHolder = (ViewHolder) convertView.getTag();
            }

            viewHolder.getText().setText(listViewItem.getText());

            return convertView;
        }

    }

A nasza aktywność jest mniej więcej taka:

private ListView listView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main); // here, you can create a single layout with a listview

        listView = (ListView) findViewById(R.id.listview);

        final ListViewItem[] items = new ListViewItem[40];

        for (int i = 0; i < items.length; i++) {
            if (i == 4) {
                items[i] = new ListViewItem("White " + i, CustomAdapter.TYPE_WHITE);
            } else if (i == 9) {
                items[i] = new ListViewItem("Black " + i, CustomAdapter.TYPE_BLACK);
            } else if (i % 2 == 0) {
                items[i] = new ListViewItem("EVEN " + i, CustomAdapter.TYPE_EVEN);
            } else {
                items[i] = new ListViewItem("ODD " + i, CustomAdapter.TYPE_ODD);
            }
        }

        CustomAdapter customAdapter = new CustomAdapter(this, R.id.text, items);
        listView.setAdapter(customAdapter);
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView adapterView, View view, int i, long l) {
                Toast.makeText(getBaseContext(), items[i].getText(), Toast.LENGTH_SHORT).show();
            }
        });

    }
}

Teraz Utwórz listview wewnątrz mainactivity.xml like this

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context="com.example.shivnandan.gygy.MainActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

    </android.support.design.widget.AppBarLayout>

    <include layout="@layout/content_main" />

    <ListView
        android:layout_width="match_parent"

        android:layout_height="match_parent"

        android:id="@+id/listView"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"


        android:layout_marginTop="100dp" />

</android.support.design.widget.CoordinatorLayout>
 43
Author: shiv,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-20 09:09:23

W niestandardowym adapterze tablicy, nadpisujesz metodę getView (), z którą prawdopodobnie znasz. Następnie wystarczy użyć polecenia switch lub polecenia if, aby zwrócić określony widok niestandardowy w zależności od argumentu pozycji przekazanego do metody getView. Android jest sprytny, ponieważ daje tylko widok convertView odpowiedniego typu dla twojej pozycji/wiersza; nie musisz sprawdzać, czy jest prawidłowy. Możesz pomóc Androidowi w tym, nadpisując getItemViewType() oraz odpowiednio metody getViewTypeCount ().

 14
Author: Jems,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-23 23:32:00

Jeśli chcemy pokazać inny typ widoku w list-view to warto użyć getViewTypeCount () i getItemViewType () w adapterze zamiast przełączać widok widoku./ Align = "left" / Widoczne może być bardzo kosztowne zadanie wewnątrz getView (), które wpłynie na przewijanie listy.

Proszę sprawdzić, czy w adapterze można użyć getViewTypeCount() i getItemViewType ().

Link: the-use-of-getviewtypecount

 4
Author: kyogs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-30 05:37:04

ListView był przeznaczony do prostych przypadków użycia, takich jak ten sam widok statyczny dla wszystkich pozycji wiersza.
Ponieważ musisz tworzyć Viewholdery i znacząco wykorzystywać getItemViewType() i dynamicznie pokazywać różne układy elementów wiersza xml, powinieneś spróbować to zrobić za pomocą RecyclerView, który jest dostępny w Android API 22. Oferuje lepszą obsługę i strukturę dla wielu typów widoków.

Zobacz ten tutorial Jak korzystać z RecyclerView, aby robić to, czego szukasz.
 1
Author: Phileo99,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-25 17:32:45