티스토리 뷰

반응형

Stack Overflow에 자주 검색, 등록되는 문제들과 제가 개발 중 찾아 본 문제들 중에서 나중에도 찾아 볼 것 같은 문제들을 정리하고 있습니다.

Stack Overflow에서 가장 먼저 확인하게 되는 가장 높은 점수를 받은 Solution과 현 시점에 도움이 될 수 있는 가장 최근에 업데이트(최소 점수 확보)된 Solution을 각각 정리하였습니다.

 

아래 word cloud를 통해 이번 포스팅의 주요 키워드를 미리 확인하세요.

Is there an addHeaderView equivalent for RecyclerView?

리사이클러 뷰에 해당하는 addHeaderView가 있습니까?

 문제 내용 

I'm looking for an equivalent to addHeaderView for a recycler view. Basically I want to have an image with 2 buttons be added as a header to the listview. Is there a different way to add a header view to a recycler view? An example for guidance would be helpful

리사이클러 뷰를 위해 HeaderView를 추가할 수 있는 동등한 것을 찾고 있습니다. 기본적으로 나는 2개의 버튼이 있는 이미지를 리스트 뷰에 헤더로 추가하고 싶다. 헤더 뷰를 재활용기 뷰에 추가하는 다른 방법이 있나요? 지침의 예는 도움이 될 것이다.

 

EDIT 2 (added fragment layouts):

EDIT 2(프래그먼트 레이아웃 추가):

 

After adding log statements, it seems as though getViewType only ever receives a position of 0. This leads to onCreateView only loading the one layout:

로그 문을 추가한 후 getView처럼 표시됩니다.형식은 0의 위치만 수신합니다. 따라서 onCreateView는 레이아웃 하나만 로드합니다.

 

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 

The fragment transition to load the CommentFragment:

CommentFragment를 로드하기 위한 fragment 전환:

 

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

The Fragment's onCreateView:

Fragment의 CreateView:

 

@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; } 

The fragment containing the recycleview:

recyclerview를 포함하는 fragment:

 

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

The comments row layout:

주석 행 레이아웃:

 

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

The header

머리글

 

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

The Adapter code (thanks to hister for getting me started):

어댑터 코드(시작하게 해준 히스터에게 감사):

 

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 = 1;      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);         }     } } 

Using the above code, only the header layout is displayed as viewType is always 0. It looks like this. If I force the other layout it looks like this:

위의 코드를 사용하면 헤더 레이아웃만 보기로 표시됩니다.유형은 항상 0입니다. 이렇게 생겼어요. 다른 레이아웃을 강제로 적용하면 다음과 같습니다.

 

 

 

 높은 점수를 받은 Solution 

There isn't an easy way like listview.addHeaderView() but you can achieve this by adding a type to your adapter for header.

listview.addHeaderView()처럼 쉬운 방법은 없지만 어댑터에 헤더 유형을 추가하여 이를 달성할 수 있습니다.

 

Here is an example

여기에 예가 있다.

 

public class HeaderAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {     private static final int TYPE_HEADER = 0;     private static final int TYPE_ITEM = 1;     String[] data;      public HeaderAdapter(String[] data) {         this.data = data;     }      @Override     public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {         if (viewType == TYPE_ITEM) {             //inflate your layout and pass it to view holder             return new VHItem(null);         } else if (viewType == TYPE_HEADER) {             //inflate your layout and pass it to view holder             return new VHHeader(null);         }          throw new RuntimeException("there is no type that matches the type " + viewType + " + make sure your using types correctly");     }      @Override     public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {         if (holder instanceof VHItem) {             String dataItem = getItem(position);             //cast holder to VHItem and set data         } else if (holder instanceof VHHeader) {             //cast holder to VHHeader and set data for header.         }     }      @Override     public int getItemCount() {         return data.length + 1;     }      @Override     public int getItemViewType(int position) {         if (isPositionHeader(position))             return TYPE_HEADER;          return TYPE_ITEM;     }      private boolean isPositionHeader(int position) {         return position == 0;     }      private String getItem(int position) {         return data[position - 1];     }      class VHItem extends RecyclerView.ViewHolder {         TextView title;          public VHItem(View itemView) {             super(itemView);         }     }      class VHHeader extends RecyclerView.ViewHolder {         Button button;          public VHHeader(View itemView) {             super(itemView);         }     } } 

link to gist -> here

gist -> 여기에 링크

 

 

 

 가장 최근 달린 Solution 

I know it is an old question, but want to provide an answer anyways.

나는 그것이 오래된 질문이라는 것을 알지만, 어쨌든 답을 제공하고 싶다.

 

There is a ConcatAdapter (docs here) that solves the problem for you. All you have to do is to define your header view layout and create a dummy Adapter with a single item In Kotlin it takes literally a few lines

문제를 해결하는 Concat Adapter(여기 문서)가 있습니다. 헤더 뷰 레이아웃을 정의하고 단일 항목으로 더미 어댑터를 생성하기만 하면 됩니다. 코틀린에서는 말 그대로 몇 줄이 필요하다.

 

class HeaderAdapter(private val inflater: LayoutInflater) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {          override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = object : RecyclerView.ViewHolder(inflater.inflate(yourViewLayoutId, parent, false)) {}      override fun onBindViewHolder(viewHolder: RecyclerView.ViewHolder, position: Int) {}      override fun getItemCount() = 1 } 

After that all you have to do is to add your header adapter and original adapter to the ConcatAdapter

그런 다음 헤더 어댑터와 원래 어댑터를 Concat 어댑터에 추가하기만 하면 됩니다.

 

recyclerView.adapter = ConcatAdapter(headerAdapter, adapter) 

See documentation for more details and advanced cases.

자세한 내용 및 고급 사례는 설명서를 참조하십시오.

 

 

 

출처 : https://stackoverflow.com/questions/26530685/is-there-an-addheaderview-equivalent-for-recyclerview

반응형
댓글
공지사항
최근에 올라온 글