Search code examples
androidgridviewpaginationhomescreenresizable

Android: Home screen with different element sizes, resizable, draggable and horizontal pagination


I am developing a new App which is going to have a home screen as grid 2 x 4. Every item can be resizable to 2 (1x2) or 4 (2x2) cells when there is room available. The grid must also contain empty spaces so other elements can be resized. Let's say you might have only 6 items and 2 spaces should be shown as blank. To change the item's position, it can be dragged and dropped to the desired location, also this should work with pagination, so it can be dragged to another page and dropped there or swapped with some item of that corresponding page. More or less like it is the home screen of Android with all the icons on it that can be dragged and placed to other page. I am not sure if I must use any kind of RecyclerView or handle manually every view, but still not sure how this should be done? Please check the mock up below for a reference how it should look like. Home Screen Mockup


Solution

  • For that, I would use a RecyclerView with a GridLayoutManager and set the cell sizes with a GridLayoutManager.SpanSizeLookup.

    By doing that you also enable the use of ItemTouchHelper that comes with the RecyclerView, to handle most of the drag'n'drop logic.

    (Also you should really provide code of any attempts you've made)

    Edit: Row spans

    As I see it, there are three ways to solve the row span problem

    1. Use a third party library
    2. Write your own LayoutManager
    3. Change the height of the item inside ´onBindViewHolder` (this is probably what I would do)
    // Some model class
    data class Item(value: String, rowSpan: Int, columnSpan: Int)
    
    // With this lookup to handle the columns
    val spanSizeLookup: GridLayoutManager.SpanSizeLookup = 
        object : GridLayoutManager.SpanSizeLookup() {
            override fun getSpanSize(position: Int) = items[position].columnSpan
        }
    
    // ...and this adapter that handles the height
    class Adapter : RecyclerView.Adapter() {
    
        // ...
    
        fun onBindViewHolder(holder: ViewHolder, position: Int) {
            val rows = items[position].rowSpan
            // Update height based on rows
        }
    }