I have RecyclerView with 2 columns. What I want is to show last item in center if number of items in list is odd. Something like this
I have tried implementing all the so threads from here https://www.google.com/search?client=firefox-b-d&q=show+last+item+in+recyclerview+center+horizontal+android
I have used below code to set layout manager
gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
#Override
public int getSpanSize(int position) {
if (mLangInfos.size() % 2 == 0)
return 1;
else {
if (position == mLangInfos.size()-1)
return 2;
else
return 1;
}
}
});
recyclerView.setLayoutManager(gridLayoutManager);
But what this does is it shows last item in full width, see below image.
Related
I need to do something like this:
How should I do this?
Update
This is almost working.
GridLayoutManager layoutManager = new GridLayoutManager(this, 3);
layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup()
{
#Override
public int getSpanSize(int position)
{
if (position == mElements.size()-1)
{
return 1;
}
else
{
SchedulePlanGlobal elem = mElements.get(position);
SchedulePlanGlobal elemNext = mElements.get(position+1);
if (elem.getRoomName().charAt(0) == elemNext.getRoomName().charAt(0))
{
return 1;
}
else
{
return calculateSpan(position);
}
}
}
private int calculateSpan(int position)
{
if (position == 0) return 3;
else
{
int currentPosition = position - 1;
int elements = 0;
while (currentPosition != 0)
{
if (mElements.get(currentPosition).getRoomName().charAt(0) == mElements.get(position).getRoomName().charAt(0))
{
elements ++;
}
else
{
break;
}
currentPosition --;
}
int spanPosition = (elements % 3) + 1;
switch (spanPosition)
{
case 1: return 3;
case 2: return 2;
default: return 1;
}
}
}
});
Implement and set GridLayoutManager.SpanSizeLookup.
override fun getSpanSize(position: Int) = /* set value based on position */
With that you can define how many spans (columns) item should use. In your case 4th item should take all 3 columns and other should take only 1 column.
A different layout manager might be an easier solution.
I suggest using https://github.com/google/flexbox-layout
You would set the layout manager to wrap, so if your items did not fit on the horizontal line then it would wrap it to a new line, this make it easy to fit on different screen sizes.
Then for your 5th item that you know you want on a new line you would use the layout_wrapBefore attribute. I would checkout the layout_wrapBefore example in the docs
I know that I can implement a RecyclerView with different views for items on Android.
But my need is a little bit different here. I would like to know how can I implement a RecyclerView with a different number of items by rows.
For example, I would have 2 items for first row, then just 1 item for second row, then 3 items for third row, ...
Is it possible to implement this with a RecyclerView? If so, How can I implement it?
Thanks for your help.
Sylvain
What you're looking for can be done with GridLayoutManager itself, the only trick here is to use the least common multiple (lcm) of your column counts per row as your total span count. Here is an easy example:
#Override
public void onCreate() {
super.onCreate();
...
int spanCount = lcm(2, 1, 3, 8);
GridLayoutManager layoutManager = new GridLayoutManager(this, spanCount);
layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
#Override
public int getSpanSize(int position) {
int numberOfColumns;
switch (position) {
case 0:
numberOfColumns = 2;
break;
case 1:
numberOfColumns = 1;
break;
case 2:
numberOfColumns = 3;
break;
case 3:
numberOfColumns = 8;
break;
default:
numberOfColumns = spanCount;
}
return spanCount / numberOfColumns;
}
});
recyclerView.setLayoutManager(layoutManager);
...
}
public static int lcm(int... input) {
int result = input[0];
for(int i = 1; i < input.length; i++) result = lcm(result, input[i]);
return result;
}
Yes it is possible, you just need to create different Views and get them in the
if (holder instanceof ProfileAdapter.VideoViewHolder) {
} else {
}
and throw the views inside the above method using
public int getItemViewType(int position) {
}
I am facing an issue while adding the horizontal recyclerview inside vertical recyclerview in 2nd position of recyclerview. The data is loaded in vertical recyclerview using arraylist. But the 2nd position data is not getting displayed in vertical recycler view in third position.How to achieve that?
#Override
public int getItemCount() {
if (mWaveLineResponseList != null && mWaveLineResponseList.size() > 0) {
return mWaveLineResponseList.size();
} else {
return 1;
}
}
#Override
public int getItemViewType(int position) {
if (position == 2) {
viewPosition = 3;
} else {
viewPosition = (position == mWaveLineResponseList.size() - 1 && isLoadingAdded) ? VIEW_TYPE_PROGRESS : VIEW_TYPE_NORMAL;
}
return viewPosition;
}
I have a horizontal recyclerView that has 28 elements. I want to achieve the following: display only 7 items at once and if the user swipes to the right then scroll to the next 7 items and same if swipes to the left then scroll to the previous 7 items. I have tried to solve it with the LinearSnapHelper like this:
public class CustomSnapHelper extends LinearSnapHelper {
#Override
public int findTargetSnapPosition(RecyclerView.LayoutManager layoutManager, int velocityX, int velocityY) {
View centerView = findSnapView(layoutManager);
if (centerView == null) {
return RecyclerView.NO_POSITION;
}
int position = layoutManager.getPosition(centerView);
int targetPosition = -1;
if (layoutManager.canScrollHorizontally()) {
if (velocityX < 0) {
targetPosition = position - 7;
} else {
targetPosition = position + 7;
}
}
final int firstItem = 0;
final int lastItem = layoutManager.getItemCount() - 1;
targetPosition = Math.min(lastItem, Math.max(targetPosition, firstItem));
return targetPosition;
}
}
But the problems are
If I drag the list and scroll a few positions and release it then it won't go back to the
original snapped position.
Sometimes (based on the velocity) If I
swipe to right when the first 7 item is displayed, then it scrolls
an additional space and snaps to the wrong position and the items
from 9-15 are displayed.
I'm trying to figure some way to achieve the next kind of view. At the moment I have tried to create a Listview and just make bigger the selected item. But I cannot make the selected item always be in the middle of my view. So now I'm trying to get this with a numberpicker.
But I didn't find any way to hide the divider bar, and make different the selected item and the rest of the view. The idea is get something like in the bottom image.
I think that the ListView may be more configurable than the NumberPicker.
What you can do is use different row layouts dependind if it is the middle one or the others, so your getView(...) method would look like this:
public View getView(int position, View convertView, ViewGroup parent) {
if (position == 1) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.focused_layout, parent, false);
// Do whatever with this view
} else {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.not_focused_layout, parent, false);
// Do whatever with this view
}
return convertView;
}
This way you can customize both layouts both in XML and code. Yo can change the condition if you want the "special" item any other way.
Following is a number picker with custom display values:
final NumberPicker aNumberPicker = new NumberPicker(context);
List<Integer> ids = getIds();
aNumberPicker.setMaxValue(ids.size()-1);
aNumberPicker.setMinValue(0);
mDisplayedIds = new String[ids.size()];
for (int i = 0; i < ids.size(); i++) {
mDisplayedIds[i] = "Nombre"+String.valueOf(ids.get(i)) ;
}
aNumberPicker.setDisplayedValues(mDisplayedIds);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(50, 50);
RelativeLayout.LayoutParams numPickerParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
numPickerParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
relativeLayout.setLayoutParams(params);
relativeLayout.addView(aNumberPicker, numPickerParams);
Also, you can check out some open source library like this one AndroidPicker
You can implement this using RecyclerView with one Holder for Normal Item and one Holder for Selected Item.
Inside your RecyclerView Adapter
private static int SELECTED_ITEM_POSITION = 2;
private static int NORMAL_ITEM = 1;
private static int SELECTED_ITEM = 2;
#Override
public int getItemViewType(int position)
{
if(position == SELECTED_ITEM_POSITION)
return SELECTED_ITEM;
else
return NORMAL_ITEM;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
if(viewType == SELECTED_ITEM)
{
YourSelectedViewHolder selectedViewHolder = (YourSelectedViewHolder)layoutInflater.inflate(R.layout.selected_item_layout, parent, false);
return selectedViewHolder;
}
else //viewType == NORMAL_ITEM
{
YourNormalViewHolder normalViewHolder = (YourNormalViewHolder)layoutInflater.inflate(R.layout.normal_item_layout, parent, false);
return normalViewHolder;
}
}
I wanted to achieve a pretty similar effect on one of my project, where I wanted the middle item of my recycler view to be more prominent.
In my case, that said item is only z-translated to give an impression of focus, but the result is pretty similar to what you're describing.
I'll post my code here, in case it could help you go in the right direction :
//We're on the onCreateView in a fragment here
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
//First I find the first visible element
int firstVisiblePosition = mLayoutManager.findFirstVisibleItemPosition();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (firstVisiblePosition != -1) {
int lastVisiblePosition = mLayoutManager.findLastVisibleItemPosition();
int itemHeight = mLayoutManager.getChildAt(0).getMeasuredHeight();
int itemTop = mLayoutManager.getChildAt(0).getTop();
//We use a '+' as itemTop will be negative
int delta = itemHeight + itemTop;
int currentItemToBeFocused = (delta < (itemHeight / 2)) ? 1 : 0;
//Reset the z-translation of other items to 0
for (int i = 0, last = (lastVisiblePosition - firstVisiblePosition); i <= last; ++i) {
if (mLayoutManager.getChildAt(i) != null) {
mLayoutManager.getChildAt(i).setTranslationZ(0);
}
}
//And set the z-translation of the current "centered" item
if (mLayoutManager.getChildAt(currentItemToBeFocused) != null) {
mLayoutManager.getChildAt(currentItemToBeFocused).setTranslationZ(10);
}
}
}
}
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
});