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.
Related
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 have an API which gives 10 per page result at once
{ item1,
item2,
item3,
.
.
item10
}
I have RecycleView in which I want to display the result.
public class RecycleAdapter extends RecyclerView.Adapter<RecycleAdapter.ViewHolder> {
private Entry[] entry;
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public static class ViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
TextView labelText;
TextView descText;
ImageView itemImage;
public ViewHolder(View v) {
super(v);
labelText = (TextView) v.findViewById(R.id.item_label);
descText = (TextView) v.findViewById(R.id.item_text);
itemImage = (ImageView) v.findViewById(R.id.item_image);
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public RecycleAdapter(Entry[] en) {
entry = en;
}
// Create new views (invoked by the layout manager)
#Override
public RecycleAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_items, parent, false);
// set the view's size, margins, paddings and layout parameters
ViewHolder vh = new ViewHolder(view);
return vh;
}
// Replace the contents of a view (invoked by the layout manager)
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
holder.labelText.setText(entry[position].title);
holder.itemImage.setImageResource(R.drawable.img);
holder.descText.setText("Random Text to Recycle");
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return entry.length;
}
}
Entry object contains the Array if Object containing data (basically String). instead of this I would like to pass and integer array
denoting the page of API and than I want to list all 10 item of that page
It seems to me that we can get only one item at a time in bind function or other way is to insert all item in Entry at beginning and than fetch them (which I want to avoid).
You can use addOnScrollListener behavior of recyclerView to monitor the scroll, and use layoutManager.findLastCompletelyVisibleItemPosition() to know who's the last item.When you know it you can populate the next 10 items you've fetched before and for a better user experience you can use adapter.notifyItemRangeInserted(int startPosition, int itemCount) to notify the list from below that postition so that if for example you had 10 items in the recyclerView before the fetch, so after the fetch you'll notify from last item (via layoutManager method above) to itemCount added (in your case 10) then the first 10 displayed will still be shown and the next 10 will be added to the bottom of the recycler, and the user will be able to 'continue' scrolling.
Hope it helps, good luck
Lets say your API gives you X items at a time. When getView is called with position lastFetchedItem-Y (where Y is a small number used to give some buffer for network delay) you request the next X items. When you receive them, you update the model backing your adapter and call notifyDataSetChanged. This will give you a smooth scroll. Adjust X and Y for network efficiency (slower networks or slower APIs, bigger Y).
Use Endless Scrolling with AdapterViews and RecyclerView
This tutorial will help you do paging functionality.
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.
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))