2

So I've followed this awesome answer to get an header view in my recyclerview. Works great so far. Now it's time for implementation, but here comes the problem: How do I access a label or an image from my Fragment to my recycler view header?

I know the other way around, on button click, on any event handler from any recycler view holder to my fragment, but I can't figure out how to do it this way.

why?

In my header view is a EditText, Button and label. When user presses the button, it takes the text from the EditText, and sends it via some interfaces to my Fragment. After some code handling this will give a result, like, at least 3 characters required or after an API call it will give an message like: "No posts yet for this."

I think it is bad practice to do all the API handling and thinking inside that recyclerViewHolder. I prefer to do this in my fragment, and later I have to switch from one fragment to the other (tabbar) and then fill in the EditText automatically and start searching for posts.

Some code, my fragment:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_find, container, false);
    List<Post> emptyPosts = new ArrayList<>();

    adapter = new FindAdapter(emptyPosts);
    adapter.setClickListener(this);
    recyclerView = (RecyclerView) view.findViewById(R.id.rvFindList);
    LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity().getBaseContext());
    recyclerView.setLayoutManager(layoutManager);
    recyclerView.setItemAnimator(new DefaultItemAnimator());
    recyclerView.setAdapter(adapter);
    return view;
}

after some api call:

   adapter.setNewData(posts);
   adapter.notifyDataSetChanged();

The Adapter, pretty much basic implementation with some tweaks to get an header view in there:

public class FindAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private static final int TYPE_HEADER = 0;
    private static final int TYPE_ITEM = 1;
    List<Post> posts = Collections.emptyList();
    private ClickListenerFindList listener;

    public interface ClickListenerFindList{
        void FindClicked(View view, int position);
    }


    public FindAdapter(List<Post> posts) {
        this.posts = posts;

    }

    public void setNewData(List<Post> posts)
    {
        this.posts = posts;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == TYPE_ITEM) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.responses_row, parent, false);
            return new MyViewHolder(view);
        } else if (viewType == TYPE_HEADER) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.find_header, parent, false);
            return new HeaderViewHolder(view);
        }
        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 MyViewHolder) {
            MyViewHolder viewHolder = (MyViewHolder)holder;
            Post post = getItem(position);
            //...set contents for post
        } else if (holder instanceof HeaderViewHolder) {
            HeaderViewHolder headerView = (HeaderViewHolder) holder;
            //...set some extra values if needed

        }
    }

    //extra methods like getItemCounts, getItemViewType, isPositionHeader, getItem

    public void setClickListener(ClickListenerFindList listener)
    {
        this.listener = listener;
    }


    class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{

        //...fields, buttons, etc.

        public MyViewHolder(View itemView) {
            super(itemView);
            //...initiating fields, set one click listener to get back to fragment
        }

        @Override
        public void onClick(View v) {
            if(listener != null)
            {
                listener.FindClicked(v, getAdapterPosition());
            }
        }
    }

    class HeaderViewHolder  extends RecyclerView.ViewHolder
    {
        //...fields, buttons, etc.
       //how do I access them from fragment?

        public HeaderViewHolder(View itemView) {
            super(itemView);
            //..initiate fields, buttons, etc.
        }

    }
}

Question: How do I send data from my Fragment to HeaderViewHolder?

Community
  • 1
  • 1
CularBytes
  • 9,924
  • 8
  • 76
  • 101

1 Answers1

2

You could add a method to your Adapter to receive the data you want to update in the header. In that method, call this.notifydataSetChanged(). The Adapter will then call onBindViewHolder() for your header when your header is displayed/re-displayed.

drew
  • 2,371
  • 2
  • 19
  • 27
  • Can't this be without calling notifyDataSetChanged? since this will also (I guess?) Update the entire list.. Isn't there a solution with an interface or something? – CularBytes Sep 29 '15 at 17:45
  • It should only bind view holders for the visible rows - which if it's not the header will be none. – drew Sep 30 '15 at 13:05