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?
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 metodziegetView
. 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.
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
Znasz już podstawy. Wystarczy, że Twój niestandardowy adapter zwróci inny układ/widok na podstawie dostarczonych informacji o wierszu / kursorze.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?
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. MetodagetView()
zawiera możliwość ponownego wykorzystania widoków za pomocą parametruconvertView
.
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Ä… metodysetViewValue()
, 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.
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>
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 ().
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 ().
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.
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