Szukam ekwiwalentu addHeaderView dla widoku recyklera. Zasadniczo chcę mieć obraz z 2 przyciskami dodanymi jako nagłówek do widoku listy. Czy istnieje inny sposób dodania widoku nagłówka do widoku recyklera? Pomocny byłby przykład wskazówek
EDYCJA 2 (dodane układy fragmentów):
Po dodaniu instrukcji dziennika wydaje się, że getViewType zawsze otrzymuje pozycję 0. To prowadzi do tego, że onCreateView ładuje tylko jeden układ:
10-26 16:32:53.766 5449-5449/co.testapp I/logger info﹕ Adapter-> getItemCount: 5
10-26 16:32:53.766 5449-5449/co.testapp I/logger info﹕ Adapter-> getItemCount: 5
10-26 16:32:53.766 5449-5449/co.testapp I/logger info﹕ Adapter-> getItemCount: 5
10-26 16:32:53.766 5449-5449/co.testapp I/logger info﹕ Adapter-> getItemCount: 5
10-26 16:32:53.766 5449-5449/co.testapp I/logger info﹕ Adapter-> getItemCount: 5
10-26 16:32:53.766 5449-5449/co.testapp I/logger info﹕ Adapter-> getItemCount: 5
10-26 16:32:53.766 5449-5449/co.testapp I/logger info﹕ Adapter-> getItemCount: 5
10-26 16:32:53.766 5449-5449/co.testapp I/logger info﹕ Adapter-> getItemCount: 5
10-26 16:32:53.766 5449-5449/co.testapp I/logger info﹕ Adapter-> getItemCount: 5
10-26 16:32:53.766 5449-5449/co.testapp I/logger info﹕ Adapter-> getItemCount: 5
10-26 16:32:53.766 5449-5449/co.testapp I/logger info﹕ Adapter-> getItemCount: 5
10-26 16:32:53.766 5449-5449/co.testapp I/logger info﹕ Adapter-> getItemViewType position: 0
10-26 16:32:53.766 5449-5449/co.testapp I/logger info﹕ Adapter-> getItemViewType position: 0
10-26 16:32:53.766 5449-5449/co.testapp I/logger info﹕ Adapter-> getItemViewType position: 0
10-26 16:32:53.766 5449-5449/co.testapp I/logger info﹕ Adapter-> onCreateViewHolder, viewtype: 0
10-26 16:32:53.766 5449-5449/co.testapp I/logger info﹕ Adapter-> onBindViewHolder, viewType: 0
Przejście fragmentu w celu załadowania komentarza:
@Override
public void onPhotoFeedItemClick(View view, int position) {
if (fragmentManager == null)
fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
if (view.getId() == R.id.button_comment){
CommentFragment commentFragment = CommentFragment.newInstance("","", position);
fragmentTransaction.add(R.id.main_activity, commentFragment,"comment_fragment_tag");
fragmentTransaction.addToBackStack(Constants.TAG_COMMENTS);
fragmentTransaction.commit();
}
}
Fragment onCreateView:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_comment, container, false);
mRecyclerView = (RecyclerView) view.findViewById(R.id.list_recylclerview);
mRecyclerView.setLayoutManager(new LinearLayoutManager(_context));
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
mAdapter = new CommentAdapter(R.layout.row_list_comments, R.layout.row_header_comments, _context, comments);
mRecyclerView.setAdapter(mAdapter);
return view;
}
Fragment zawierający przegląd:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
tools:context="co.testapp.fragments.CommentFragment"
android:background="@color/white">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/list_recylclerview"
android:layout_width="match_parent"
android:layout_height="200dp" />
</RelativeLayout>
</RelativeLayout>
Układ wiersza komentarzy:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_margin="10dp"
android:background="@color/white">
<!--Profile Picture-->
<ImageView
android:layout_width="80dp"
android:layout_height="80dp"
android:id="@+id/profile_picture"
android:background="@color/blue_testapp"/>
<!--Name-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:text="First Name Last Name"
android:textSize="16dp"
android:textColor="@color/blue_testapp"
android:id="@+id/name_of_poster"
android:layout_toRightOf="@id/profile_picture"
/>
<!--Comment-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_marginTop="-5dp"
android:text="This is a test comment"
android:textSize="14dp"
android:textColor="@color/black"
android:id="@+id/comment"
android:layout_below="@id/name_of_poster"
android:layout_toRightOf="@id/profile_picture"/>
</RelativeLayout>
Nagłówek
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="300dp"
android:id="@+id/header_photo"
android:layout_gravity="center_horizontal"/>
</LinearLayout>
Kod adaptera (dzięki hister za rozpoczęcie pracy):
public class CommentAdapter extends RecyclerView.Adapter<ViewHolder>{
private final int rowCardLayout;
public static Context mContext;
private final int headerLayout;
private final String [] comments;
private static final int HEADER = 0;
private static final int OTHER = 0;
public CommentAdapter(int rowCardLayout, int headerLayout, Context context, String [] comments) {
this.rowCardLayout = rowCardLayout;
this.mContext = context;
this.comments = comments;
this.headerLayout = headerLayout;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
logger.i("onCreateViewHolder, viewtype: " + i); //viewtype always returns 0 so OTHER layout is never inflated
if (i == HEADER) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(headerLayout, viewGroup, false);
return new ViewHolderHeader(v);
}
else if (i == OTHER){
View v = LayoutInflater.from(viewGroup.getContext()).inflate(rowCardLayout, viewGroup, false);
return new ViewHolderComments(v);
}
else
throw new RuntimeException("Could not inflate layout");
}
@Override
public void onBindViewHolder(ViewHolder viewHolder, int i) {
logger.i("onBindViewHolder, viewType: " + i);
if (viewHolder instanceof ViewHolderComments)
((ViewHolderComments) viewHolder).comment.setText(comments[i].toString());
if (viewHolder instanceof ViewHolderHeader)
((ViewHolderHeader) viewHolder).header.setImageResource(R.drawable.image2);
else {
logger.e("no instance of viewholder found");
}
}
@Override
public int getItemCount() {
int count = comments.length + 1;
logger.i("getItemCount: " + count);
return count;
}
@Override
public int getItemViewType(int position) {
logger.i("getItemViewType position: " + position);
if (position == HEADER)
return HEADER;
else
return OTHER;
}
public static class ViewHolderComments extends RecyclerView.ViewHolder {
public TextView comment;
public ImageView image;
public ViewHolderComments(View itemView) {
super(itemView);
comment = (TextView) itemView.findViewById(R.id.comment);
image = (ImageView) itemView.findViewById(R.id.image);
}
}
public static class ViewHolderHeader extends RecyclerView.ViewHolder {
public final ImageView header;
public ViewHolderHeader(View itemView){
super(itemView);
header = (ImageView) itemView.findViewById(R.id.header_photo);
}
}
}
Przy użyciu powyższego kodu wyświetlany jest tylko układ nagłówka, ponieważ viewType ma zawsze wartość 0. Wygląda to tak . Gdybym zmusić drugą układ wygląda jak ten :
źródło
Odpowiedzi:
Nie ma łatwego sposobu,
listview.addHeaderView()
ale można to osiągnąć, dodając do adaptera typ nagłówka.Oto przykład
link do gist -> tutaj
źródło
private String getItem(int position) { return data[position + 1]; }
Powoduje NPE. Ponieważ nasza pozycja została zwiększona o jeden, z powodu nagłówka musimy odjąć 1, aby uzyskać prawidłowy element z naszych danych [].private String getItem(int position) { return data[position - 1]; }
setSpanSizeLookup
doGridLayoutManager
, więc nagłówek weźmie wszystkie kolumnyŁatwe i wielokrotnego użytku
ItemDecoration
Statyczne nagłówki mogą być łatwo dodawane z
ItemDecoration
i bez dalszych zmian.Dekoracja jest również wielokrotnego użytku, ponieważ nie ma potrzeby modyfikowania adaptera lub
RecyclerView
w ogóle.Przykładowy kod podany poniżej będzie wymagał widoku, aby dodać do góry, który można po prostu napompować jak wszystko inne. Może to wyglądać tak:
Dlaczego statyczny ?
Jeśli musisz tylko wyświetlić tekst i obrazy, to rozwiązanie jest dla Ciebie - nie ma możliwości interakcji użytkownika, takich jak przyciski lub pagery, ponieważ zostanie on po prostu przeniesiony na górę listy.
Obsługa pustej listy
Jeśli nie ma widoku do dekoracji, dekoracja nie zostanie narysowana. Nadal będziesz musiał samodzielnie obsługiwać pustą listę. (Jednym z możliwych obejść może być dodanie elementu zastępczego do adaptera).
Kod
Możesz znaleźć pełny kod źródłowy tutaj na GitHub, w tym
Builder
aby pomóc w inicjalizacji dekoratora, lub po prostu użyj kodu poniżej i podaj własne wartości do konstruktora.Pamiętaj, aby ustawić prawidłowy
layout_height
widok. np.match_parent
może nie działać poprawnie.Uwaga: Projekt GitHub to mój osobisty plac zabaw. To nie jest thorougly przetestowane, dlatego nie ma biblioteki jeszcze .
Co to robi?
ItemDecoration
Jest dodatkowy rysunek do elementu listy. W takim przypadku dekoracja jest rysowana na górze pierwszego elementu.Widok zostanie zmierzony i rozłożony, a następnie zostanie przeciągnięty na górę pierwszego elementu. Jeśli dodany zostanie efekt paralaksy, zostanie również przycięty do właściwych granic.
źródło
Zapraszam do korzystania z mojej biblioteki, dostępnej tutaj .
Pozwala utworzyć nagłówek
View
dla każdegoRecyclerView
, kto używaLinearLayoutManager
lubGridLayoutManager
za pomocą prostego wywołania metody.źródło
Pokażę ci, aby zrobić nagłówek z elementami w widoku Recycler.
Krok 1– Dodaj zależność do pliku ocen.
Cardview służy do celów dekoracyjnych.
Krok 2 - Utwórz trzy pliki XML. Jeden dla głównej aktywności Drugi dla układu nagłówka Trzeci dla układu elementu listy.
Activity_main.xml
header.xml
list.xml
Krok 3 - Utwórz trzy klasy fasoli.
Header.java
ContentItem.java
ListItem.java
Krok 4 - Utwórz adapter o nazwie MyRecyclerAdapter.java
Krok 5 - W MainActivity dodaj następujący kod:
Funkcja getList () dynamicznie generuje dane dla nagłówków i elementów listy.
źródło
Możesz to osiągnąć za pomocą biblioteki SectionedRecyclerViewAdapter , ma ona pojęcie „Sekcje”, w której sekcja ma Nagłówek, Stopkę i Treść (listę elementów). W twoim przypadku możesz potrzebować tylko jednej sekcji, ale możesz mieć wiele:
1) Utwórz niestandardową klasę sekcji:
2) Utwórz niestandardowy ViewHolder dla elementów:
3) Skonfiguruj ReclyclerView za pomocą SectionedRecyclerViewAdapter
źródło
Możesz po prostu umieścić nagłówek i RecyclerView w NestedScrollView:
Aby przewijanie działało poprawnie, musisz wyłączyć przewijanie zagnieżdżone w RecyclerView:
źródło
Natywny interfejs API nie ma takiej funkcji „addHeader”, ale ma pojęcie „addItem”.
Byłem w stanie włączyć tę szczególną funkcję nagłówków i rozszerzeń do stopek również w moim projekcie FlexibleAdapter . Nazwałem to Przewijanymi nagłówkami i stopkami .
Oto jak działają:
Przewijane nagłówki i stopki to specjalne elementy, które przewijają się wraz ze wszystkimi innymi, ale nie należą do głównych elementów (przedmiotów biznesowych) i zawsze są obsługiwane przez adapter obok głównych elementów. Przedmioty te są stale umieszczane na pierwszej i ostatniej pozycji.
Jest wiele do powiedzenia na ich temat, lepiej przeczytaj szczegółową stronę wiki .
Ponadto FlexibleAdapter pozwala tworzyć nagłówki / sekcje, a także można je lepić i dziesiątki innych funkcji, takich jak elementy rozwijane, nieskończone przewijanie, rozszerzenia interfejsu użytkownika itp ... wszystko w jednej bibliotece!
źródło
Na podstawie tego postu utworzyłem podklasę RecyclerView.Adapter, która obsługuje dowolną liczbę nagłówków i stopek.
https://gist.github.com/mheras/0908873267def75dc746
Chociaż wydaje się to rozwiązaniem, myślę również, że tą sprawą powinien zarządzać LayoutManager. Niestety, potrzebuję go teraz i nie mam czasu na wdrożenie StaggeredGridLayoutManager od zera (ani nawet z niego nie rozszerzać).
Nadal go testuję, ale możesz go wypróbować, jeśli chcesz. Daj mi znać, jeśli znajdziesz jakieś problemy.
źródło
Jest jeszcze jedno rozwiązanie, które obejmuje wszystkie powyższe przypadki użycia: CompoundAdapter: https://github.com/negusoft/CompoundAdapter-android
Możesz utworzyć grupę adapterów, która będzie przechowywać adapter w niezmienionej postaci, wraz z adapterem z pojedynczym elementem reprezentującym nagłówek. Kod jest łatwy i czytelny:
AdapterGroup pozwala również na zagnieżdżanie, więc dla adaptera z sekcjami możesz utworzyć AdapterGroup dla każdej sekcji. Następnie umieść wszystkie sekcje w katalogu głównym AdapterGroup.
źródło
HeaderView zależy od menedżera układu. Żaden z domyślnych menedżerów LayoutManagers nie obsługuje tego i prawdopodobnie nie będzie. HeaderView w ListView tworzy dużo złożoności bez żadnych znaczących korzyści.
Sugerowałbym utworzenie podstawowej klasy adaptera, która dodaje elementy do nagłówków, jeśli są dostępne. Nie zapomnij zastąpić metod powiadomień *, aby odpowiednio je zrównoważyć w zależności od tego, czy nagłówek jest obecny, czy nie.
źródło
ListView.addHeaderView
ani odpowiedzi na to pytanie.Po - Zastąp metodę getItemViewTpe *** Ważniejsze
Metoda onCreateViewHolder
Metoda onBindViewHolder
w zakończeniu implementuje statyczną klasę ViewHolders
źródło
tutaj niektóre elementy do podglądu recyklera
źródło
Wykonałem implementację opartą na @ hister dla moich osobistych celów, ale używając dziedziczenia.
I ukryć szczegóły implementacji mechanizmów (jak dodać 1 aby
itemCount
odjąć 1 odposition
) w abstrakcyjnej klasy SuperHeadingableRecycleAdapter
, poprzez wdrożenie metod wymaganych od zasilacza jakonBindViewHolder
,getItemViewType
igetItemCount
, co sprawia, że metody ostateczna i zapewnienie nowych metod z ukrytej logiki do klienta:onAddViewHolder(RecyclerView.ViewHolder holder, int position)
,onCreateViewHolder(ViewGroup parent)
,itemCount()
Oto
HeadingableRecycleAdapter
klasa i klient. Układ nagłówka pozostawiłem trochę zakodowany, ponieważ odpowiada moim potrzebom.źródło
Może zawiń nagłówek i widok programu recyklingowego w koordynatora :
źródło
Prawdopodobnie pomoże http://alexzh.com/tutorials/multiple-row-layouts-using-recyclerview/ . Wykorzystuje tylko RecyclerView i CardView. Oto adapter:
A oto istota:
źródło
możesz utworzyć addHeaderView i używać
adapter.addHeaderView(View)
.Ten kod buduje
addHeaderView
dla więcej niż jednego nagłówka. nagłówki powinny mieć:android:layout_height="wrap_content"
źródło
Minęło kilka lat, ale na wypadek, gdyby ktoś czytał to później ...
Problem polega na stałej deklaracji:
Jeśli zadeklarujesz je oba jako zero, zawsze otrzymasz zero!
źródło
Wdrożyłem to samo podejście zaproponowane w odpowiedzi EC84B4 , ale wyodrębniłem RecycleViewAdapter i sprawiłem, że można go łatwo przywrócić za pomocą interfejsów.
Aby więc zastosować moje podejście, należy dodać do swojego projektu następujące klasy podstawowe i interfejsy:
1) Interfejs udostępniający dane dla adaptera (zbiór typu ogólnego T i dodatkowe parametry (w razie potrzeby) typu ogólnego P)
2) Fabryka do wiązania twoich przedmiotów (nagłówek / pozycja):
3) Fabryka dla viewHolders (nagłówek / elementy):
4) Klasa podstawowa dla adaptera z nagłówkiem:
Przykład użycia :
1) Implementacja IRecycleViewListHolder:
2) Implementacja IViewHolderBinderFactory:
3) Implementacja IViewHolderFactory:
4) Adapter wyprowadzający
5) Utwórz instancję klasy adaptera:
PS : AssetItemViewHolder, AssetBasedListItemBinding itp. Moja aplikacja ma własne struktury, które powinny zostać zamienione przez ciebie, do własnych celów.
źródło