1 /* 2 * Copyright 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package androidx.compose.foundation.lazy.grid 18 19 import androidx.compose.foundation.gestures.Orientation 20 import androidx.compose.ui.unit.IntSize 21 import kotlin.math.max 22 23 /** 24 * Contains useful information about the currently displayed layout state of lazy grids like 25 * [LazyVerticalGrid]. For example you can get the list of currently displayed items. 26 * 27 * Use [LazyGridState.layoutInfo] to retrieve this 28 */ 29 sealed interface LazyGridLayoutInfo { 30 /** The list of [LazyGridItemInfo] representing all the currently visible items. */ 31 val visibleItemsInfo: List<LazyGridItemInfo> 32 33 /** 34 * The start offset of the layout's viewport in pixels. You can think of it as a minimum offset 35 * which would be visible. Usually it is 0, but it can be negative if non-zero 36 * [beforeContentPadding] was applied as the content displayed in the content padding area is 37 * still visible. 38 * 39 * You can use it to understand what items from [visibleItemsInfo] are fully visible. 40 */ 41 val viewportStartOffset: Int 42 43 /** 44 * The end offset of the layout's viewport in pixels. You can think of it as a maximum offset 45 * which would be visible. It is the size of the lazy grid layout minus [beforeContentPadding]. 46 * 47 * You can use it to understand what items from [visibleItemsInfo] are fully visible. 48 */ 49 val viewportEndOffset: Int 50 51 /** The total count of items passed to [LazyVerticalGrid]. */ 52 val totalItemsCount: Int 53 54 /** 55 * The size of the viewport in pixels. It is the lazy grid layout size including all the content 56 * paddings. 57 */ 58 val viewportSize: IntSize 59 60 /** The orientation of the lazy grid. */ 61 val orientation: Orientation 62 63 /** True if the direction of scrolling and layout is reversed. */ 64 val reverseLayout: Boolean 65 66 /** 67 * The content padding in pixels applied before the first row/column in the direction of 68 * scrolling. For example it is a top content padding for LazyVerticalGrid with reverseLayout 69 * set to false. 70 */ 71 val beforeContentPadding: Int 72 73 /** 74 * The content padding in pixels applied after the last row/column in the direction of 75 * scrolling. For example it is a bottom content padding for LazyVerticalGrid with reverseLayout 76 * set to false. 77 */ 78 val afterContentPadding: Int 79 80 /** The spacing between lines in the direction of scrolling. */ 81 val mainAxisItemSpacing: Int 82 83 /** 84 * The max line span an item can occupy. This will be the number of columns in vertical grids or 85 * the number of rows in horizontal grids. 86 * 87 * For example if [LazyVerticalGrid] has 3 columns this value will be 3 for each cell. 88 */ 89 val maxSpan: Int 90 } 91 visibleLinesAverageMainAxisSizenull92internal fun LazyGridLayoutInfo.visibleLinesAverageMainAxisSize(): Int { 93 val isVertical = orientation == Orientation.Vertical 94 val visibleItems = visibleItemsInfo 95 fun lineOf(index: Int): Int = 96 if (isVertical) visibleItemsInfo[index].row else visibleItemsInfo[index].column 97 98 var totalLinesMainAxisSize = 0 99 var linesCount = 0 100 101 var lineStartIndex = 0 102 while (lineStartIndex < visibleItems.size) { 103 val currentLine = lineOf(lineStartIndex) 104 if (currentLine == -1) { 105 // Filter out exiting items. 106 ++lineStartIndex 107 continue 108 } 109 110 var lineMainAxisSize = 0 111 var lineEndIndex = lineStartIndex 112 while (lineEndIndex < visibleItems.size && lineOf(lineEndIndex) == currentLine) { 113 lineMainAxisSize = 114 max( 115 lineMainAxisSize, 116 if (isVertical) { 117 visibleItems[lineEndIndex].size.height 118 } else { 119 visibleItems[lineEndIndex].size.width 120 } 121 ) 122 ++lineEndIndex 123 } 124 125 totalLinesMainAxisSize += lineMainAxisSize 126 ++linesCount 127 128 lineStartIndex = lineEndIndex 129 } 130 131 return totalLinesMainAxisSize / linesCount + mainAxisItemSpacing 132 } 133 134 internal val LazyGridLayoutInfo.singleAxisViewportSize: Int 135 get() = if (orientation == Orientation.Vertical) viewportSize.height else viewportSize.width 136