I have multiple lists in my Android app, the activities that contain those (recycle) listviews also contain other content. Putting a listview below the content works fine without any custom modelling. However, when scrolling in the list, it is only scrolling the list, thus showing about 1 or 2 items, while we would like to scroll the whole activity, so that the content moves up and the complete list is shown.
To make an activity scrollable, we would need a ScrollView, this goes a bit against the design guidelines, I know, but I need it.
To get this done, I used this solution: https://mcmap.net/q/37081/-how-can-i-put-a-listview-into-a-scrollview-without-it-collapsing
It works perfectly, as long as the height of the listview is set equal to the needed height for the items in the listview. So there comes my issue, How can I calculate this height.
Now I am in a bit of luck that the items in the lists have the same height, so with a bit of trial and error I could achieve this like so:
recyclerView.setMinimumHeight(posts.size() * 190);
This however, doesn't really work, since we have different resolutions and screen dimensions. on xhdpi this would work, but on xxhdpi I would still need space for 4 more items.
One solution I found:
int totalHeight = 0;
for (int i = 0; i < mAdapter.getCount(); i++) {
View mView = mAdapter.getView(i, null, listView);
mView.measure(
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
totalHeight += mView.getMeasuredHeight();
Log.w("HEIGHT" + i, String.valueOf(totalHeight));
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight
+ (listView.getDividerHeight() * (mAdapter.getCount() - 1));
listView.setLayoutParams(params);
listView.requestLayout();
However, this does not work with the RecyclerView.Adapter<myAdpater.MyViewHolder>
because it does not contain a getView()
method. (and not a getDividerHeight()
method eather).
This is how one of my adapters look like:
public class ResponsesAdpater extends RecyclerView.Adapter<ResponsesAdpater.MyViewHolder> {
private LayoutInflater inflrater;
List<Post> posts = Collections.emptyList();
Context context;
private ClickListenerResponseList listener;
public ResponsesAdpater(Context context, List<Post> posts) {
this.context = context;
inflrater = LayoutInflater.from(context);
this.posts = posts;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflrater.inflate(R.layout.responses_row, parent, false);
MyViewHolder holder = new MyViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
Post post = posts.get(position);
holder.lblMainText.setText(post.text);
}
public void setClickListener(ClickListenerResponseList listener)
{
this.listener = listener;
}
@Override
public int getItemCount() {
return posts.size();
}
class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
TextView lblMainText;
ImageView imgIcon;
public MyViewHolder(View itemView) {
super(itemView);
lblMainText = (TextView) itemView.findViewById(R.id.lblPostMainText);
imgIcon = (ImageView) itemView.findViewById(R.id.imgIcon);
}
@Override
public void onClick(View v) {
if(listener != null)
{
listener.ResponseClicked(v, getAdapterPosition());
}
}
}
public interface ClickListenerResponseList{
void ResponseClicked(View view, int position);
}
}
Another solution would be something like this, but when extending from RecyclerView, we don't have a onDraw method to override.
Help would be much appreciated!