Как добавить обнаружение смахивания в HorizontalPager?Android

Форум для тех, кто программирует под Android
Ответить Пред. темаСлед. тема
Anonymous
 Как добавить обнаружение смахивания в HorizontalPager?

Сообщение Anonymous »

Я все еще новичок в кодировании на Kotlin для Android, и у меня возникли проблемы с функцией для моего дочернего приложения для именования. Эта конкретная функция предназначена для того, чтобы пользователи могли проводить пальцем влево и вправо по ChildNames, проводить пальцем влево для неприязни, вправо для лайка. Затем эти движения должны быть записаны классом данных «SwipedName» в таблицу базы данных комнат под названием «SwipedNames». однако в настоящее время данные в таблицу не сохраняются, а смахивание влево перемещает пользователя к предыдущему имени, а не к следующему имени.
package com.examples.childrennaming

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.detectHorizontalDragGestures
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import com.examples.childrennaming.ui.theme.ChildrenNamingTheme

class SwipeActivity : ComponentActivity() {
private lateinit var database: AppDatabase //Declares a private lateinit variable database of type AppDatabase for late state intialisation

override fun onCreate(savedInstanceState: Bundle?) { //onCreate method is called when the activity is first created to perform intial set up
super.onCreate(savedInstanceState)

val currentUserId = intent.getIntExtra("CURRENT_USER_ID", -1)

database = (application as MyApp).database //Initialises the database property using the application context

val nameDao = database.nameDao() //Retrieves the DAO (Data Access Object) from the database
val repository = NameRepository(nameDao) //Creates an instance of NameRepository with the DAO
val viewModel: NameViewModel by viewModels { NameViewModelFactory(repository) } //Initializes a NameViewModel instance using a NameViewModel factory that provides the repository

val swipedNameDao = database.swipedNameDao() //Retrieves the swipedNameDao from the database
val swipedNameRepository = SwipedNameRepository(swipedNameDao) //Creates an instance of SwipedNameRepository with the swipedNameDao

setContent { //Sets the content view of the activity using Jetpack Compose
ChildrenNamingTheme { //Applies a theme to the Compose UI.
val names by viewModel.allNames.observeAsState(emptyList()) //Observes allNames LiveData from the ViewModel and collects its state, to give an empty list as the initial state.
NamePagerScreen(names, currentUserId, swipedNameRepository) //Calls the composable function NamePagerScreen with the list of names.
}
}
}
}

@OptIn(ExperimentalFoundationApi::class)
@Composable //Marks this as a composable function
fun NamePagerScreen(names: List, currentUserId: Int, swipedNameRepository: SwipedNameRepository) { //Defines a composable function NamePagerScreen that takes a list of Name objects, currentUserId and SwipedNameRepository as a parameter.
val pagerState = rememberPagerState( //Creates a rememberPagerState instance to manage the pager state
initialPage = 0,// Sets the initial page to 0, shows first name in the table first
initialPageOffsetFraction = 0f // Sets the initial page offset fraction to 0
) {
names.size //Sets the total number of pages based on the size of the names lis
}
val swipedNameViewModel: SwipedNameViewModel = viewModel( //Creates a SwipedNameViewModel instance using the viewModel() function.
factory = SwipedNameViewModelFactory(swipedNameRepository) //Provides the SwipedNameRepository as a parameter to the factory.
)

Box(modifier = Modifier //Creates a box layout for swipe detection
.fillMaxSize() //Fills the entire available space
.pointerInput(Unit) { //Enables pointer input for the box
detectHorizontalDragGestures { change, dragAmount -> //Detects horizontal drag gestures
val isRightSwipe = dragAmount > 0 //Determines if the swipe is to the right
val swipedName = SwipedName( //Creates a new SwipedName object with the provided parameters
userId = currentUserId,
nameId = names[pagerState.currentPage].nameId,
isRightSwipe = isRightSwipe //Sets the isRightSwipe property based on the swipe direction
)
swipedNameViewModel.insert(swipedName) //Inserts the swipedName into the database using the SwipedNameViewModel
change.consume() //Consumes the change event to prevent further processing
}
}
) {
HorizontalPager( //Creates a horizontal pager layout

state = pagerState //Creates a horizontal pager with the given state.
) { page ->
val name = names[page] //Gets the name value corresponding to the current page.
val background = when (name.gender) { //Sets the background resource based on the gender of the name
"Girl" -> R.drawable.pink //if gender is "Girl" sets background a pink.jpg
"Boy" -> R.drawable.blue //if gender is "Boy" sets background a pink.jpg
else -> R.drawable.default_background //else sets background a default_background.jpg
}

Box(modifier = Modifier.fillMaxSize()) {//box layout for Name and gender text
Image( //Displays background image
painter = painterResource(id = background), //sets background image with the specified painter resource based on gender
contentDescription = null,
contentScale = ContentScale.Crop,//crops scale of box
modifier = Modifier.fillMaxSize()
)
Box( //style of the box set to semi transparent black
modifier = Modifier //box modifier
.align(Alignment.Center)
.background(Color(0x80000000))
.fillMaxWidth()
.padding(16.dp)
) {
Text( //style for name and gender text
text = "${name.childFirstName} - ${name.gender}", //sets name and gender text
style = MaterialTheme.typography.headlineMedium,
color = Color.White,
modifier = Modifier.align(Alignment.Center)
)
}
}
}

}

}

