### Create Individual Styles
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/xml.md
Examples of custom styles for horizontal and vertical DpadRecyclerView configurations.
```xml
```
--------------------------------
### Set Extra Layout Space Strategy
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/recipes/layout.md
Implement ExtraLayoutSpaceStrategy to define how extra layout space is calculated. This example adds half a page of extra space at the start for alignment purposes.
```kotlin
recyclerView.setExtraLayoutSpaceStrategy(object : ExtraLayoutSpaceStrategy {
override fun calculateStartExtraLayoutSpace(state: RecyclerView.State): Int {
return recyclerView.width / 2
}
})
```
--------------------------------
### Configure Start Alignment
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/recipes/alignment.md
Aligns items to the start of the container with a specific offset.
```xml
```
```kotlin
recyclerView.setParentAlignment(
ParentAlignment(
fraction = 0f,
offset = 24.dp.toPx()
)
)
recyclerView.setChildAlignment(
ChildAlignment(fraction = 0f)
)
```
--------------------------------
### Enable Infinite Looping
Source: https://context7.com/rubensousa/dpadrecyclerview/llms.txt
Configure adapter content looping behavior when reaching the start or end of the list.
```kotlin
// Loop in both directions
recyclerView.setLoopDirection(DpadLoopDirection.MIN_MAX)
// Loop only at the end
recyclerView.setLoopDirection(DpadLoopDirection.MAX)
// Disable looping
recyclerView.setLoopDirection(DpadLoopDirection.NONE)
```
--------------------------------
### Start Dragging an Item
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/recipes/dragdrop.md
Initiate a drag operation on a specific item by calling startDrag with its position. If the item is not selected, a selection will be triggered first.
```kotlin
dragHelper.startDrag(position = 0)
```
--------------------------------
### Custom Span Sizes with DpadSpanSizeLookup
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/recipes/layout.md
Implement DpadSpanSizeLookup to customize the span size of items in a grid. This example makes the first item span the full width.
```kotlin
recyclerView.setSpanSizeLookup(object : DpadSpanSizeLookup() {
override fun getSpanSize(position: Int): Int {
return if (position == 0) {
recyclerView.getSpanCount()
} else {
1
}
}
})
```
--------------------------------
### Asserting DpadRecyclerView State
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/testing.md
Example of using DpadRecyclerViewAssertions to verify the focus state of a ViewHolder at a specific position.
```kotlin
Espresso.onView(withId(R.id.recyclerView))
.assert(DpadRecyclerViewAssertions.isFocused(position = 5))
```
--------------------------------
### Setup Horizontal Spacing for DpadRecyclerView
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/recipes/spacing.md
Use this function to configure horizontal item and edge spacing for a DpadRecyclerView. Ensure R.dimen.grid_horizontal_item_spacing and R.dimen.horizontal_edge_spacing are defined in your resources.
```kotlin
fun setupSpacing(recyclerView: DpadRecyclerView) {
recyclerView.addItemDecoration(
DpadGridSpacingDecoration.create(
itemSpacing = recyclerView.resources.getDimensionPixelOffset(
R.dimen.grid_horizontal_item_spacing
),
perpendicularItemSpacing = recyclerView.resources.getDimensionPixelOffset(
R.dimen.grid_horizontal_item_spacing
),
edgeSpacing = recyclerView.resources.getDimensionPixelOffset(
R.dimen.horizontal_edge_spacing
)
)
)
}
```
--------------------------------
### Limit Pending Focus Requests
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/recipes/scrolling.md
Control the responsiveness to key events by setting `setFocusSearchDebounceMs`. This example ignores key events faster than 200ms to prevent excessive scrolling.
```kotlin
// Will ignore key events faster than 200ms
recyclerView.setFocusSearchDebounceMs(200)
```
--------------------------------
### Performing DpadRecyclerView Actions
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/testing.md
Example of using DpadRecyclerViewActions to scroll to a specific item within a RecyclerView.
```kotlin
Espresso.onView(withId(R.id.recyclerView))
.perform(DpadRecyclerViewActions.scrollTo(
hasDescendant(withText("Some title"))
))
```
--------------------------------
### Change Smooth Scrolling Behavior with Linear Interpolator
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/recipes/scrolling.md
Customize the smooth scrolling behavior by providing a custom `SmoothScrollByBehavior`. This example sets a `LinearInterpolator` to change the default animation.
```kotlin
val linearInterpolator = LinearInterpolator()
recyclerView.setSmoothScrollBehavior(
object : DpadRecyclerView.SmoothScrollByBehavior {
override fun configSmoothScrollByDuration(dx: Int, dy: Int): Int {
return RecyclerView.UNDEFINED_DURATION
}
override fun configSmoothScrollByInterpolator(dx: Int, dy: Int): Interpolator {
return linearInterpolator
}
}
)
```
--------------------------------
### Configure DpadRecyclerView via XML
Source: https://context7.com/rubensousa/dpadrecyclerview/llms.txt
Define layout, alignment, spacing, and focus behavior directly in XML layout files.
```xml
android:orientation="vertical"
app:spanCount="5"
app:reverseLayout="false"
android:gravity="center"
app:dpadRecyclerViewParentAlignmentFraction="0.5"
app:dpadRecyclerViewParentAlignmentOffset="24dp"
app:dpadRecyclerViewParentAlignmentEdge="min_max"
app:dpadRecyclerViewChildAlignmentFraction="0.5"
app:dpadRecyclerViewChildAlignmentOffset="0dp"
app:dpadRecyclerViewItemSpacing="8dp"
app:dpadRecyclerViewItemEdgeSpacing="16dp"
app:dpadRecyclerViewFocusOutFront="true"
app:dpadRecyclerViewFocusOutBack="false"
app:dpadRecyclerViewFocusOutSideFront="true"
app:dpadRecyclerViewFocusOutSideBack="true"
app:dpadRecyclerViewSmoothFocusChangesEnabled="true"
app:dpadRecyclerViewFocusableDirection="standard" />
```
--------------------------------
### Implement Dpad-compatible Composable
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/getting_started.md
Create a focusable Composable using dpadClickable and onFocusChanged modifiers.
```kotlin
@Composable
fun ItemComposable(
item: Int,
onClick: () -> Unit,
modifier: Modifier = Modifier,
) {
var isFocused by remember { mutableStateOf(false) }
val backgroundColor = if (isFocused) Color.White else Color.Black
val textColor = if (isFocused) Color.Black else Color.White
Box(
modifier = modifier
.background(backgroundColor)
.onFocusChanged { focusState ->
isFocused = focusState.hasFocus
}
.focusable()
.dpadClickable {
onClick()
},
contentAlignment = Alignment.Center,
) {
Text(
text = item.toString(),
color = textColor,
fontSize = 35.sp
)
}
}
```
--------------------------------
### Assert Focus and Selection in Espresso
Source: https://context7.com/rubensousa/dpadrecyclerview/llms.txt
Use DpadRecyclerViewAssertions to verify the focus and selection state of items at specific positions.
```kotlin
@Test
fun testFocusAndSelection() {
// Assert ViewHolder at position is focused
Espresso.onView(withId(R.id.recyclerView))
.check(DpadRecyclerViewAssertions.isFocused(position = 5))
// Assert ViewHolder at position is selected
Espresso.onView(withId(R.id.recyclerView))
.check(DpadRecyclerViewAssertions.isSelected(position = 5))
// Assert selection with sub-position
Espresso.onView(withId(R.id.recyclerView))
.check(DpadRecyclerViewAssertions.isSelected(position = 5, subPosition = 1))
}
```
--------------------------------
### Configure DpadRecyclerView in XML
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/getting_started.md
Add the view to your layout file. Do not manually set a LayoutManager as it is handled internally.
```xml
```
--------------------------------
### Dispatching Key Events with KeyEvents
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/testing.md
Utility methods for simulating key presses with configurable counts and delays.
```kotlin
KeyEvents.click()
KeyEvents.back()
KeyEvents.pressDown(times = 5)
// 50 ms between each key press
KeyEvents.pressUp(times = 5, delay = 50)
```
--------------------------------
### Listen for Selection Changes
Source: https://context7.com/rubensousa/dpadrecyclerview/llms.txt
Add a listener to observe selection changes and alignment events as users navigate items with DPAD controls.
```kotlin
recyclerView.addOnViewHolderSelectedListener(object : OnViewHolderSelectedListener {
override fun onViewHolderSelected(
parent: DpadRecyclerView,
child: RecyclerView.ViewHolder?,
position: Int,
subPosition: Int
) {
// Called immediately when selection changes
Log.d("Selection", "Selected position: $position, subPosition: $subPosition")
}
override fun onViewHolderSelectedAndAligned(
parent: DpadRecyclerView,
child: RecyclerView.ViewHolder?,
position: Int,
subPosition: Int
) {
// Called after scrolling animation completes
Log.d("Selection", "Aligned to position: $position")
}
})
```
--------------------------------
### Add DpadRecyclerView dependencies
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/getting_started.md
Include the library and optional Compose or testing modules in your build.gradle file.
```groovy
implementation "com.rubensousa.dpadrecyclerview:dpadrecyclerview:{{ dpadrecyclerview.version }}"
// Recommended: To use Compose together with DpadRecyclerView
implementation "com.rubensousa.dpadrecyclerview:dpadrecyclerview-compose:{{ dpadrecyclerview.version }}"
// Optional: Espresso test helpers for your instrumented tests:
androidTestImplementation "com.rubensousa.dpadrecyclerview:dpadrecyclerview-testing:{{ dpadrecyclerview.version }}"
```
--------------------------------
### Manage Programmatic Selection in Kotlin
Source: https://context7.com/rubensousa/dpadrecyclerview/llms.txt
Navigates to specific positions or sub-positions with optional smooth scrolling and completion callbacks.
```kotlin
// Immediate jump to position
recyclerView.setSelectedPosition(position = 10)
// Smooth scroll to position
recyclerView.setSelectedPositionSmooth(position = 10)
// Selection with callback when complete
recyclerView.setSelectedPosition(position = 0, object : ViewHolderTask() {
override fun execute(viewHolder: RecyclerView.ViewHolder) {
// ViewHolder is now selected and aligned
viewHolder.itemView.requestFocus()
}
})
// Select specific sub-position
recyclerView.setSelectedSubPosition(position = 5, subPosition = 1)
recyclerView.setSelectedSubPositionSmooth(position = 5, subPosition = 2)
// Get current selection
val position = recyclerView.getSelectedPosition()
val subPosition = recyclerView.getSelectedSubPosition()
```
--------------------------------
### Create and Attach DpadDragHelper
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/recipes/dragdrop.md
Instantiate DpadDragHelper with your mutable adapter and a callback for drag events. Then, attach the helper to your DpadRecyclerView.
```kotlin
private val adapter = ExampleAdapter()
private val dragHelper = DpadDragHelper(
adapter = dragAdapter,
callback = object : DpadDragHelper.DragCallback {
override fun onDragStarted(viewHolder: RecyclerView.ViewHolder) {
// ViewHolder is now being dragged
}
override fun onDragStopped(fromUser: Boolean) {
// Dragging was cancelled either by user or programmatically
}
}
)
dragHelper.attachToRecyclerView(dpadRecyclerView)
```
--------------------------------
### Configure Grid Spacing
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/recipes/spacing.md
Apply spacing decorations to grid layouts.
```kotlin
fun setupSpacing(recyclerView: DpadRecyclerView) {
recyclerView.addItemDecoration(
DpadGridSpacingDecoration.createVertical(
itemSpacing = recyclerView.resources.getDimensionPixelOffset(
R.dimen.grid_horizontal_item_spacing
),
perpendicularItemSpacing = recyclerView.resources.getDimensionPixelOffset(
R.dimen.grid_vertical_item_spacing
),
edgeSpacing = recyclerView.resources.getDimensionPixelOffset(
R.dimen.grid_vertical_edge_spacing
)
)
)
}
```
```kotlin
fun setupSpacing(recyclerView: DpadRecyclerView) {
recyclerView.addItemDecoration(
DpadGridSpacingDecoration.create(
itemSpacing = recyclerView.resources.getDimensionPixelOffset(
R.dimen.grid_item_spacing
)
)
)
}
```
--------------------------------
### Apply Theme Styling
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/xml.md
Configuration for setting a default style for DpadRecyclerView within an application theme.
```xml
```
--------------------------------
### Dispatch DPAD Key Events in Espresso Tests
Source: https://context7.com/rubensousa/dpadrecyclerview/llms.txt
Utilize the KeyEvents utility to dispatch DPAD key events within Espresso tests for navigation testing. Supports single key presses and multiple presses with optional delays.
```kotlin
@Test
fun testNavigation() {
// Single key presses
KeyEvents.click()
KeyEvents.back()
// Multiple presses
KeyEvents.pressDown(times = 5)
KeyEvents.pressUp(times = 5, delay = 50) // 50ms between presses
KeyEvents.pressLeft(times = 3)
KeyEvents.pressRight(times = 3)
}
```
--------------------------------
### Configure Custom Grid Span Sizes
Source: https://context7.com/rubensousa/dpadrecyclerview/llms.txt
Implement DpadSpanSizeLookup to define custom span sizes for items, such as full-width headers.
```kotlin
// Custom span sizes for headers
recyclerView.setSpanSizeLookup(object : DpadSpanSizeLookup() {
override fun getSpanSize(position: Int): Int {
return if (position == 0) {
recyclerView.getSpanCount() // Full-width header
} else {
1 // Regular item
}
}
})
```
--------------------------------
### Configure Spacing APIs
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/recipes/spacing.md
Available methods for setting spacing properties on the DpadRecyclerView.
```kotlin
setItemSpacing()
setItemEdgeSpacing()
setItemMaxEdgeSpacing()
setItemMinEdgeSpacing()
```
--------------------------------
### Migrating Selection Listeners from BaseGridView to DpadRecyclerView
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/migrating_leanback.md
This code shows how to migrate from BaseGridView's addOnChildViewHolderSelectedListener to DpadRecyclerView's addOnViewHolderSelectedListener.
```kotlin
recyclerView.addOnChildViewHolderSelectedListener(object : OnChildViewHolderSelectedListener() {
override fun onChildViewHolderSelected(
parent: RecyclerView,
child: RecyclerView.ViewHolder?,
position: Int,
subposition: Int
) {}
override fun onChildViewHolderSelectedAndPositioned(
parent: RecyclerView,
child: RecyclerView.ViewHolder?,
position: Int,
subposition: Int
) {}
})
```
```kotlin
recyclerView.addOnViewHolderSelectedListener(object : OnViewHolderSelectedListener {
override fun onViewHolderSelected(
parent: DpadRecyclerView,
child: RecyclerView.ViewHolder?,
position: Int,
subPosition: Int
) {}
override fun onViewHolderSelectedAndAligned(
parent: DpadRecyclerView,
child: RecyclerView.ViewHolder?,
position: Int,
subPosition: Int
) {}
})
```
--------------------------------
### Configure Smooth Scrolling Behavior
Source: https://context7.com/rubensousa/dpadrecyclerview/llms.txt
Adjust scroll speed, interpolation, and pending request limits to customize the smooth scrolling experience.
```kotlin
// Disable smooth scrolling for immediate focus changes
recyclerView.setSmoothFocusChangesEnabled(false)
// Slow down smooth scrolling (2x slower)
recyclerView.setSmoothScrollSpeedFactor(2f)
// Custom scroll behavior with interpolator
val linearInterpolator = LinearInterpolator()
recyclerView.setSmoothScrollBehavior(
object : DpadRecyclerView.SmoothScrollByBehavior {
override fun configSmoothScrollByDuration(dx: Int, dy: Int): Int {
return RecyclerView.UNDEFINED_DURATION // Use default
}
override fun configSmoothScrollByInterpolator(dx: Int, dy: Int): Interpolator {
return linearInterpolator
}
}
)
// Limit pending scroll requests to prevent over-scrolling
recyclerView.setSmoothScrollMaxPendingAlignments(2)
recyclerView.setSmoothScrollMaxPendingMoves(3)
```
--------------------------------
### Configure Grid Layout in XML
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/recipes/layout.md
Use this XML to set up a DpadRecyclerView as a grid. The 'app:spanCount' attribute defines the number of columns in the grid.
```xml
```
--------------------------------
### Configure Grid Layout in Kotlin
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/recipes/layout.md
Use this Kotlin code to set up a DpadRecyclerView as a grid programmatically. Call setSpanCount to define the number of columns.
```kotlin
recyclerView.setSpanCount(5)
```
--------------------------------
### Add DpadRecyclerView Dependencies
Source: https://context7.com/rubensousa/dpadrecyclerview/llms.txt
Add these dependencies to your Gradle build file to include the core library, Compose integration, and testing utilities.
```groovy
// Core library
implementation "com.rubensousa.dpadrecyclerview:dpadrecyclerview:1.5.0-beta01"
// Recommended: Compose integration
implementation "com.rubensousa.dpadrecyclerview:dpadrecyclerview-compose:1.5.0-beta01"
// Optional: Espresso test helpers
androidTestImplementation "com.rubensousa.dpadrecyclerview:dpadrecyclerview-testing:1.5.0-beta01"
```
--------------------------------
### Migrating Window Alignment from BaseGridView to DpadRecyclerView
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/migrating_leanback.md
This snippet shows how to migrate window alignment settings from BaseGridView to DpadRecyclerView's ParentAlignment.
```kotlin
recyclerView.windowAlignment = BaseGridView.WINDOW_ALIGN_NO_EDGE
recyclerView.windowAlignmentOffset = 0
recyclerView.windowAlignmentOffsetPercent = 100f
recyclerView.windowAlignmentPreferKeyLineOverLowEdge = false
recyclerView.windowAlignmentPreferKeyLineOverHighEdge = false
```
```kotlin
recyclerView.setParentAlignment(
ParentAlignment(
edge = ParentAlignment.Edge.NONE,
offset = 0,
fraction = 1f,
preferKeylineOverEdge = false
)
)
```
--------------------------------
### Configure Grid Layout Span Count
Source: https://context7.com/rubensousa/dpadrecyclerview/llms.txt
Set the number of columns for a grid layout. This should be called before the adapter is set.
```kotlin
// Set up a 5-column grid
recyclerView.setSpanCount(5)
```
--------------------------------
### Implement DpadComposeViewHolder for View-system focus
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/compose.md
Use DpadComposeViewHolder to maintain focus state within the View system and pass it as a parameter to Composables.
```kotlin
class ComposeItemAdapter(
private val onItemClick: (Int) -> Unit
) : ListAdapter>(Item.DIFF_CALLBACK) {
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): DpadComposeViewHolder {
return DpadComposeViewHolder(
parent,
onClick = onItemClick
) { item, isFocused ->
ItemComposable(item, isFocused)
}
}
override fun onBindViewHolder(
holder: DpadComposeViewHolder,
position: Int
) {
holder.setItemState(getItem(position))
}
}
```
--------------------------------
### Configure grid focus direction
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/recipes/focus.md
Sets the focus navigation strategy for the grid layout.
```kotlin
recyclerView.setFocusableDirection(FocusableDirection.CIRCULAR)
```
```kotlin
recyclerView.setFocusableDirection(FocusableDirection.CONTINUOUS)
```
--------------------------------
### Migrate Window Alignment from BaseGridView to DpadRecyclerView
Source: https://context7.com/rubensousa/dpadrecyclerview/llms.txt
Use ParentAlignment in DpadRecyclerView to replicate window alignment settings from Leanback's BaseGridView. Ensure correct mapping of edge alignment constants.
```kotlin
// Leanback BaseGridView
recyclerView.windowAlignment = BaseGridView.WINDOW_ALIGN_NO_EDGE
recyclerView.windowAlignmentOffset = 0
recyclerView.windowAlignmentOffsetPercent = 100f
// DpadRecyclerView equivalent
recyclerView.setParentAlignment(
ParentAlignment(
edge = ParentAlignment.Edge.NONE,
offset = 0,
fraction = 1f
)
)
// Edge alignment mapping:
// WINDOW_ALIGN_NO_EDGE -> ParentAlignment.Edge.NONE
// WINDOW_ALIGN_LOW_EDGE -> ParentAlignment.Edge.MIN
// WINDOW_ALIGN_MAX_EDGE -> ParentAlignment.Edge.MAX
// WINDOW_ALIGN_BOTH_EDGE -> ParentAlignment.Edge.MIN_MAX
```
--------------------------------
### Enable Infinite Scrolling with Looping
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/recipes/layout.md
Configure DpadRecyclerView to loop its adapter contents for infinite scrolling. Use setLoopDirection with DpadLoopDirection.MIN_MAX for both directions or DpadLoopDirection.MAX for end-only looping. Looping requires enough items to fill the viewport.
```kotlin
// This will loop when scrolling towards both the start and end edges
recyclerView.setLoopDirection(DpadLoopDirection.MIN_MAX)
// This will loop only when scrolling towards the end
recyclerView.setLoopDirection(DpadLoopDirection.MAX)
```
--------------------------------
### Configure Fading Edges
Source: https://context7.com/rubensousa/dpadrecyclerview/llms.txt
Set up visual fading indicators for off-screen content via XML or programmatically.
```xml
```
```kotlin
// Programmatic fading edge control
recyclerView.setFadingEdgeLength(120.dpToPx())
recyclerView.setMinEdgeFadingLength(60.dpToPx())
recyclerView.setMaxEdgeFadingLength(120.dpToPx())
recyclerView.enableMinEdgeFading(true)
recyclerView.enableMaxEdgeFading(true)
```
--------------------------------
### Compose Integration with DpadComposeViewHolder
Source: https://context7.com/rubensousa/dpadrecyclerview/llms.txt
Create ViewHolders that render Composables while keeping focus within the View system. This adapter uses DpadComposeViewHolder to render Composables.
```kotlin
class ComposeItemAdapter(
private val onItemClick: (Int) -> Unit
) : ListAdapter>(DiffCallback) {
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): DpadComposeViewHolder {
return DpadComposeViewHolder(
parent,
onClick = onItemClick
) { item, isFocused ->
ItemComposable(item, isFocused)
}
}
override fun onBindViewHolder(
holder: DpadComposeViewHolder,
position: Int
) {
holder.setItemState(getItem(position))
}
}
```
```kotlin
@Composable
fun ItemComposable(item: Int, isFocused: Boolean) {
val backgroundColor = if (isFocused) Color.White else Color.Black
val textColor = if (isFocused) Color.Black else Color.White
Box(
modifier = Modifier.background(backgroundColor),
contentAlignment = Alignment.Center
) {
Text(
text = item.toString(),
color = textColor,
fontSize = 35.sp
)
}
}
```
--------------------------------
### Implement DpadViewHolder Interface
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/selection.md
Implement DpadViewHolder in your ViewHolder to automatically receive selection and deselection events.
```kotlin
class ExampleViewHolder(
view: View
) : RecyclerView.ViewHolder(view), DpadViewHolder {
override fun onViewHolderSelected() {}
override fun onViewHolderDeselected() {}
}
```
--------------------------------
### Configure Linear Column Spacing
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/recipes/spacing.md
Apply spacing decorations to a vertical linear layout.
```kotlin
fun setupSpacing(recyclerView: DpadRecyclerView) {
recyclerView.addItemDecoration(
DpadLinearSpacingDecoration.create(
itemSpacing = recyclerView.resources.getDimensionPixelOffset(
R.dimen.vertical_item_spacing
),
edgeSpacing = recyclerView.resources.getDimensionPixelOffset(
R.dimen.vertical_edge_spacing
),
perpendicularEdgeSpacing = recyclerView.resources.getDimensionPixelOffset(
R.dimen.horizontal_edge_spacing
)
)
)
}
```
```xml
```
```kotlin
fun setupSpacing(recyclerView: DpadRecyclerView) {
recyclerView.addItemDecoration(
DpadLinearSpacingDecoration.create(
itemSpacing = recyclerView.resources.getDimensionPixelOffset(
R.dimen.vertical_item_spacing
)
)
)
}
```
--------------------------------
### Implement Sub Position Alignment
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/recipes/alignment.md
Defines custom alignment points within a ViewHolder by implementing DpadViewHolder.
```kotlin
class ExampleViewHolder(
view: View
) : RecyclerView.ViewHolder(view), DpadViewHolder {
private val alignments = ArrayList()
init {
alignments.apply {
add(
SubPositionAlignment(
fraction = 0f,
alignmentViewId = R.id.firstView,
focusViewId = R.id.firstView
)
)
add(
SubPositionAlignment(
fraction = 0.5f,
alignmentViewId = R.id.firstView,
focusViewId = R.id.secondView
)
)
add(
SubPositionAlignment(
fraction = 0f,
alignmentViewId = R.id.secondView,
focusViewId = R.id.thirdView
)
)
}
}
override fun getSubPositionAlignments(): List {
return alignments
}
}
```
--------------------------------
### Configure Scrollbars
Source: https://context7.com/rubensousa/dpadrecyclerview/llms.txt
Define scrollbar appearance and behavior using XML attributes.
```xml
```
--------------------------------
### Perform DpadRecyclerView Actions in Espresso
Source: https://context7.com/rubensousa/dpadrecyclerview/llms.txt
Use DpadRecyclerViewActions to perform scrolling, selection, and synchronization tasks within Espresso tests.
```kotlin
@Test
fun testScrolling() {
// Scroll to ViewHolder matching condition
Espresso.onView(withId(R.id.recyclerView))
.perform(DpadRecyclerViewActions.scrollTo(
hasDescendant(withText("Target Item"))
))
// Select specific position
Espresso.onView(withId(R.id.recyclerView))
.perform(DpadRecyclerViewActions.selectPosition(position = 10))
// Select last position
Espresso.onView(withId(R.id.recyclerView))
.perform(DpadRecyclerViewActions.selectLastPosition())
// Wait for adapter updates
Espresso.onView(withId(R.id.recyclerView))
.perform(DpadRecyclerViewActions.waitForAdapterUpdate(expectedUpdates = 1))
// Wait for scroll to complete
Espresso.onView(withId(R.id.recyclerView))
.perform(DpadRecyclerViewActions.waitForIdleScroll())
}
```
--------------------------------
### Implement DpadComposeFocusViewHolder for focus-aware Composables
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/compose.md
Use DpadComposeFocusViewHolder to allow Composables to manage their own focus state directly.
```kotlin
class ComposeItemAdapter(
private val onItemClick: (Int) -> Unit
) : ListAdapter>(Item.DIFF_CALLBACK) {
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): DpadComposeFocusViewHolder {
return DpadComposeFocusViewHolder(parent) { item ->
ItemComposable(
item = item,
onClick = {
onItemClick(item)
}
)
}
}
override fun onBindViewHolder(
holder: DpadComposeFocusViewHolder,
position: Int
) {
holder.setItemState(getItem(position))
}
}
```
--------------------------------
### Observe selection changes
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/getting_started.md
Implement OnViewHolderSelectedListener to track selection and alignment events.
```kotlin
recyclerView.addOnViewHolderSelectedListener(object : OnViewHolderSelectedListener {
override fun onViewHolderSelected(
parent: DpadRecyclerView,
child: RecyclerView.ViewHolder?,
position: Int,
subPosition: Int
) {}
override fun onViewHolderSelectedAndAligned(
parent: DpadRecyclerView,
child: RecyclerView.ViewHolder?,
position: Int,
subPosition: Int
) {}
})
```
--------------------------------
### Compose Integration with DpadComposeFocusViewHolder
Source: https://context7.com/rubensousa/dpadrecyclerview/llms.txt
Create ViewHolders that render Composables with focus handled within the Compose tree. This adapter uses DpadComposeFocusViewHolder to manage focus for Composable items.
```kotlin
class ComposeItemAdapter(
private val onItemClick: (Int) -> Unit
) : ListAdapter>(DiffCallback) {
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): DpadComposeFocusViewHolder {
return DpadComposeFocusViewHolder(parent) { item ->
ItemComposable(
item = item,
onClick = { onItemClick(item) }
)
}
}
override fun onBindViewHolder(
holder: DpadComposeFocusViewHolder,
position: Int
) {
holder.setItemState(getItem(position))
}
}
```
```kotlin
@Composable
fun ItemComposable(
item: Int,
onClick: () -> Unit,
modifier: Modifier = Modifier
) {
var isFocused by remember { mutableStateOf(false) }
val backgroundColor = if (isFocused) Color.White else Color.Black
val textColor = if (isFocused) Color.Black else Color.White
Box(
modifier = modifier
.background(backgroundColor)
.onFocusChanged { focusState ->
isFocused = focusState.hasFocus
}
.focusable()
.dpadClickable { onClick() },
contentAlignment = Alignment.Center
) {
Text(
text = item.toString(),
color = textColor,
fontSize = 35.sp
)
}
}
```
--------------------------------
### Migrating Item Alignment from BaseGridView to DpadRecyclerView
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/migrating_leanback.md
This snippet demonstrates migrating item alignment configurations from BaseGridView to DpadRecyclerView's ChildAlignment.
```kotlin
recyclerView.itemAlignmentOffset = 0
recyclerView.itemAlignmentOffsetPercent = 100f
recyclerView.isItemAlignmentOffsetWithPadding = true
```
```kotlin
recyclerView.setChildAlignment(
ChildAlignment(
offset = 0,
fraction = 1f,
includePadding = true
)
)
```
--------------------------------
### Apply Grid Spacing Decoration in Kotlin
Source: https://context7.com/rubensousa/dpadrecyclerview/llms.txt
Adds spacing between items in grid layouts with control over gaps and edges.
```kotlin
// Simple grid spacing (same on all sides)
recyclerView.addItemDecoration(
DpadGridSpacingDecoration.create(
itemSpacing = resources.getDimensionPixelOffset(R.dimen.grid_spacing)
)
)
// Vertical grid with custom spacing
recyclerView.addItemDecoration(
DpadGridSpacingDecoration.createVertical(
itemSpacing = resources.getDimensionPixelOffset(R.dimen.horizontal_spacing),
perpendicularItemSpacing = resources.getDimensionPixelOffset(R.dimen.vertical_spacing),
edgeSpacing = resources.getDimensionPixelOffset(R.dimen.edge_spacing)
)
)
```
--------------------------------
### Create ComposeItemAdapter for DpadRecyclerView
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/README.MD
This adapter is designed for integrating DpadRecyclerView with Jetpack Compose. It uses DpadComposeFocusViewHolder to manage item focus and rendering within a Compose environment.
```kotlin
class ComposeItemAdapter(
private val onItemClick: (Int) -> Unit
) : ListAdapter>(Item.DIFF_CALLBACK) {
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): DpadComposeFocusViewHolder {
return DpadComposeFocusViewHolder(parent) { item ->
ItemComposable(
item = item,
onClick = {
onItemClick(item)
}
)
}
}
override fun onBindViewHolder(
holder: DpadComposeFocusViewHolder,
position: Int
) {
holder.setItemState(getItem(position))
}
}
```
--------------------------------
### Configure ParentAlignment with offset
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/alignment.md
Sets the parent anchor with a specific pixel offset and fraction.
```kotlin
ParentAlignment(offset = 16.dp.toPx(), fraction = 0f)
```
--------------------------------
### Implement Mutable Adapter for Drag and Drop
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/recipes/dragdrop.md
Implement DpadDragHelper.DragAdapter to expose a mutable list of items. This allows DpadDragHelper to automatically reorder elements.
```kotlin
class ExampleAdapter(
private val adapterConfig: AdapterConfig
) : RecyclerView.Adapter(),
DpadDragHelper.DragAdapter {
private val items = ArrayList()
override fun getMutableItems(): MutableList = items
```
--------------------------------
### Configure Child Alignment in Kotlin
Source: https://context7.com/rubensousa/dpadrecyclerview/llms.txt
Defines how individual child ViewHolders align to the parent's keyline position.
```kotlin
// Center of child aligns to keyline
recyclerView.setChildAlignment(
ChildAlignment(fraction = 0.5f)
)
// Start of child aligns to keyline
recyclerView.setChildAlignment(
ChildAlignment(fraction = 0f)
)
// Include padding in alignment calculation
recyclerView.setChildAlignment(
ChildAlignment(
fraction = 0f,
includePadding = true
)
)
// Combined alignment setup
recyclerView.setAlignments(
parentAlignment = ParentAlignment(fraction = 0.5f),
childAlignment = ChildAlignment(fraction = 0.5f),
smooth = true // Animate to new alignment
)
```
--------------------------------
### Configure Focus Direction
Source: https://context7.com/rubensousa/dpadrecyclerview/llms.txt
Define how focus navigation behaves at grid boundaries using standard, circular, or continuous modes.
```kotlin
// Standard: Focus stops at edges
recyclerView.setFocusableDirection(FocusableDirection.STANDARD)
// Circular: Focus wraps to opposite span
recyclerView.setFocusableDirection(FocusableDirection.CIRCULAR)
// Continuous: Focus moves to next/previous row
recyclerView.setFocusableDirection(FocusableDirection.CONTINUOUS)
```
--------------------------------
### Make ViewHolder Focusable
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/selection.md
Set a child view as focusable in XML or after onCreateViewHolder to enable DPAD navigation.
```kotlin
view.isFocusable = true
view.isFocusableInTouchMode = true
```
--------------------------------
### Configure Horizontal Row Layout in XML
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/recipes/layout.md
Use this XML to set up a DpadRecyclerView as a horizontal row. Ensure the orientation attribute is set to 'horizontal'.
```xml
```
--------------------------------
### Define Extra Layout Space
Source: https://context7.com/rubensousa/dpadrecyclerview/llms.txt
Implement a strategy to calculate additional space for off-screen items, useful for edge-aligned layouts.
```kotlin
recyclerView.setExtraLayoutSpaceStrategy(object : ExtraLayoutSpaceStrategy {
override fun calculateStartExtraLayoutSpace(state: RecyclerView.State): Int {
return recyclerView.width / 2 // Half page at start
}
override fun calculateEndExtraLayoutSpace(state: RecyclerView.State): Int {
return recyclerView.width / 2 // Half page at end
}
})
```
--------------------------------
### Configure Linear Row Spacing
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/recipes/spacing.md
Apply spacing decorations to a horizontal linear layout.
```kotlin
fun setupSpacing(recyclerView: DpadRecyclerView) {
recyclerView.addItemDecoration(
DpadLinearSpacingDecoration.create(
itemSpacing = recyclerView.resources.getDimensionPixelOffset(
R.dimen.horizontal_item_spacing
),
edgeSpacing = recyclerView.resources.getDimensionPixelOffset(
R.dimen.horizontal_edge_spacing
),
perpendicularEdgeSpacing = recyclerView.resources.getDimensionPixelOffset(
R.dimen.vertical_edge_spacing
)
)
)
}
```
```kotlin
fun setupSpacing(recyclerView: DpadRecyclerView) {
recyclerView.addItemDecoration(
DpadLinearSpacingDecoration.create(
itemSpacing = recyclerView.resources.getDimensionPixelOffset(
R.dimen.vertical_item_spacing
)
)
)
}
```
--------------------------------
### Define Sub-Position Alignment in Kotlin
Source: https://context7.com/rubensousa/dpadrecyclerview/llms.txt
Implements DpadViewHolder to define multiple focusable alignment points within a single ViewHolder.
```kotlin
class DetailViewHolder(view: View) : RecyclerView.ViewHolder(view), DpadViewHolder {
private val alignments = listOf(
SubPositionAlignment(
fraction = 0f,
alignmentViewId = R.id.headerView,
focusViewId = R.id.headerView
),
SubPositionAlignment(
fraction = 0.5f,
alignmentViewId = R.id.headerView,
focusViewId = R.id.descriptionView
),
SubPositionAlignment(
fraction = 0f,
alignmentViewId = R.id.descriptionView,
focusViewId = R.id.actionButton
)
)
override fun getSubPositionAlignments(): List = alignments
}
// Navigate sub-positions programmatically
recyclerView.setSelectedSubPosition(subPosition = 1)
recyclerView.setSelectedSubPositionSmooth(position = 0, subPosition = 2)
```
--------------------------------
### Add DpadRecyclerView Dependency
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/README.MD
Include the DpadRecyclerView library in your app's build.gradle file. The compose and testing artifacts are optional.
```groovy
implementation "com.rubensousa.dpadrecyclerview:dpadrecyclerview:$latestVersion"
// Recommended: To use Compose together with DpadRecyclerView
implementation "com.rubensousa.dpadrecyclerview:dpadrecyclerview-compose:$latestVersion"
// Optional: Espresso test helpers for your instrumented tests:
androidTestImplementation "com.rubensousa.dpadrecyclerview:dpadrecyclerview-testing:$latestVersion"
```
--------------------------------
### Page-by-Page Scrolling with DpadScroller
Source: https://context7.com/rubensousa/dpadrecyclerview/llms.txt
Enable page-by-page scrolling for long text content. Attach DpadScroller to your DpadRecyclerView and optionally enable smooth scrolling.
```kotlin
val scroller = DpadScroller()
scroller.attach(dpadRecyclerView)
// Enable smooth scrolling
scroller.setSmoothScrollEnabled(true)
// Detach when done
scroller.detach()
```
--------------------------------
### Style DpadRecyclerView with Themes
Source: https://context7.com/rubensousa/dpadrecyclerview/llms.txt
Apply global styles or reusable component styles to DpadRecyclerView instances using Android themes.
```xml
```
--------------------------------
### Configure ParentAlignment for vertical centering
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/alignment.md
Sets the parent anchor to the center of the container using a fraction.
```kotlin
ParentAlignment(fraction = 0.5f)
```
--------------------------------
### Apply Linear Spacing Decoration in Kotlin
Source: https://context7.com/rubensousa/dpadrecyclerview/llms.txt
Adds consistent spacing between items in linear row or column layouts.
```kotlin
// Simple even spacing
recyclerView.addItemDecoration(
DpadLinearSpacingDecoration.create(
itemSpacing = resources.getDimensionPixelOffset(R.dimen.item_spacing)
)
)
// Full configuration with edge spacing
recyclerView.addItemDecoration(
DpadLinearSpacingDecoration.create(
itemSpacing = resources.getDimensionPixelOffset(R.dimen.item_spacing),
edgeSpacing = resources.getDimensionPixelOffset(R.dimen.edge_spacing),
perpendicularEdgeSpacing = resources.getDimensionPixelOffset(R.dimen.perpendicular_spacing)
)
)
```
--------------------------------
### Configure Center Alignment
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/recipes/alignment.md
Sets the parent and child alignment fractions to 0.5 to center items in the view.
```xml
```
```kotlin
recyclerView.setParentAlignment(
ParentAlignment(fraction = 0.5f)
)
recyclerView.setChildAlignment(
ChildAlignment(fraction = 0.5f)
)
```
--------------------------------
### Enable Drag and Drop with DPAD Controls
Source: https://context7.com/rubensousa/dpadrecyclerview/llms.txt
Implement drag and drop functionality for RecyclerView items using DPAD controls. Requires making your adapter implement DpadDragHelper.DragAdapter and attaching a DpadDragHelper instance to your RecyclerView.
```kotlin
class DraggableAdapter : RecyclerView.Adapter(),
DpadDragHelper.DragAdapter {
private val items = mutableListOf()
override fun getMutableItems(): MutableList = items
// ... standard adapter methods
}
```
```kotlin
val dragHelper = DpadDragHelper(
adapter = draggableAdapter,
callback = object : DpadDragHelper.DragCallback {
override fun onDragStarted(viewHolder: RecyclerView.ViewHolder) {
viewHolder.itemView.alpha = 0.7f
}
override fun onDragStopped(fromUser: Boolean) {
// Save new order
}
}
)
dragHelper.attachToRecyclerView(recyclerView)
// Start dragging programmatically
dragHelper.startDrag(position = selectedPosition)
// Stop dragging
dragHelper.stopDrag()
```
--------------------------------
### Define Focus Attributes
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/xml.md
Attributes for managing focus navigation behavior and smooth transitions.
```xml
```
--------------------------------
### Configure combined Parent and Child alignment
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/alignment.md
Sets both parent and child anchor positions for horizontal alignment.
```kotlin
ParentAlignment(offset = 24.dp.toPx(), fraction = 0f)
ChildAlignment(fraction = 0f)
```
--------------------------------
### Observe Focus Changes in DpadRecyclerView
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/selection.md
Implement OnViewFocusedListener to observe focus changes within the DpadRecyclerView.
```kotlin
recyclerView.addOnViewFocusedListener(object : OnViewFocusedListener {
override fun onViewFocused(parent: RecyclerView.ViewHolder, child: View) {
// Child has focus
}
})
```
--------------------------------
### Supported Layout Attributes
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/xml.md
Standard ViewGroup attributes supported by DpadRecyclerView.
```xml
```
--------------------------------
### React to focus changes in a Composable
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/compose.md
Use standard focus APIs like onFocusChanged and focusable to handle focus state within a Composable.
```kotlin
@Composable
fun ItemComposable(
item: Int,
onClick: () -> Unit,
modifier: Modifier = Modifier,
) {
var isFocused by remember { mutableStateOf(false) }
val backgroundColor = if (isFocused) Color.White else Color.Black
val textColor = if (isFocused) Color.Black else Color.White
Box(
modifier = modifier
.background(backgroundColor)
.onFocusChanged { focusState ->
isFocused = focusState.hasFocus
}
.focusable()
.dpadClickable {
onClick()
},
contentAlignment = Alignment.Center,
) {
Text(
text = item.toString(),
color = textColor,
fontSize = 35.sp
)
}
}
```
--------------------------------
### Include Padding in Child Alignment
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/recipes/alignment.md
Enables padding consideration for alignment when the fraction is 0f or 1f.
```kotlin
recyclerView.setChildAlignment(
ChildAlignment(fraction = 0f, includePadding = true)
)
```
--------------------------------
### Observe focus changes
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/getting_started.md
Use OnViewFocusedListener to react when a view gains focus.
```kotlin
recyclerView.addOnViewFocusedListener(object : OnViewFocusedListener {
override fun onViewFocused(
parent: RecyclerView.ViewHolder,
child: View,
) {
// Child is now focused
}
})
```
--------------------------------
### Observe Focus Changes with OnFocusChangeListener
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/selection.md
Use OnFocusChangeListener on a view to react to focus gain or loss.
```kotlin
view.setOnFocusChangeListener { _, hasFocus ->
if (hasFocus) {
// React to focus gain
} else {
// React to focus loss
}
}
```
--------------------------------
### Define Alignment Attributes
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/xml.md
Attributes for configuring child and parent alignment within the DpadRecyclerView.
```xml
```
--------------------------------
### Configure Edge Alignment Preference
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/recipes/alignment.md
Sets the edge preference to NONE to ensure items remain aligned to the keyline at list boundaries.
```xml
app:dpadRecyclerViewParentAlignmentEdge="none" />
```
```kotlin
recyclerView.setParentAlignment(
ParentAlignment(
fraction = 0f,
offset = 24.dp.toPx()
edge = ParentAlignment.Edge.NONE
)
)
```
--------------------------------
### Scroll to Specific Position with Callback
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/recipes/scrolling.md
Use `setSelectedPosition` to scroll immediately to a given position and execute a callback once the ViewHolder is selected and aligned.
```kotlin
recyclerView.setSelectedPosition(0, object : ViewHolderTask() {
override fun execute(viewHolder: RecyclerView.ViewHolder) {
// ViewHolder was selected and aligned to its final location
}
})
```
--------------------------------
### Define Spacing Attributes
Source: https://github.com/rubensousa/dpadrecyclerview/blob/master/docs/xml.md
Attributes for controlling item spacing and edge spacing configurations.
```xml
```