This guide explains how to react to events with CardStackListener.
CardStackListener provides callbacks for all important events:
| Callback | When is it called? |
|---|---|
onCardDragging |
While the card is being dragged |
onCardSwiped |
When the card has been swiped |
onCardRewound |
When a card has been brought back |
onCardCanceled |
When the swipe has been canceled |
onCardAppeared |
When a card appears |
onCardDisappeared |
When a card disappears |
Implement CardStackListener in your Activity or Fragment:
class MainActivity : AppCompatActivity(), CardStackListener {
override fun onCardDragging(direction: Direction?, ratio: Float) {
// Called while dragging
}
override fun onCardSwiped(direction: Direction?) {
// Called when the card has been swiped
}
override fun onCardRewound() {
// Called when a card has been brought back
}
override fun onCardCanceled() {
// Called when the swipe has been canceled
}
override fun onCardAppeared(view: View?, position: Int) {
// Called when a card appears
}
override fun onCardDisappeared(view: View?, position: Int) {
// Called when a card disappears
}
}Pass the listener when creating the manager:
val manager = CardStackLayoutManager(this, this) // this = CardStackListener
cardStackView.layoutManager = managerOr set it later:
manager.cardStackListener = thisCalled continuously while dragging:
override fun onCardDragging(direction: Direction?, ratio: Float) {
// direction: The direction being dragged (Left, Right, Top, Bottom)
// ratio: Progress from 0.0f (start) to 1.0f (threshold reached)
when (direction) {
Direction.Left -> {
// Show dislike indicator based on ratio
updateDislikeIndicator(ratio)
}
Direction.Right -> {
// Show like indicator based on ratio
updateLikeIndicator(ratio)
}
else -> {}
}
}Usage:
- Update UI elements based on swipe progress
- Show/hide overlays dynamically
- Play sound effects
Called when a card has been successfully swiped:
override fun onCardSwiped(direction: Direction?) {
val currentPosition = manager.topPosition
val totalItems = adapter.itemCount
when (direction) {
Direction.Right -> {
// Like action
handleLike(currentPosition)
}
Direction.Left -> {
// Dislike action
handleDislike(currentPosition)
}
Direction.Top -> {
// Super Like action
handleSuperLike(currentPosition)
}
Direction.Bottom -> {
// Pass action
handlePass(currentPosition)
}
null -> {}
}
// Paging: Load more data if needed
if (currentPosition >= totalItems - 5) {
loadMoreData()
}
}Usage:
- Perform actions based on swipe direction
- Save preferences
- Load more data (paging)
- Update backend
Called when a card has been brought back:
override fun onCardRewound() {
val currentPosition = manager.topPosition
// Undo last action
undoLastAction(currentPosition)
Log.d("CardStack", "Card at position $currentPosition was rewound")
}Usage:
- Undo last action
- Update statistics
- Logging
Called when the swipe has been canceled (card was not dragged beyond threshold):
override fun onCardCanceled() {
val currentPosition = manager.topPosition
// Reset UI elements
resetIndicators()
Log.d("CardStack", "Swipe canceled at position $currentPosition")
}Usage:
- Reset UI elements
- Hide temporary overlays
- Logging
Called when a card appears (e.g., after swipe or rewind):
override fun onCardAppeared(view: View?, position: Int) {
// Load data for the new card
val item = adapter.getItem(position)
loadCardData(item)
// Update UI
updateCardInfo(item)
Log.d("CardStack", "Card appeared at position $position")
}Usage:
- Load additional data for the card
- Update UI elements
- Analytics tracking
Called when a card disappears (e.g., after swipe):
override fun onCardDisappeared(view: View?, position: Int) {
val item = adapter.getItem(position)
// Cleanup
cleanupCardData(item)
Log.d("CardStack", "Card disappeared at position $position")
}Usage:
- Cleanup resources
- Stop running animations
- Analytics tracking
class MainActivity : AppCompatActivity(), CardStackListener {
private lateinit var manager: CardStackLayoutManager
private lateinit var adapter: CardStackAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setupCardStackView()
}
private fun setupCardStackView() {
val cardStackView = findViewById<CardStackView>(R.id.card_stack_view)
manager = CardStackLayoutManager(this, this)
adapter = CardStackAdapter()
cardStackView.layoutManager = manager
cardStackView.adapter = adapter
}
override fun onCardDragging(direction: Direction?, ratio: Float) {
when (direction) {
Direction.Right -> updateLikeIndicator(ratio)
Direction.Left -> updateDislikeIndicator(ratio)
else -> {}
}
}
override fun onCardSwiped(direction: Direction?) {
val position = manager.topPosition
when (direction) {
Direction.Right -> handleLike(position)
Direction.Left -> handleDislike(position)
else -> {}
}
// Paging
if (position >= adapter.itemCount - 5) {
loadMoreData()
}
}
override fun onCardRewound() {
undoLastAction(manager.topPosition)
}
override fun onCardCanceled() {
resetIndicators()
}
override fun onCardAppeared(view: View?, position: Int) {
val item = adapter.getItem(position)
updateCardInfo(item)
}
override fun onCardDisappeared(view: View?, position: Int) {
// Cleanup if needed
}
private fun updateLikeIndicator(ratio: Float) {
// Update UI
}
private fun updateDislikeIndicator(ratio: Float) {
// Update UI
}
private fun handleLike(position: Int) {
// Handle like action
}
private fun handleDislike(position: Int) {
// Handle dislike action
}
private fun undoLastAction(position: Int) {
// Undo action
}
private fun resetIndicators() {
// Reset UI
}
private fun updateCardInfo(item: YourDataModel) {
// Update UI
}
private fun loadMoreData() {
// Load more data
}
}You can also create a separate listener:
val listener = object : CardStackListener {
override fun onCardDragging(direction: Direction?, ratio: Float) {}
override fun onCardSwiped(direction: Direction?) {}
override fun onCardRewound() {}
override fun onCardCanceled() {}
override fun onCardAppeared(view: View?, position: Int) {}
override fun onCardDisappeared(view: View?, position: Int) {}
}
val manager = CardStackLayoutManager(this, listener)- Performance: Avoid heavy operations in
onCardDragging(called very frequently) - UI Updates: Perform UI updates in
onCardDraggingto provide visual feedback - Business Logic: Perform business logic in
onCardSwiped, not inonCardDragging - Cleanup: Use
onCardDisappearedfor cleanup operations
- Basic Usage - Swipe and Rewind
- Paging - Dynamic data loading
- Overlay Views - Like/Dislike indicators