问题
I'm downloading data from an external db and populate arrays when the user scrolls down. I'm showing a footerview (loadmoreview) while the data is being downloaded. Where I'm currently stuck at is removing this footerview when the user got to the end of the list aka there is no more data to download.
Download:
private void DownloadUsersClassic(final String start, final String finish) {
loadingMore = true;
Log.i("DownloadUsersClassic", "started");
StringRequest postReq = new StringRequest(Request.Method.POST, download_leaderboard_classic, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
if (response.length() > 10) {
//populate arrays from json
if (arr_userid.size() < 14) {
//set adapter the first time the user scrolls
mAdapter = new CustomAdapter(getActivity(), arr_userid, arr_username, arr_photo, arr_level, arr_date, true);
rv.setAdapter(mAdapter);
} else {
//call notifyDataSetChanged() at the other scrolls
mAdapter.notifyDataSetChanged();
}
else {
//there is no more data to download
mAdapter = new CustomAdapter(getActivity(), arr_userid, arr_username, arr_photo, arr_level, arr_date, false);
mAdapter.notifyDataSetChanged();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.i("VOLLEY_ERROR", error.toString());
}
}) {
@Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("start", start);
params.put("finish", finish);
return params;
}
};
Adapter:
public class CustomAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
ArrayList<String> arr_userid = new ArrayList<String>();
ArrayList<String> arr_username = new ArrayList<String>();
ArrayList<String> arr_photo = new ArrayList<String>();
ArrayList<String> arr_level = new ArrayList<String>();
ArrayList<String> arr_date = new ArrayList<String>();
boolean show_footer;
public LayoutInflater inflater;
public static final int TYPE_ITEM = 1;
public static final int TYPE_FOOTER = 2;
Context context;
public CustomAdapter(Context context, ArrayList<String> arr_userid, ArrayList<String> arr_username, ArrayList<String> arr_photo, ArrayList<String> arr_level, ArrayList<String> arr_date, boolean show_footer) {
super();
this.arr_userid = arr_userid;
this.arr_username = arr_username;
this.arr_photo = arr_photo;
this.arr_level = arr_level;
this.arr_date = arr_date;
this.show_footer = show_footer;
this.inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public class GenericViewHolder extends RecyclerView.ViewHolder {
public TextView txtName, txtPoints, txtDate;
public ImageView ivUser;
public LinearLayout llLoadmore;
public GenericViewHolder(View v) {
super(v);
txtName = (TextView) v.findViewById(R.id.txtName);
txtPoints = (TextView) v.findViewById(R.id.txtPoints);
txtDate = (TextView) v.findViewById(R.id.txtDate);
ivUser = (ImageView) v.findViewById(R.id.ivUser);
llLoadmore = (LinearLayout) v.findViewById(R.id.loadmore);
}
}
class FooterViewHolder extends RecyclerView.ViewHolder {
TextView tvloadmore;
public FooterViewHolder (View itemView) {
super (itemView);
this.tvloadmore = (TextView) itemView.findViewById (R.id.tvloadmore);
}
}
public void add(int position, String item) {
arr_userid.add(position, item);
notifyItemInserted(position);
}
public void remove(String item) {
int position = arr_userid.indexOf(item);
arr_userid.remove(position);
notifyItemRemoved(position);
}
public CustomAdapter(ArrayList<String> myDataset) {
arr_userid = myDataset;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder (ViewGroup parent, int viewType) {
if(viewType == TYPE_FOOTER) {
View v = LayoutInflater.from (parent.getContext ()).inflate (R.layout.loadmore, parent, false);
return new FooterViewHolder (v);
} else if(viewType == TYPE_ITEM) {
View v = LayoutInflater.from (parent.getContext ()).inflate (R.layout.leaderboard_row, parent, false);
return new GenericViewHolder (v);
}
return null;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if(holder instanceof FooterViewHolder) {
FooterViewHolder footerHolder = (FooterViewHolder) holder;
footerHolder.tvloadmore.setText("Footer");
footerHolder.tvloadmore.setOnClickListener (new View.OnClickListener () {
@Override
public void onClick (View view) {
Toast.makeText (getActivity(), "Clicked Footer", Toast.LENGTH_SHORT).show ();
}
});
} else if(holder instanceof GenericViewHolder) {
GenericViewHolder genericViewHolder = (GenericViewHolder) holder;
final String name = arr_username.get(position);
genericViewHolder.txtName.setText(arr_username.get(position));
genericViewHolder.txtPoints.setText(arr_level.get(position) + " Levels");
String year = arr_date.get(position).substring(0, 4);
String month = arr_date.get(position).substring(5, 7);
String day = arr_date.get(position).substring(8, 10);
genericViewHolder.txtDate.setText(month + "." + day + "." + year);
if (!arr_photo.get(position).equals("")) {
Picasso.with(getActivity())
.load(arr_photo.get(position))
.into(genericViewHolder.ivUser);
} else {
genericViewHolder.ivUser.setImageDrawable(null);
}
}
}
@Override
public int getItemCount() {
if (show_footer) {
return arr_userid.size() + 1; //+1 is for the footer as it's an extra item
} else {
return arr_userid.size();
}
}
@Override
public int getItemViewType (int position) {
if (show_footer) {
if (isPositionFooter(position)) {
return TYPE_FOOTER;
}
return TYPE_ITEM;
} else {
return TYPE_ITEM;
}
}
private boolean isPositionFooter (int position) {
return position == arr_userid.size ();
}
}
onScrollListener:
rv.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
visibleItemCount = rv.getChildCount();
totalItemCount = llm.getItemCount();
firstVisibleItem = llm.findFirstVisibleItemPosition();
if (loading) {
if (totalItemCount > previousTotal) {
loading = false;
previousTotal = totalItemCount;
}
}
if (!loading && (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold)) {
// End has been reached
//we need the -1 otherwise 1 item will be missed the first time we scroll. I don't know why only the first
//time but the point it's working this way
DownloadUsersClassic(String.valueOf(totalItemCount-1), String.valueOf(num_loadfinish));
loading = true;
}
}
});
See the boolean variable at the end of the adapter? I'm trying to use it to tell the adapter whether I need the footer or I don't. It's true when I'm downloading data:
mAdapter = new CustomAdapter(getActivity(), arr_userid, arr_username, arr_photo, arr_level, arr_date, true);
And it's false when the end has been reached:
mAdapter = new CustomAdapter(getActivity(), arr_userid, arr_username, arr_photo, arr_level, arr_date, false);
The thing is, nothing happens. The footer stays there. I can't call
mAdapter = new CustomAdapter(getActivity(), arr_userid, arr_username, arr_photo, arr_level, arr_date, false);
rv.setAdapter(mAdapter);
because it reinitializes the adapter and it jumps to the top.
回答1:
Little modification in adapter class:-
@Override
public int getItemViewType(int position) {
return dataSet.get(position) != null ? VIEW_ITEM : VIEW_PROG;
}
insert null as an item while you are calling loadMore
like this:-
dataSet.add(null);
mAdapter.notifyItemInserted(dataSet.size() - 1);
Remove the item from recyclerView when the loadMore is done:-
dataset.remove(dataSet.size() - 1);
mAdapter.notifyItemRemoved(dataSet.size());
That's all. Hope this helps
回答2:
After a few hours I found it out. Where you determine that there is no more data to download, add:
mAdapter.hideFooter();
mAdapter.notifyDataSetChanged();
Add this to the adapter:
public void hideFooter() {
show_footer = false;
}
This tells the adapter to hide the footer at the end.
Check out this tutorial for the full code.
来源:https://stackoverflow.com/questions/33982271/remove-recyclerview-footerview