I have a GridView
that has items inside 5x50.
I need to scroll them in all directions and instead of stopping when reached the end just start from the top/left.
for example left-to-right scroll
before scroll
1 2 3 4 5
6 7 8 9 10
after scroll to the right
5 1 2 3 4
10 6 7 8 9
and for top-to-bottom (or bottom-to-top)
before scroll to the bottom
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
after scroll
6 7 8 9 10
11 12 13 14 15
1 2 3 4 5
I try to make it smooth scroll as GridView
native scroll.
Having specified following view hierarchy in activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
And a basic list item - a TextView
, inside item.xml
:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"/>
Then in the activity:
public class MainActivity extends AppCompatActivity {
private static final int spanCount = 5;
private static final int totalItemCount = 15;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RecyclerView recyclerView = findViewById(R.id.recycler);
// Shamelessly stolen from devunwired bit.ly/2yCqVIp
recyclerView.addItemDecoration(new GridDividerDecoration(this));
recyclerView.setLayoutManager(new GridLayoutManager(this, spanCount, LinearLayoutManager.VERTICAL, false));
recyclerView.setAdapter(new MyAdapter(totalItemCount));
}
static class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {
private final int totalSizeOfItems;
private boolean hasBeenSetup = false;
MyAdapter(int totalSizeOfItems) {
this.totalSizeOfItems = totalSizeOfItems;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
final int cellSize = parent.getMeasuredWidth() / spanCount;
view.setMinimumWidth(cellSize);
view.setMinimumHeight(cellSize);
setupRecyclerHeightIfNeeded(parent, cellSize);
return new MyViewHolder(view);
}
// We need to perform this operation once, not each time `onCreateViewHolder` is called
private void setupRecyclerHeightIfNeeded(View parent, int cellSize) {
if (hasBeenSetup) return;
hasBeenSetup = true;
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) parent.getLayoutParams();
int numOfRows = (int) (totalItemCount / (double) spanCount);
params.height = numOfRows * cellSize;
new Handler().post(parent::requestLayout);
}
@Override
public void onBindViewHolder(MyViewHolder holder, int pos) {
int position = holder.getAdapterPosition() % totalSizeOfItems;
holder.textView.setText(Integer.toString(position + 1));
}
@Override
public int getItemCount() {
// this will result the list to be "infinite"
return Integer.MAX_VALUE;
}
}
static class MyViewHolder extends RecyclerView.ViewHolder {
TextView textView;
MyViewHolder(View itemView) {
super(itemView);
textView = (TextView) itemView;
}
}
}
On output you'll get:
Taking care of the horizontal scroll would require a small amount of changes:
GridLayoutManager
should be changed to HORIZONTAL
Other than that - everything should be similar.
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