Вот класс данных для SwipeName.
@Entity(tableName = "swiped_names")
data class SwipedName(
@PrimaryKey(autoGenerate = true) val id: Int = 0,
val userId: Int,
val nameId: Int,
val isRightSwipe: Boolean
)

если для пояснения потребуется дополнительная информация, дайте мне знать.
С тех пор я пытался переместить детектор HorizontalDragGestures, чтобы прикрепить его непосредственно к HorizontalPager. , это дало некоторые результаты, так как пролистывания были правильно сохранены в таблице, однако другие данные, такие как идентификатор пользователя, неверны, это также нарушило фактическую функцию пролистывания между страницами и застряло на начальной странице.
import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.detectHorizontalDragGestures
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.room.Room
import com.examples.childrennaming.ui.theme.ChildrenNamingTheme
import kotlinx.coroutines.Dispatchers
import kotlin.math.abs

class SwipeActivity : ComponentActivity() {
private lateinit var database: AppDatabase //Declares a private lateinit variable database of type AppDatabase for late state intialisation

override fun onCreate(savedInstanceState: Bundle?) { //onCreate method is called when the activity is first created to perform intial set up
super.onCreate(savedInstanceState)

val currentUserId = intent.getIntExtra("CURRENT_USER_ID", -1)

database = (application as MyApp).database //Initialises the database property using the application context

val nameDao = database.nameDao() //Retrieves the DAO (Data Access Object) from the database
val repository = NameRepository(nameDao) //Creates an instance of NameRepository with the DAO
val viewModel: NameViewModel by viewModels { NameViewModelFactory(repository) } //Initializes a NameViewModel instance using a NameViewModel factory that provides the repository

val swipedNameDao = database.swipedNameDao() //Retrieves the swipedNameDao from the database
val swipedNameRepository = SwipedNameRepository(swipedNameDao) //Creates an instance of SwipedNameRepository with the swipedNameDao

setContent { //Sets the content view of the activity using Jetpack Compose
ChildrenNamingTheme { //Applies a theme to the Compose UI.
val names by viewModel.allNames.observeAsState(emptyList()) //Observes allNames LiveData from the ViewModel and collects its state, to give an empty list as the initial state.
NamePagerScreen(names, currentUserId, swipedNameRepository) //Calls the composable function NamePagerScreen with the list of names.
}
}
}
}

@OptIn(ExperimentalFoundationApi::class)
@Composable //Marks this as a composable function
fun NamePagerScreen(names: List, currentUserId: Int, swipedNameRepository: SwipedNameRepository) { //Defines a composable function NamePagerScreen that takes a list of Name objects, currentUserId and SwipedNameRepository as a parameter.
val pagerState = rememberPagerState( //Creates a rememberPagerState instance to manage the pager state
initialPage = 0,// Sets the initial page to 0, shows first name in the table first
initialPageOffsetFraction = 0f // Sets the initial page offset fraction to 0
) {
names.size //Sets the total number of pages based on the size of the names lis
}
val swipedNameViewModel: SwipedNameViewModel = viewModel( //Creates a SwipedNameViewModel instance using the viewModel() function.
factory = SwipedNameViewModelFactory(swipedNameRepository) //Provides the SwipedNameRepository as a parameter to the factory.
)

HorizontalPager(state = pagerState) { page ->
val name = names[page]
val background = when (name.gender) {
"Girl" -> R.drawable.pink
"Boy" -> R.drawable.blue
else -> R.drawable.default_background
}

Box(
modifier = Modifier
.fillMaxSize()
.pointerInput(Unit) {
detectHorizontalDragGestures { change, dragAmount ->
val isSignificantSwipe = abs(dragAmount) > 16 // Define a threshold

if (isSignificantSwipe) {
val isRightSwipe = dragAmount > 0
val swipedName = SwipedName(
userId = currentUserId,
nameId = name.nameId,
isRightSwipe = isRightSwipe
)
Log.d("SwipeActivity", "Detected swipe: isRightSwipe=$isRightSwipe, swipedName=$swipedName")
swipedNameViewModel.insert(swipedName)
change.consume() // Consume for significant swipes
}

}
}
) {
Image(
painter = painterResource(id = background),
contentDescription = null,
contentScale = ContentScale.Crop,
modifier = Modifier.fillMaxSize()
)
Box(
modifier = Modifier
.align(Alignment.Center)
.background(Color(0x80000000))
.fillMaxWidth()
.padding(16.dp)
) {
Text(
text = "${name.childFirstName} - ${name.gender}",
style = MaterialTheme.typography.headlineMedium,
color = Color.White,
modifier = Modifier.align(Alignment.Center)
)
}
}
}
}


Подробнее здесь: https://stackoverflow.com/questions/788 ... ontalpager
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Android»