I need to create a horizontal list of items that only displays fully visible items.

But as you can see, my recycler view show a particular element. I use a horizontal LinearLayoutManager.
I add 10 elements, but recycler view has room only for 3. I need to show only 3, but it always show me 3 and particular element.
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintEnd_toStartOf="@+id/textView"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
My item layout:
<LinearLayout
android:id="@+id/itemLayout"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="10dp">
<TextView
android:id="@+id/tvAnimalName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ASDAS"
android:background="@color/colorAccent"
android:padding="10dp"
android:textSize="17sp"/>
</LinearLayout>
Adapter and activity are plain.
How can I show only visible 3 items?
Edit. I must to disable scroll. So i am using:
layoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false) {
@Override
public boolean canScrollHorizontally() {
return false;
}
};
Edit 2. These methods show -1 always:
int findLastVisibleItemPosition();
int findLastCompletelyVisibleItemPosition();
class HideLastDecorator() : RecyclerView.ItemDecoration() {
override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
super.onDraw(c, parent, state)
val count = parent.childCount
for (i in 0 until count) {
parent.getChildAt(i).visibility = if (count == i - 1) View.INVISIBLE else View.VISIBLE
}
}
}
and add it to your recyclerView Decorations
appsRecyclerView.addItemDecoration(HideLastDecorator())
Sorry for Kotlin :)
View.INVISIBLE is important, because if the View becomes GONE, it will be removed from the measuring of the RecyclerView's content and the new ViewHolder would be added.
I prefer to work careful with OnClickListener if any is set for the ViewHolder's content.
Below code will work for you. A little explanation: Extend RecyclerView and override onLayout() method. Once RecyclerView is ready iterate through all visible (on-screen) children of RecyclerView and apply your logic. In our case we'll draw BounddingBox for every nth child and RecyclerView. If child's bounds lie inside RecyclerView's bounds then show that child otherwise set visibility to GONE/INVISIBLE.
public class CustomRecyclerView extends RecyclerView {
Rect recyclerViewBounds = new Rect();
Rect currentChildViewBounds = new Rect();
public CustomRecyclerView(@NonNull Context context) {
super(context);
}
public CustomRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public CustomRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
recyclerViewBounds.set(l, t, r, b);
for (int i = 0; i < getChildCount(); i++) {
View currentChild = getChildAt(i);
currentChildViewBounds.set(currentChild.getLeft(), currentChild.getTop(), currentChild.getRight(), currentChild.getBottom());
currentChild.setVisibility(recyclerViewBounds.contains(currentChildViewBounds) ? VISIBLE : GONE); // or INVISBLE instead of GONE
}
}
}
And most importantly: In your xml file use com.your.packagename.CustomRecyclerView instead of androidx.recyclerview.widget.RecyclerView.
NOTE: Please refrain from any object initialization inside onLayout(). What I mean is don't move the object initializations inside onLayout() to make it "fancier".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With