I have a RecyclerView with a dynamic number of elements (The heights of the elements is not known in advance). If the heights of all elements is less than the screen height, I want to add equal spaces between the elements. Is there a simple way to do something like this?
Thanks!
CraniumRat
Use this class to add space dynamically to the recyclerview:
public class VerticalSpaceItemDecoration extends RecyclerView.ItemDecoration {
private final int mVerticalSpaceHeight;
public VerticalSpaceItemDecoration(int mVerticalSpaceHeight) {
this.mVerticalSpaceHeight = mVerticalSpaceHeight;
}
#Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
RecyclerView.State state) {
outRect.bottom = mVerticalSpaceHeight;
}
}
If you set up the list or the sum of the heights of all elements changes then also update mVerticalSpaceHeight.
Add this line:
rv.addItemDecoration(new VerticalSpaceItemDecoration(PUT THE CALCULATED HEIGHT IN HERE))
Related
in order to remove all items from recyclerview, I'm using the below code:
int size = recyclerViewAdapter.getItemCount();
recyclerViewAdapter.clearList();
recyclerViewAdapter.notifyItemRangeRemoved(0, size);
the recycler view is using the following ItemDecoration:
public class CollectionsDecoration extends RecyclerView.ItemDecoration {
private int margin;
public CollectionsDecoration(Context context) {
margin = MeasurementsComputer.getPX(5, context);
}
#Override
public void getItemOffsets(#NonNull Rect outRect, #NonNull View view, #NonNull RecyclerView parent, #NonNull RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
outRect.left = 0;
outRect.right = 0;
outRect.bottom = 0;
if (parent.getChildAdapterPosition(view) == 0)
outRect.top = 15 * margin;
else
outRect.top = 0;
}
}
as you can see, the first item has a larger top margin. the problem is that when I run the above code to remove all items, all items including the first item gets the top margin of zero, and then they get removed and hided. why the item decoration of first item is not respected at the time of removing?
If I understand correctly, you want to keep item decoration when you remove all items?
In that case, you can try adding separate view on top, and when the list is empty, set its visibility to View.VISIBLE, and when the list is not empty, set it to View.INVISIBLE.
Example of custom view as a decorator:
<View
android:id="#+id/dividerView"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#E3E4E5" />
I am trying to create a Comments section to my app and am using a RecyclerView to display the comments. I would like to add a left margin to each RecyclerView item to show the "depth" that the comment is replying at. I have successfully added padding to each item viewholder using viewHolder.itemView.setPadding(depth *30, 0, 0, 0); but there is no equivalent setMargin function.
This is what I have now:
The red line is where I want to create a margin, for example.
I will need to calculate the margin dynamically as well.
You could change your item views to be a View within a FrameLayout (or similar), so that adding margin actually accomplishes something. But my recommendation would be to use a RecyclerView.ItemDecoration to apply offsets to each view.
#Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
Context context = view.getContext();
int indentation = context.getResources().getDimensionPixelSize(R.dimen.indentation);
RecyclerView.ViewHolder holder = parent.getChildViewHolder(view);
outRect.left = indentation * holder.getIndentationLevel();
}
This is assuming you have a dimen resource for a single level of indentation, and that your ViewHolder has the item's indentation level.
How to make such like horizontal recycle view with nice UI animation.
Note: I can make horizontal recyclerview. but how can it start from middle and when scroll it comes in start? and secondly background image will be visible or invisible animatedly according scrolling.
I want to make such like I already try ItemDecoration but when it load fast time start from left after if start from center any help.
Set padding left on Recyclerview as below code to start your recyclerView row as per padding left :
your Xml code should be like this :
<LinearLayout
android:layout_marginTop="8dp"
android:background="#drawable/banner2"
android:layout_width="match_parent"
android:layout_height="240dp">
<android.support.v7.widget.RecyclerView
android:paddingLeft="180dp"
android:layout_marginTop="17dp"
android:id="#+id/recycler_kids"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</LinearLayout>
Look into this for detect hiding row on recyclerview to show background image Hiding views in RecyclerView
Linearlayout manager with horizontal orientation and PagerSnapHelper() will be helpful to achieve this. Following code from pagersnap will provide better illustration.
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
LinearLayoutManager layoutManager = new LinearLayoutManager(context,
LinearLayoutManager.HORIZONTAL, false);
SnapHelper snapHelper = new PagerSnapHelper();
recyclerView.setLayoutManager(layoutManager);
snapHelper.attachToRecyclerView(mRecyclerView);
To Start horizontal RecyclerView with a starting empty space Use:
recyclerView.addItemDecoration(new HorizontalSpaceItemDecoration(700));
and define Class: HorizontalSpaceItemDecoration(); as
public class HorizontalSpaceItemDecoration extends RecyclerView.ItemDecoration {
private final int mHorizontalSpaceWidth;
public HorizontalSpaceItemDecoration(int mHorizontalSpaceWidth) {
this.mHorizontalSpaceWidth = mHorizontalSpaceWidth;
}
#Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
RecyclerView.State state) {
if (parent.getChildAdapterPosition(view) == 0) {
outRect.left = mHorizontalSpaceWidth;
}
}
my solution is to add blank item at first.
#Override
public int getItemViewType(int position) {
if (position==0){
return 1;
}else {
return super.getItemViewType(position);
}
}
you need to create blank item in xml for that
You can use this in your adapter :
if (position == 0) {
holder.card_zero.setVisibility(View.VISIBLE);
holder.card_info.setVisibility(View.GONE);
holder.card_pic.setVisibility(View.GONE);
} else {
holder.card_zero.setVisibility(View.GONE);
holder.card_info.setVisibility(View.VISIBLE);
holder.card_pic.setVisibility(View.VISIBLE);
I am trying to create a chat application with RecyclerView for displaying the list of messages in chatBubble form.
In recyclerView, in each row layout I have two text views. One for displaying the message and other for displaying the timestamp. For short messages, it works. However, for long messages, the chat bubble grows too big and the corresponding TextView for displaying timestamp can't be seen in this case.
Why is this happening and how to correct this,
Also, the space between each item in RecyclerView needs to be increased, I tried using android:dividerHeight="12dp" but it didn't work.
As #Mohammed Atif commented, instead of using
android:layout_toRightOf="#+id/message
use this
android:layout_alignParentRight="true"
Now, for adding space between recyclerview's items, you need to add itemDecorator
public class VerticalSpaceItemDecoration extends RecyclerView.ItemDecoration {
private final int mVerticalSpaceHeight;
public VerticalSpaceItemDecoration(int mVerticalSpaceHeight) {
this.mVerticalSpaceHeight = mVerticalSpaceHeight;
}
#Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
RecyclerView.State state) {
if (parent.getChildAdapterPosition(view) != parent.getAdapter().getItemCount() - 1) {
outRect.bottom = mVerticalSpaceHeight;
}
}
}
Then add this item decorator to recyclerview like this
recyclerview.addItemDecoration(new VerticalSpaceItemDecoration(2));
Here, 2 is the space between the recyclerview list items.
i am building an app on android and am using several recyclerviews.
in the first page that i used a recyclerview, everything worked flawlessly and my custom ItemDecoration (divider) was applied to all views.
then i started a new page in which i use the same divider on a similar RecyclerView, but on the last list item the bottom divider is not present.
seeing that it worked perfectly in one place, i don't believe the issue is with the custom ItemDecoration class, nor with the xml. I also tried using the same viewholder for the one that worked, but still the last divider was not drawn.
here is the code where is set up my adapter in the problematic recyclerview:
private void setUpPracticesList() {
lstPractices = (RecyclerView) getActivity().findViewById(R.id.lstPractices);
lstPractices.setLayoutManager(new LinearLayoutManager(getActivity()));
RecyclerView.Adapter<PracticeHolder> adapter = new RecyclerView.Adapter<PracticeHolder>() {
String[] titles = getResources().getStringArray(R.array.practices_names);
int[] imageIds = {R.drawable.consultation_meeting_icon,
R.drawable.monitoring_meeting_icon,
R.drawable.parent_lectures_icon,
R.drawable.parent_support_groups_icon,
R.drawable.staff_courses_icon};
#Override
public PracticeHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.kidsense_practices_list_item, parent, false);
return new PracticeHolder(v);
}
#Override
public void onBindViewHolder(PracticeHolder holder, int position) {
holder.setName(titles[position]);
holder.setImage(imageIds[position]);
}
#Override
public int getItemCount() {
return titles.length;
}
};
lstPractices.setAdapter(adapter);
lstPractices.setHasFixedSize(true);
lstPractices.addItemDecoration(new DividerItemDecoration(getActivity(), null));
}
does anyone have any ideas?
I have found the solution:
what i have found is that a recyclerview will not show a divider at the bottom of the last view if there is no more space left in the recyclerview.
in my case, the problem was that my recyclerview was in a layout that had a height of "wrap_content", meaning that there was no extra space left under the recyclerview to display the divider. as soon as i rearranged my layout so that my recyclerview had more space underneath with a parent layout height of "match_parent" the final divider was displayed.