Page Size
Chooses how many rows a page of a list shows: the words "Per page" and, beside them, a select of sizes.
import com.pantrixui.components.data.pagination.PantrixPageSize
- Numbers and gaps. The first and the last
boundaryCountpages are shown, andsiblingCountpages on each side of the page on screen; those between them fold into a gap of three dots. Each is one unless given. A gap stands for two pages at the least: where a single page is left in between, that page itself is shown. Once there are enough pages to fold, the row has as many items whichever page is on screen: near an end, more pages stand on that side. - In a narrow place. A row too narrow for its numbers folds step by step: first it shows fewer pages beside the page on screen, as many as fit; if that does not fit either, fewer pages at its ends, down to one. Where no row of numbers fits it is laid out as previous, "Page 3 of 10" and next. The room is asked for the page on which the row is widest: the row folds the same way on every page, and its layout does not change as the page moves. How it is laid out is decided by the width left to the row, not by the window.
PaginationLayout.Compactasks for the short row at every width. In a place narrower even than its buttons the short row is drawn smaller: its buttons are not cut. - First and last page.
firstAndLast = trueputs one more button outside previous and outside next: one goes to the first page, the other to the last. On the first page the two buttons at the start cannot be pressed, nor the two at the end on the last page. Four buttons leave less room for the numbers. - The page on screen. It is told by its fill and is no button: a press on it reports nothing.
- The ends. Previous cannot be pressed on the first page, nor next on the last. A
pageoutside the pages is taken as the nearest page. ApageCountunder one is taken as one: a list with nothing in it has one page, an empty one, and the row's arrows cannot be pressed. - A row that cannot be pressed.
enabled = falseturns the whole row off: no part of it can be pressed, and the row is drawn in the theme's disabled colours. If the row is turned off while a keyboard's focus is on one of its parts, the focus stays there; when the row is turned on again, the keyboard goes on from where it was. - Sizes.
PaginationStyle.itemSizeis the size of a number, of previous and of next: 40dp on Android, 36dp on iOS, 32dp on desktop and the web. A number too long for it makes its item wider; the icon of previous and of next is 4dp more than half the item.itemShapegives the corners: fully round on Android and iOS, small on desktop and the web.itemGapis the room between two neighbours, and follows the density. The platform's touch target is kept free around every item; the row is as wide as its items, and at least as tall as that target. - Type.
textStyleis the text style of the numbers and of the short row's words, the theme'slabelstyle unless given. A style that makes an item larger does not make its text larger: a large item is given a large type too. - Digits. The numbers, the numbers in the short row's words and the numbers in the names said to a screen reader are written in the digits of the theme's language (
PantrixStrings.digits): in Arabic digits in the Arabic pack.onPageChangereports the same number in every language. - Colours.
PaginationColorspaints the numbers and the short row's words (content), previous, next and the gaps' marks (control), and the fill and the number of the page on screen (selectedContainer,selectedContent) one by one. On a fill, all of a row that is given no colour is in the colour that is written on the fill; the page on screen is told by its fill, a share of that colour. - Right to left. In languages read from right to left the row starts on the right, and the arrows turn round.
- Page size.
PantrixPageSizeis the words "Per page" and, beside them, a select of sizes. The size that is chosen is its caller's: it is given withpageSize, and when another size is chosen it is reported throughonPageSizeChange; choosing the chosen size again reports nothing. The sizes are 10, 25, 50 and 100 unless given (DefaultPageSizes);pageSizesgives others. ApageSizethat is none of the sizes is shown as chosen too, and stands in the list before the first size larger than itself. The select is as wide as the longest size needs: the row stands still as the choice changes. - Go to page.
PantrixPageJumpis the words "Go to page" and, beside them, a short field. Enter, or the action of a keyboard on the screen, reports the page that was typed throughonPageChangeand empties the field; the focus stays in the field. A number outside the pages is taken as the nearest page; an empty field reports nothing. The field takes digits alone, the Western ones and those of the theme's language, and holds as many digits as the last page's number has. - The companions' words. In both the words stand before the control, on the side where the row starts, and are for the eye: a screen reader is given one control, named by those words.
labelchanges the words. In a narrow place the words give way and the control does not.enabled = falsewrites the words in the disabled text colour and turns the control off. - Automation. A row given a
tagKeyisPagination_<tagKey>, and its parts are named inside it:Pagination_orders.Page_4,Pagination_orders.Step_previous,Pagination_orders.Step_next,Pagination_orders.Step_first,Pagination_orders.Step_last, and the short row's wordsPagination_orders.Text_position. Every page that is asked for is reported asselect, with its number and with what asked for it (page,previous,next,first,last). The companions arePageSize_<tagKey>andPageJump_<tagKey>; the select in one carries the tagSelect_<tagKey>_page_size, the field in the otherTextField_<tagKey>_page_jump.
Examples
In a table's foot: page size and go to page
A table's foot: PantrixPageSize chooses how many orders a page shows, PantrixPagination moves between the pages, and PantrixPageJump goes to the page whose number is typed. The three are in a FlowRow: where there is room they stand side by side, and in a narrow place the one that does not fit goes down to the next line; on a phone held upright the three stand one under another. A Row does not take what does not fit down a line: it squeezes the last one into the room that is left. The three may not be the same height: itemVerticalAlignment lines them up by their middles.
All three read the screen's state, and none knows of the others. Change the page size: forty-eight orders make sixteen pages three at a time, and five pages ten at a time; the row's numbers and the number of digits the field takes follow the new number of pages. As the size changes the first order shown stays on screen: the page that is opened is the one that order falls on at the new size. On the fourth page, with orders 16–20 shown, choose 10: the second page comes, orders 11–20. For forty-eight orders the sizes are small: 3 and 5, before the first of the ready sizes (DefaultPageSizes), 10.
Type a number in the field and press Enter: that page is opened, the field is emptied and the focus stays in the field. A number larger than the last page opens the last page; the field takes nothing but digits. The page that was asked for, whatever asked for it, is written on the card's "Last event" line.
val report = LocalExampleEvents.current
var pageSize by rememberSaveable { mutableIntStateOf(ORDERS_PER_PAGE) }
var page by rememberSaveable { mutableIntStateOf(1) }
val pageCount = (ORDER_COUNT + pageSize - 1) / pageSize
val first = (page - 1) * pageSize + 1
val last = minOf(page * pageSize, ORDER_COUNT)
val open: (Int) -> Unit = { asked ->
page = asked
report("Page $asked was asked for")
}
OrderRows(first = first, last = last, rows = pageSize, tagKey = "row")
PantrixText(
text = "$first–$last of $ORDER_COUNT orders",
color = PantrixTheme.colors.textSecondary,
tagKey = "foot_shown"
)
FlowRow(
horizontalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.lg),
verticalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.sm),
itemVerticalAlignment = Alignment.CenterVertically
) {
PantrixPageSize(
pageSize = pageSize,
onPageSizeChange = { size ->
// The page that is opened is the one the first order shown falls on at the new size: the order stays on screen.
val kept = (first - 1) / size + 1
pageSize = size
page = kept
report("$size orders to a page: page $kept was opened")
},
pageSizes = listOf(3, 5) + DefaultPageSizes.first(),
tagKey = "foot"
)
PantrixPagination(page = page, pageCount = pageCount, onPageChange = open, tagKey = "foot")
PantrixPageJump(pageCount = pageCount, onPageChange = open, tagKey = "foot")
}
@Composable
private fun OrderRows(
first: Int,
last: Int,
rows: Int,
tagKey: String
) {
PantrixSurface(modifier = Modifier.fillMaxWidth(), border = PantrixTheme.colors.divider) {
Column {
for (order in first until first + rows) {
val listed = order <= last
// The line of an empty row keeps its place too, but is not drawn.
val line = if (listed) Color.Unspecified else Color.Transparent
if (order > first) PantrixHorizontalDivider(color = line)
Row(
modifier = Modifier.fillMaxWidth().padding(PantrixTheme.spacing.md),
horizontalArrangement = Arrangement.SpaceBetween
) {
if (listed) {
PantrixText(text = "Order #${FIRST_ORDER + order}", tagKey = "${tagKey}_$order")
PantrixText(text = "Items: ${1 + order % 4}", color = PantrixTheme.colors.textSecondary)
} else {
// An empty text is a line tall too; it has nothing to say to a screen reader.
PantrixText(text = "", role = TextRole.Decorative)
}
}
}
}
}
}
private const val ORDER_COUNT = 48
private const val ORDERS_PER_PAGE = 5
private const val FIRST_ORDER = 4800
API
pageSize
Chooses how many rows a page of a list shows: the words "Per page" and, beside them, a select of sizes.
| Parameter | Type | Default | What it is |
|---|---|---|---|
pageSize | Int | how many rows a page shows now. | |
onPageSizeChange | (pageSize: Int) -> Unit | told the size that was chosen, where it is another than pageSize. The select shows it once pageSize says so. | |
modifier | Modifier | Modifier | applied to the row. |
pageSizes | List<Int> | DefaultPageSizes | the sizes to choose from, in the order they are listed: DefaultPageSizes unless given. A size given twice is listed once. There is one at the least, and each is a row or more: a list that is empty or holds a number under one is refused. |
label | String | PantrixTheme.strings.perPage | the words before the select, and the select's name for a screen reader: the theme's "Per page" unless given. |
enabled | Boolean | true | whether a size can be chosen: a row that cannot be used has its words in the disabled text colour and a select that is disabled, which takes no focus and says so. |
tagKey | String? | null | a locale-independent key for automation: the row's tag is PageSize_<tagKey> and its words are PageSize_<tagKey>.Text_label. The select in it has the key <tagKey>_page_size, and is tagged as a select is: Select_<tagKey>_page_size, its list SelectList_<tagKey>_page_size, and a size in the list Select_<tagKey>_page_size.SelectOption_<size>. A key too long for a tag is cut, and _page_size is kept whole. A choice is reported as PageSize, with the size. That the list of sizes opened is reported as PageSize too, with the row's tag: the row is one component, and reports under one name. |
Accessibility
- Keyboard. The numbers and the arrows are each a stop for Tab; Enter and Space press them. The page on screen is a stop too, and keeps the focus a keyboard put on it: on a page opened by the keyboard the focus stays where it is. When the row comes to one of its ends, the page on screen takes the focus of the button that can no longer be pressed; in the short row the button on the other side takes it.
- Screen reader. A number is a button named by the page it opens: "Page 4". The page on screen is no button and offers the reader nothing to press: it is read with the state "Current page". The gaps are not read. The buttons that go to the first and the last page are named "First page" and "Last page". The short row's words are told to the reader each time they change. The row is a group named "Pagination". On iOS the group has no name: the reader there reads a group's name after what it holds.