{"id":28494526,"url":"https://github.com/ingenuity-ph/android-tableview-kotlin","last_synced_at":"2025-07-08T14:31:37.807Z","repository":{"id":134905232,"uuid":"123251675","full_name":"ingenuity-ph/android-tableview-kotlin","owner":"ingenuity-ph","description":"Android's missing TableView component.","archived":false,"fork":false,"pushed_at":"2019-10-30T11:07:41.000Z","size":6187,"stargazers_count":46,"open_issues_count":7,"forks_count":13,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-06-08T10:06:56.689Z","etag":null,"topics":["android-development","android-library","android-ui","custom-view","gridview","kotlin","kotlin-android","kotlin-language","kotlin-library","recyclerview","sortabletableview","table","tableview","tableviewcell"],"latest_commit_sha":null,"homepage":null,"language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ingenuity-ph.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2018-02-28T08:11:59.000Z","updated_at":"2025-02-25T07:45:00.000Z","dependencies_parsed_at":null,"dependency_job_id":"2bcb7e6f-c6be-4e56-8833-2a6342f14b13","html_url":"https://github.com/ingenuity-ph/android-tableview-kotlin","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/ingenuity-ph/android-tableview-kotlin","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ingenuity-ph%2Fandroid-tableview-kotlin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ingenuity-ph%2Fandroid-tableview-kotlin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ingenuity-ph%2Fandroid-tableview-kotlin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ingenuity-ph%2Fandroid-tableview-kotlin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ingenuity-ph","download_url":"https://codeload.github.com/ingenuity-ph/android-tableview-kotlin/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ingenuity-ph%2Fandroid-tableview-kotlin/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264286301,"owners_count":23585043,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android-development","android-library","android-ui","custom-view","gridview","kotlin","kotlin-android","kotlin-language","kotlin-library","recyclerview","sortabletableview","table","tableview","tableviewcell"],"created_at":"2025-06-08T10:06:59.646Z","updated_at":"2025-07-08T14:31:37.794Z","avatar_url":"https://github.com/ingenuity-ph.png","language":"Kotlin","readme":"# Android TableView (Kotlin)\n\n##### _Android's missing TableView component._ \n\nThis Kotlin version is based on the original\n[TableView](https://github.com/evrencoskun/TableView) implementation by\n[Evren Coşkun](https://github.com/evrencoskun/). This component uses RecyclerViews for displaying\ncolumn headers, row headers and cells.\n\n\u003cp align=\"center\"\u003e\n    \u003cimg height=\"600\" src=\"https://github.com/ingenuity-ph/android-tableview-kotlin/blob/master/tableview-demo-v0.1.0-alpha.gif\"\u003e\n\u003c/p\u003e\n\n## Features\n\n- [x] Calculated fixed width based on the largest cell.\n- [x] Different ViewHolders for the headers and cells.\n- [x] Action listeners for interacting with the headers and cells.\n- [x] Visibility control for rows and columns.\n- [x] Sorting for column data.\n- [x] Filtering/query for data.\n- [x] Pagination functionality.\n\n## Latest version\n\nYou can check the [releases page](https://github.com/ingenuity-ph/android-tableview-kotlin/releases)\nfor the latest version and changelog.\n\n## Documentation\n- [Integration](#project-integration)\n- [Creating the TableView](#creating-the-tableview)\n- [Creating the TableViewAdapter](#creating-the-tableviewadapter)\n- [Setting the TableViewAdapter to the TableView](#setting-the-tableviewadapter-to-the-tableview)\n- [Setting an ActionListener to the TableView](#setting-an-actionlistener-to-the-tableview)\n- [Updating TableView data](#updating-tableview-data)\n- [Visibility controls](#tableview-visibility-controls)\n- [Advanced properties and methods](#tableview-advanced-properties-and-methods)\n- [Sorting](#sorting)\n- [Filtering](#filtering)\n- [Pagination](#pagination)\n- [Sample Applications](#sample-applications)\n- [Articles](#articles)\n- [Communication](#communication)\n- [Contributors](#contributors)\n- [License](#license)\n\n### Project integration\n\nTo use this library in your Android project, add this dependency line\n`implementation 'ph.ingenuity.tableview:tableview:0.1.0-alpha'`\nto your application's `build.gradle` file.\n\n```\n    dependencies {\n        implementation 'ph.ingenuity.tableview:tableview:0.1.0-alpha'\n    }\n```\n\n### 1. Creating the TableView\n\n#### Programmatically\n\n```kotlin\n    val tableView = TableView(context)\n```\n\n#### XML layout\n\n##### Basic\n\n```xml\n    \u003cph.ingenuity.tableview.TableView\n        android:id=\"@+id/table_view\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"/\u003e\n```\n\n##### Customized\n\n```xml\n    \u003cph.ingenuity.tableview.TableView\n        android:id=\"@+id/table_view\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        app:table_column_header_height=\"@dimen/default_column_header_height\"\n        app:table_row_header_width=\"@dimen/row_header_width\"\n        app:table_selected_color=\"@color/colorPrimary\"\n        app:table_separator_color=\"@color/colorAccent\"\n        app:table_shadow_color=\"@color/table_view_default_shadow_background_color\"\n        app:table_show_horizontal_separator=\"true\"\n        app:table_show_vertical_separator=\"true\"\n        app:table_unselected_color=\"@color/table_view_default_unselected_background_color\" /\u003e\n```\n\n```kotlin\n    val tableView = findViewById(R.id.table_view)\n```\n\n###### Customizable Attributes\n\n**Note:** To use these attributes on XML layout, the **xmlns:** namespace line\n`xmlns:app=\"http://schemas.android.com/apk/res-auto\"` should be added on the layout root view.\nOtherwise, Android Studio gives you compile error.\n\n- `table_column_header_height` - height of the column header\n- `table_row_header_width` - width of the row header\n- `table_selected_color` - color for selected cells\n- `table_separator_color` - separator color\n- `table_shadow_color` - shadow color\n- `table_show_horizontal_separator` - visibility control for horizontal separator\n- `table_show_vertical_separator` - visibility control for vertical separator\n- `table_unselected_color` - color for not selected cells\n\n### 2. Creating the TableViewAdapter\n\nA custom TableViewAdapter must be created to handle the ViewHolders for the column header, row\nheader and cells. Since this library uses `RecyclerView` component, `onCreateViewHolder` and\n`onBindViewHolder` methods are called for the column header, row header and cells. The custom\nTableViewAdapter should extend the `AbstractTableAdapter` class. Also create your `ViewHolder`\nclasses to extend `AbstractViewHolder` class.\n\n###### Example TableViewAdapter\n\n```kotlin\n    class RandomDataTableViewAdapter(\n        private val context: Context\n    ) : AbstractTableAdapter(context) {\n    \n        override fun getColumnHeaderItemViewType(column: Int): Int = 0\n    \n        override fun getRowHeaderItemViewType(row: Int): Int = 0\n    \n        override fun getCellItemViewType(column: Int): Int = 0\n    \n        override fun onCreateCellViewHolder(\n                parent: ViewGroup,\n                viewType: Int\n        ): RecyclerView.ViewHolder {\n            val cellView = LayoutInflater.from(context).inflate(\n                    // Replace this with your cell view layout\n                    R.layout.table_cell_text_data,\n                    parent,\n                    false\n            )\n    \n            return RandomDataCellViewHolder(cellView)\n        }\n    \n        override fun onBindCellViewHolder(\n                holder: AbstractViewHolder,\n                cellItem: Any,\n                column: Int,\n                row: Int\n        ) {\n            val cell = cellItem as RandomDataCell\n            val cellViewHolder = holder as RandomDataCellViewHolder\n            cellViewHolder.cellTextView.text = cell.content.toString()\n        }\n    \n        override fun onCreateColumnHeaderViewHolder(\n                parent: ViewGroup,\n                viewType: Int\n        ): RecyclerView.ViewHolder {\n            val columnHeaderView = LayoutInflater.from(context).inflate(\n                    // Replace this with your column header view layout\n                    R.layout.table_column_header_text_data,\n                    parent,\n                    false\n            )\n    \n            return RandomDataColumnHeaderViewHolder(columnHeaderView)\n        }\n    \n        override fun onBindColumnHeaderViewHolder(\n                holder: AbstractViewHolder,\n                columnHeaderItem: Any,\n                column: Int\n        ) {\n            val columnHeaderCell = columnHeaderItem as RandomDataCell\n            val columnHeaderViewHolder = holder as RandomDataColumnHeaderViewHolder\n            columnHeaderViewHolder.cellTextView.text = columnHeaderCell.content.toString()\n        }\n    \n        override fun onCreateRowHeaderViewHolder(\n                parent: ViewGroup,\n                viewType: Int\n        ): RecyclerView.ViewHolder {\n            val rowHeaderView = LayoutInflater.from(context).inflate(\n                    // Replace this with your row header view layout\n                    R.layout.table_row_header_text_data,\n                    parent,\n                    false\n            )\n    \n            return RandomDataRowHeaderViewHolder(rowHeaderView)\n        }\n    \n        override fun onBindRowHeaderViewHolder(\n                holder: AbstractViewHolder,\n                rowHeaderItem: Any,\n                row: Int\n        ) {\n            val rowHeaderCell = rowHeaderItem as RandomDataCell\n            val rowHeaderViewHolder = holder as RandomDataRowHeaderViewHolder\n            rowHeaderViewHolder.cellTextView.text = rowHeaderCell.content.toString()\n        }\n    \n        override fun onCreateCornerView(): View? {\n            // Replace this with your corner view layout\n            val cornerView = LayoutInflater.from(context).inflate(R.layout.table_corner_view, null)\n            cornerView.setOnClickListener {\n                Toast.makeText(context, \"CornerView has been clicked.\", Toast.LENGTH_SHORT).show()\n            }\n    \n            return cornerView\n        }\n        \n        class RandomDataCellViewHolder(itemView: View) : AbstractViewHolder(itemView) {\n            val cellTextView: TextView\n                get() = itemView.findViewById(R.id.random_data_cell_data)\n        }\n        \n        class RandomDataColumnHeaderViewHolder(itemView: View) : AbstractViewHolder(itemView) {\n            val cellTextView: TextView\n                get() = itemView.findViewById(R.id.column_header_text)\n        }\n        \n        class RandomDataRowHeaderViewHolder(itemView: View) : AbstractViewHolder(itemView) {\n            val cellTextView: TextView\n                get() = itemView.findViewById(R.id.row_header_text)\n        }\n    }\n```\n\n### 3. Setting the TableViewAdapter to the TableView\n\n`AbstractTableAdapter` class requires three lists for the column header, row header and cell items.\n\n```kotlin\n    // Retrieve your data from local storage or API\n    val cellsList = randomDataFactory.randomCellsList as List\u003cList\u003cAny\u003e\u003e\n    val rowHeadersList = randomDataFactory.randomRowHeadersList as List\u003cAny\u003e\n    val columnHeadersList = randomDataFactory.randomColumnHeadersList as List\u003cAny\u003e\n            \n    // Create an instance of our custom TableViewAdapter\n    val tableAdapter = RandomDataTableViewAdapter(mainView!!.context)\n    \n    // Set the adapter to the created TableView\n    tableView.adapter = tableAdapter\n    \n    // Set the data to the adapter\n    tableAdapter.setAllItems(cellsList, columnHeadersList, rowHeadersList)\n```\n\n### 4. Setting an ActionListener to the TableView\n\nA custom TableViewListener must be created to handle column header, row header and\ncell click and long pressed actions. The custom TableViewListener must implement the\n`ITableViewListener` interface.\n\n###### Example TableViewListener\n\n```kotlin\n    class TableViewListener(private val tableView: TableView) : ITableViewListener {\n    \n        private var toast: Toast? = null\n    \n        private val context: Context = tableView.context\n    \n        override fun onCellClicked(cellView: RecyclerView.ViewHolder, column: Int, row: Int) {\n            showToast(\"Cell $column $row has been clicked.\")\n        }\n    \n        override fun onCellLongPressed(cellView: RecyclerView.ViewHolder, column: Int, row: Int) {\n            showToast(\"Cell $column, $row has been long pressed.\")\n        }\n    \n        override fun onColumnHeaderClicked(columnHeaderView: RecyclerView.ViewHolder, column: Int) {\n            showToast(\"Column header $column has been clicked.\")\n        }\n    \n        override fun onColumnHeaderLongPressed(\n            columnHeaderView: RecyclerView.ViewHolder, \n            column: Int\n        ) {\n            if (columnHeaderView is RandomDataColumnHeaderViewHolder) {\n                val popup = ColumnHeaderLongPressPopup(columnHeaderView, tableView)\n                popup.show()\n            }\n        }\n    \n        override fun onRowHeaderClicked(rowHeaderView: RecyclerView.ViewHolder, row: Int) {\n            showToast(\"Row header $row has been clicked.\")\n        }\n    \n        override fun onRowHeaderLongPressed(rowHeaderView: RecyclerView.ViewHolder, row: Int) {\n            if (rowHeaderView is RandomDataRowHeaderViewHolder) {\n                val popup = RowHeaderLongPressPopup(rowHeaderView, tableView)\n                popup.show()\n            }\n        }\n    \n        private fun showToast(message: String) {\n            if (toast == null) {\n                toast = Toast.makeText(context, message, Toast.LENGTH_SHORT)\n            }\n    \n            toast!!.setText(message)\n            toast!!.show()\n        }\n    }\n```\n\n###### Setting the TableViewListener to the TableView\n\n```kotlin\n    tableView.tableViewListener = TableViewListener(tableView)\n```\n\n\u003e By now, we should have a working TableView with displayed data and action listeners.\nThe next sections are for some TableView features such as changing data sets, hiding/showing\ncolumns and rows and scrolling to position, as well as advanced features such as\nsorting, filtering and pagination.\n\n### Updating TableView data\n\nThe data set in the TableView can be updated by updating the TableViewAdapter.\n\n- To **add a row**:\n\n```kotlin\n    tableView.adapter.addRow(position, rowHeaderItem, cellItems)\n```\n\n- To **add a multiple rows**:\n\n```kotlin\n    tableView.adapter.addRowRange(position, rowHeaderItems, cellItems)\n```\n\n- To **remove a row**:\n\n```kotlin\n    tableView.adapter.removeRow(position)\n``` \n\n- To **remove multiple rows**:\n\n```kotlin\n    tableView.adapter.removeRow(position, count)\n``` \n\n- To **update a row header**:\n\n```kotlin\n    tableView.adapter.changeRowHeaderItem(position, rowHeaderItem)\n```\n\n- To **update multiple row headers**:\n\n```kotlin\n    tableView.adapter.changeRowHeaderItemRange(position, rowHeaderItems)\n``` \n\n- To **update a column header**:\n\n```kotlin\n    tableView.adapter.changeColumnHeader(position, columnHeaderItem)\n```\n\n- To **update multiple column headers**:\n\n```kotlin\n    tableView.adapter.changeColumnHeaderRange(position, columnHeaderItems)\n``` \n\n- To **update a cell item**:\n\n```kotlin\n    tableView.adapter.changeCellItem(column, row, cellItem)\n``` \n\n### TableView visibility controls\n\nThe visibility of the the rows and columns in the TableView can be controlled using the visibility\ncontrols in the TableView instance.\n\n- To **show** a row:\n\n```kotlin\n    tableView.showRow(row)\n```\n\n- To **hide** the row:\n\n```kotlin\n    tableView.hideRow(row)\n```\n\n- To **show all hidden** rows:\n\n```kotlin\n    tableView.showAllHiddenRows()\n```\n\n- TableView store a map that contains all hidden rows.\nThis method will **clear the list of hidden rows**:\n\n```kotlin\n    tableView.clearHiddenRowList()\n```\n\n- To **check the visibility state** of a row:\n\n```kotlin\n    tableView.isRowVisible(row)\n```\n\n- To **show** a column:\n\n```kotlin\n    tableView.showColumn(column)\n```\n\n- To **hide** a column:\n\n```kotlin\n    tableView.hideColumn(column)\n```\n\n- To **show all hidden** columns\n\n```kotlin\n    tableView.showAllHiddenColumns()\n```\n\n- TableView store a map that contains all hidden columns.\nThis method will **clear the list of hidden columns**:\n\n```kotlin\n    tableView.clearHiddenColumnList()\n```\n\n- To **check the visibility state** of a column:\n\n```kotlin\n    tableView.isColumnVisible(column)\n```\n\n### TableView advanced properties and methods\n\n- To recalculate column width:\n\n```kotlin\n    tableView.remeasureColumnWidth(column)\n``` \n\n- To ignore column width calculation for better performance:\n  \n```kotlin\n    tableView.hasFixedWidth = false\n``` \n\n- To ignore setting selection colors that are displayed by user interaction:\n\n```kotlin\n    tableView.ignoreSelectionColors = false\n``` \n\n- To show or hide separators of the TableView:\n\n```kotlin\n    tableView.showHorizontalSeparators = Boolean\n```\n\n```kotlin\n    tableView.showVerticalSeparators = Boolean\n```\n\n- To programmatically scroll to a row or column position:\n\n```kotlin\n    tableView.scrollToColumn(column)\n```\n\n```kotlin\n    tableView.scrollToRow(row)\n```\n\n### Sorting\n\n\u003e **Sorting**, by definition and usage in this context is the rearrangement of values in a data set\naccording to a property in ascending or descending manner.\n\n#### Implementation\n\nTo use this feature in the TableView, the `Sortable` interface must be implemented in the data\nclasses or the models. The `Sortable` interface requires you to provide a unique `id` and\n`content` value for your data. Sorting can be done on the following data types:\n\n- **Number**\n- **String**\n- **Date**\n- **Boolean**\n- **Comparable**\n\n###### Example data class implementing `Sortable` interface\n\n```kotlin\n    class RandomDataCell(\n            _data: Any,\n            _id: String = _data.hashCode().toString()\n    ) : Sortable {\n        \n        override var id: String = _id\n    \n        override var content: Any = _data\n    }\n```\n\n###### Sorting controls\n\n- To **sort the TableView according to a specified column**:\n\n```kotlin\n    tableView.sortColumn(column, sortState)\n```\n\n- To **get the current sorting state of a column**:\n\n```kotlin\n    tableView.getColumnSortState(column)\n```\n\n###### Sorting states\n\n- `SortState.ASCENDING`\n- `SortState.DESCENDING`\n- `SortState.UNSORTED`\n\n###### Sorting state updates\n\nListening to sorting state changes can be done by implementing the `AbstractSorterViewHolder`\ninterface to your `ColumnHeaderViewHolder` class.\n\n- This method is called after every sorting process:\n\n```kotlin\n    onSortingStatusChanged(SortState sortState) {\n        // do something here...\n    }\n```\n\n- To get the sort state of a column header, just access the `sortState` object:\n\n```kotlin\n    columnHeaderViewHolder.sortState\n```\n\n### Filtering\n\n\u003e **Filtering**, by definition and usage in this context, is displaying a subset of data into the\nTableView based on a given filter globally. on a specified column or combination.\n\n#### Implementation\n\nTo use this feature in the TableView, the `Filterable` interface must be implemented in the data\nclasses or the models. The `Filterable` interface requires you to provide a unique\n`filterableKeyword` string value for your data. This `filterableKeyword` will be used for filtering\nthe cell data based on a filter query.\n\n###### Example data class implementing `Filterable` interface\n\n```kotlin\n    class RandomDataCell(\n            _filter: String = _data.toString()\n    ) : Filterable {\n    \n        override var filterableKeyword: String = _filter\n    }\n```\n\n###### Creating an instance of the `Filter` class\n\nAn instance of the `Filter` class must be created and pass the TableView to be filtered.\n\n```kotlin\n    private lateinit var filter: Filter\n    \n    initialize() {\n        setUpTableView()\n        filter = Filter(tableView)\n    }\n```\n\n###### Filtering process\n\nFiltering can be done by calling the `set()` method of the `Filter` instance which can be used to\nfilter the whole tabele data, a column or combination. Clearing a filter can be simply done by\npassing an **empty** string as filterKeyword (`\"\"` and not `null`).\n\n```kotlin\n    // filtering whole table data\n    fun filterWholeTable(filterKeyword: String) = filter.set(filterKeyword)\n    \n    // filtering a specific column\n    fun filterThisColumn(column: Int, filterKeyword: String) = filter.set(column, filterKeyword)\n    \n    // clear filter for whole table\n    fun clearTableFilter() = filter.set(\"\")\n    \n    // clear filter for a specific column\n    fun clearFilterForThisColumn(column: Int) = filter.set(column, \"\")\n```\n\n###### Adding a `FilterChangedListener`\n\nA `FilterChangedListener` object can be added to the TableView for handling data changes during\nfiltering process.\n\n```kotlin\n    private val filterChangedListener = object : FilterChangedListener {\n\n        fun onFilterChanged(\n            filteredCellItems: List\u003cList\u003cAny\u003e\u003e,\n            filteredRowHeaderItems: List\u003cAny\u003e\n        ) {\n            // do something here...\n        }\n\n        fun onFilterCleared(\n            originalCellItems: List\u003cList\u003cAny\u003e\u003e,\n            originalRowHeaderItems: List\u003cAny\u003e\n        ) {\n            // do something here...\n        }\n    }\n    \n    initialize() {\n        setUpTableView()\n        filter = Filter(tableView)\n        tableView.filterHandler.addFilterChangedListener(filterChangedListener)\n    }\n```\n\n### Pagination\n\n\u003e **Pagination**, by definition and usage in this context, is the division of the whole set of data\ninto subsets called pages and loading the data into the TableView page-by-page and not the whole\ndata directly. This is useful if you have a large amount of data to be displayed.\n\n#### Implementation\n\n###### Creating views to control the Pagination\n\n_Depending on your preference, you may not follow the following and create your own implementation._\n1. Create a layout with the following components: Two **Button** views to control next and\nprevious page, a **Spinner** if you want to have a customized number of pagination\n(e.g. 10, 20, 50, All), an **EditText** to have a user input on which page s/he wants to go to,\na **TextView** to display details (e.g. _Showing page X, items Y-Z_).\n2. Assign the views with the controls and methods which are discussed below.\n\n###### Creating an instance of the `Pagination` class\n\n- The `Pagination` class has three possible constructors: (1) passing the `TableView` instance only,\n(2) `TableView` and the initial `ITEMS_PER_PAGE` and (3) `TableView`, initial `ITEMS_PER_PAGE` and\nthe `OnTableViewPageTurnedListener`. By default, if no ITEMS_PER_PAGE specified, the TableView will\nbe paginated into **10** items per page.\n\n```kotlin\n    private lateinit var pagination: Pagination\n    \n    initialize() {\n        setUpTableView()\n        pagination = Pagination(tableView)\n    }\n```\n\n- **Loading the next page of items** into the TableView using the `loadNextPage()` method.\nYou can assign this to your implementation of nextPageButton onClick action:\n\n```kotlin\n    fun nextTablePage() = pagination.loadNextPage()\n```\n\n- **Loading the previous page of items** into the TableView using the `loadPreviousPage()` method.\nYou can assign this to your implementation of previousPageButton onClick action:\n\n```kotlin\n    fun previousTablePage() = pagination.loadPreviousPage()\n```\n\n- You can navigate through the pages by **going to a specific page directly** using the\n`loadPage(page: Int)` method. You can assign this to the EditText field TextChanged\naction (using TextWatcher):\n\n```kotlin\n    fun loadTablePage(page: Int) = pagination.loadPage(page)\n```\n\n- You can customize and **set the number of items to be displayed per page** of the TableView\nusing the `itemsPerPage` property of the pagination. You can assign this to your Spinner\nwith the number of items per page list:\n\n```kotlin\n    fun setTableItemsPerPage(numItems: Int) {\n        pagination.itemsPerPage = numItems\n    }\n```\n\n###### Adding an `OnTableViewPageTurnedListener`\n\n- A listener interface (**Pagination.OnTableViewPageTurnedListener**) can also be implemented\nif you want to do something each time _a page is turned_ (e.g. previous, next, goToPage or\nchange items per page action is called):\n\n```kotlin\n    private val onTableViewPageTurnedListener =\n            object : Pagination.OnTableViewPageTurnedListener {\n            \n                override fun onPageTurned(numItems: Int, itemsStart: Int, itemsEnd: Int) {\n                    // do something here...\n                }\n            }\n    \n    initialize() {\n        setUpTableView()\n        pagination = Pagination(tableView)\n        pagination.onTableViewPageTurnedListener = onTableViewPageTurnedListener\n    }\n```\n\n## Sample Applications\n\n- This repository contains a Kotlin demo application implementing the TableView library.\n- [Contact me](mailto:jeremy@ingenuity.ph) if you want your app to be listed here.\n\n## Articles\n\n- [TODO](TODO)\n\n## Communication\n\n- If you **need help**, please use\n[Stack Overflow](https://stackoverflow.com/questions/tagged/tableview+android+kotlin).\n(Tag 'TableView', 'Android', 'Kotlin')\n- If you'd like to **ask a general question**, please use\n[Stack Overflow](https://stackoverflow.com/questions/tagged/tableview+android+kotlin).\n- If you **found a bug**, please open an issue.\n- If you **have a feature request**, please open an issue.\n- If you **want to contribute**, please submit a pull request.\n- You can [contact me](mailto:jeremy@ingenuity.ph) if you want to discuss privately.\n\n## Contributors\n\n**Original author, idea, implementation and code** by\n[Evren Coşkun](https://github.com/evrencoskun/).\n\nContributions of any kind are welcome!\n\n## License\n\n    Copyright 2018 Jeremy Patrick Pacabis\n    Copyright 2017-2018 Evren Coşkun\n    \n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n    \n    The above copyright notice and this permission notice shall be included in all\n    copies or substantial portions of the Software.\n    \n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n    SOFTWARE.","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fingenuity-ph%2Fandroid-tableview-kotlin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fingenuity-ph%2Fandroid-tableview-kotlin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fingenuity-ph%2Fandroid-tableview-kotlin/lists"}