Kotlin의 안드로이드 애니메이션: 러티 애니메이션, 내비게이션 구성 요소, ViewPager2가 있는 로그인 화면
19858 단어 androidlottienavigationkotlin
입사 화면은 주로 응용 프로그램의 기능을 설명하고 이미지, 텍스트 또는 애니메이션을 사용하는 데 사용된다.응용 프로그램 모듈 구축에 다음 의존항을 추가하기 시작합니다.그레델 줄
//navigation component
Implementation "androidx.navigation:navigation-fragment-ktx:2.3.1"
implementation "androidx.navigation:navigation-ui-ktx:2.3.1"
//viewpager2
implementation "androidx.viewpager2:viewpager2:1.0.0"
//indicator
implementation 'me.relex:circleindicator:2.1.4'
//lottie
implementation "com.airbnb.android:lottie:3.4.1"
//datastore
implementation "androidx.datastore:datastore-preferences:1.0.0-alpha02"
형식 안전을 확보하기 위해gradle에 플러그인을 추가해야 합니다.다음 내용을 맨 윗부분 구축에 추가합니다.의존 블록의gradle 파일classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.3.1"
그리고 응용 모듈 구축에 플러그인을 적용합니다.그레델 줄apply plugin: 'androidx.navigation.safeargs.kotlin'
우리는 초기 화면에서 입사 화면으로 내비게이션할 것이다.탐색 프로세스는 시작 화면 -> 입사 화면 -> 홈 페이지입니다.단일 활동 원칙에 따라 프로젝트는 하나의 활동(주요 활동)과 세 개의 부분만 있을 것이다.
내비게이션 맵.xml
<navigation
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/nav_graph"
app:startDestination="@id/splashFragment">
<fragment
android:id="@+id/splashFragment"
android:name="com.wellnesscity.health.ui.intro.SplashFragment"
android:label="fragment_splash"
tools:layout="@layout/fragment_splash" >
<action
android:id="@+id/action_splashFragment_to_welcomeFragment"
app:destination="@id/welcomeFragment"
app:popUpTo="@id/splashFragment"
app:popUpToInclusive="true" />
<action
android:id="@+id/action_splashFragment_to_onboardingFragment"
app:destination="@id/onboardingFragment"
app:popUpTo="@id/splashFragment"
app:popUpToInclusive="true" />
</fragment>
<fragment
android:id="@+id/onboardingFragment"
android:name="com.wellnesscity.health.ui.intro.OnboardingFragment"
android:label="fragment_onboarding"
tools:layout="@layout/fragment_onboarding" >
<action
android:id="@+id/action_onboardingFragment_to_welcomeFragment"
app:destination="@id/welcomeFragment"
app:popUpTo="@id/onboardingFragment"
app:popUpToInclusive="true" />
</fragment>
<fragment
android:id="@+id/welcomeFragment"
android:name="com.wellnesscity.health.ui.welcome.WelcomeFragment"
android:label="fragment_welcome"
tools:layout="@layout/fragment_welcome" >
</fragment>
</navigation>
네비게이션 맵은 시작 목적지의 시작 부분, 탑승 부분, 마지막으로 환영 부분을 포함한다.추가된 첫 번째 세션은 시작 목적지로 설정되었습니다. 필요하면 app:startDestination
표시된 속성 <navigation>
의 id를 선택한 다른 세션 id로 변경할 수 있습니다.app:destination
목표 세션app:popUpTo
는 뒷창고에 직접 있는 부분의 id를 포함한다.app:popUpToInclusive="true"
는 popUpTo 세션도 뒷창고주 활동에 탐색 맵 연결
주요 활동.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.activity.MainActivity">
<fragment
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:navGraph="@navigation/nav_graph"
app:defaultNavHost="true" />
</androidx.constraintlayout.widget.ConstraintLayout>
android:name
속성은 이미 사용한 내비게이션 유형을 표시한다app:navGraph
속성은 레이아웃을 내비게이션에 연결app:defaultNavHost="true"
시스템 분리 후퇴 버튼물보라가 튀다.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.intro.SplashFragment">
<!-- TODO: Update blank fragment layout -->
<ImageView
android:id="@+id/splash_iv"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:srcCompat="@drawable/splash_screen" />
</FrameLayout>
간호사: B
Dagger-Hilt은 전체 프로젝트에서 의존 항목 주석으로 사용되며, 주석을 볼 수 있습니다.
흩날리는 조각.kt
@AndroidEntryPoint
class SplashFragment : Fragment() {
private var binding: FragmentSplashBinding? = null
@Inject lateinit var prefs:DataStore<Preferences>
private val handler = Handler()
private val runnable = Runnable {
//saves the onboarding screen to datastore the first its viewed and ensures it only shows up ones after installation
lifecycleScope.launch {
prefs.data.collectLatest {
if (it[preferencesKey<Boolean>("onBoard")] == true)
requireView().findNavController()
.navigate(SplashFragmentDirections.actionSplashFragmentToWelcomeFragment())
else
requireView().findNavController()
.navigate(SplashFragmentDirections.actionSplashFragmentToOnboardingFragment())
}
}}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
binding = FragmentSplashBinding.inflate(layoutInflater)
return binding?.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
requireActivity().window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN)
}
override fun onResume() {
super.onResume()
handler.postDelayed(runnable,3000)
}
override fun onPause() {
super.onPause()
handler.removeCallbacks(runnable)
}
}
Splash Fragment에서, 우리는 이전에 onboarding이 표시되었는지 확인하고, 만약 그렇다면 환영 화면으로 이동하고, 그렇지 않으면 onboarding Fragment로 이동합니다. 왜냐하면 우리는 프로그램을 처음 설치할 때만 onboarding을 표시하기를 원하기 때문입니다.이를 실현하기 위해서, 우리는 첫 번째 설치 때 블로 값을true로 저장하는 첫 번째 설정 데이터를 사용합니다.WonboardingFragment에는 세 개의 응용 프로그램 내용을 설명하는 항목이 포함되어 있으며, 이 항목들은 ViewPager2와 Recycler Adapter와 함께 표시됩니다.after effect를 사용하여 자신의 애니메이션을 만들고 json 파일로 내보낼 수도 있고 lottie website에서 선택할 수도 있습니다
자산 폴더에 json 파일 추가하기;
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="15dp">
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/imageSlideIcon"
android:layout_width="match_parent"
android:layout_height="300dp"
app:layout_constraintTop_toTopOf="parent"
app:lottie_autoPlay="true"
app:lottie_fileName="diet.json"
app:lottie_loop="true" />
<TextView
android:id="@+id/textTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Title Text"
android:textColor="@color/colorPrimary"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintTop_toBottomOf="@id/imageSlideIcon" />
<TextView
android:id="@+id/textDescription"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:gravity="center"
android:text="Description Text"
android:textColor="@color/colorTextSecondary"
android:textSize="15sp"
app:layout_constraintTop_toBottomOf="@id/textTitle" />
</androidx.constraintlayout.widget.ConstraintLayout>
Lottie 파일은 두 개의 폴더에서 인용할 수 있습니다: raw와 asset 폴더. 본문에 대해 json 파일은 다음 폴더에 있습니다.위 항목 레이아웃의 Lottie view 위젯을 주의하십시오.app:lottie_autoPlay="true"
화면이 나오자마자app:lottie_fileName="diet.json"
속성은 json 파일이 자산 폴더app:lottie_loop="true"
속성은 사용자가 화면을 종료할 때까지 애니메이션을 활성화시킵니다내활
data class IntroSlide (
val title: String,
val description: String,
val icon: String
)
위의 모델 클래스는 입사 페이지의 모든 항목을 표시하는 데 사용됩니다내부 슬라이더 어댑터.kt
class IntroSliderAdapter(private val introSlides: List<IntroSlide>)
: RecyclerView.Adapter<IntroSliderAdapter.IntroSlideViewHolder>(){
//for adding text to speech listener in the onboarding fragment
var onTextPassed: ((textView:TextView) -> Unit)? = null
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): IntroSlideViewHolder {
return IntroSlideViewHolder(
SlideItemContainerBinding.inflate(LayoutInflater.from(parent.context),parent,false)
)
}
override fun getItemCount(): Int {
return introSlides.size
}
override fun onBindViewHolder(holder: IntroSlideViewHolder, position: Int) {
holder.bind(introSlides[position])
}
inner class IntroSlideViewHolder(private val binding: SlideItemContainerBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(introSlide: IntroSlide) {
binding.textTitle.text = introSlide.title
binding.textDescription.text = introSlide.description
binding.imageSlideIcon.imageAssetsFolder = "images";
binding.imageSlideIcon.setAnimation(introSlide.icon)
onTextPassed?.invoke(binding.textTitle)
}
}
}
위의 어댑터는 프로젝트 레이아웃이 있는viewHolder를 포함하는 일반적인 RecyclerView 어댑터입니다.view Holder에서, 우리는 Lottie 보기에서 호출 .imageAssetsFolder
을 하고, 이를 "images"
로 설정한 다음, 보기에서 호출 setAnimation
을 통해 Lottie를 그림이 저장된 위치를 가리킨다.나는 방금 차에 올랐다.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.intro.OnboardingFragment">
<!-- TODO: Update blank fragment layout -->
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/indicator"/>
<me.relex.circleindicator.CircleIndicator3
android:id="@+id/indicator"
android:layout_width="wrap_content"
android:layout_height="@dimen/indicator_height"
app:ci_drawable="@drawable/indicator_active"
app:ci_drawable_unselected="@drawable/indicator_inactive"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toTopOf="@id/buttonNext" />
<com.google.android.material.button.MaterialButton
android:id="@+id/buttonNext"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/standard_padding"
android:text="@string/next"
android:textColor="@android:color/white"
android:textStyle="bold"
app:backgroundTint="@color/colorPrimaryDark"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
onboardingfragment 레이아웃relex indicator이 포함된 라이브러리로 호출기 자동 제어 표시기를 볼 수 있습니다.배의 파편.kt
@AndroidEntryPoint
class OnboardingFragment : Fragment() {
private var binding: FragmentOnboardingBinding? = null
@Inject
lateinit var prefs: DataStore<Preferences>
//the items are added to the adapter
private val introSliderAdapter = IntroSliderAdapter(
listOf(
IntroSlide(
"Health Tips / Advice",
"Discover tips and advice to help you to help maintain transform and main your health",
"exercise.json"
),
IntroSlide(
"Diet Tips / Advice",
"Find out basics of health diet and good nutrition, Start eating well and keep a balanced diet",
"diet.json"
),
IntroSlide(
"Covid 19 Symptoms/Prevention tips",
"Get regular Reminders of Covid-19 prevention tips ensuring you stay safe",
"covid19.json"
)
)
)
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
binding = FragmentOnboardingBinding.inflate(layoutInflater)
return binding?.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
//set the adapter to the viewpager2
binding?.viewPager?.adapter = introSliderAdapter
//sets the viewpager2 to the indicator
binding?.indicator?.setViewPager(binding?.viewPager)
binding?.viewPager?.registerOnPageChangeCallback(
object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
/*
*check if its the last page, change text on the button
*from next to finish and set the click listener to
*to navigate to welcome screen else set the text to next
* and click listener to move to next page
*/
if (position == introSliderAdapter.itemCount - 1) {
//this animation is added to the finish button
val animation = AnimationUtils.loadAnimation(
requireActivity(),
R.anim.app_name_animation
)
binding?.buttonNext?.animation = animation
binding?.buttonNext?.text = "Finish"
binding?.buttonNext?.setOnClickListener {
lifecycleScope.launch {
saveOnboarding()
}
requireView().findNavController()
.navigate(OnboardingFragmentDirections.actionOnboardingFragmentToWelcomeFragment())
}
} else {
binding?.buttonNext?.text = "Next"
binding?.buttonNext?.setOnClickListener {
binding?.viewPager?.currentItem?.let {
binding?.viewPager?.setCurrentItem(it + 1, false)
}
}
}
}
})
}
//suspend function to save the onboarding to datastore
suspend fun saveOnboarding() {
prefs.edit {
val oneTime = true
it[preferencesKey<Boolean>("onBoard")] = oneTime
}
}
}
onboarding Fragment에서 Introslide Adapter는 Onboarding 페이지의 항목 목록을 사용하여 어댑터를 ViewPager2에 연결하고 ViewPager2 설정 표시기를 사용합니다.onPageChangeCallback
에서 현재 페이지가 마지막 페이지인지 확인하고 단추의 텍스트를finish로 변경한 다음WelcomeFragment로 이동합니다. 그렇지 않으면 텍스트는 다음 페이지에 남고, 누르면 다음 페이지로 이동합니다.이 예시 코드는 커뮤니티 프로젝트WellnessCity의 일부입니다. onboarding branchhere를 보실 수 있습니다.
만약 당신에게 어떤 건의나 문제가 있다면, 그것들을 평론 구역에 놓으세요.고마워요
Reference
이 문제에 관하여(Kotlin의 안드로이드 애니메이션: 러티 애니메이션, 내비게이션 구성 요소, ViewPager2가 있는 로그인 화면), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/kulloveth/android-animation-onboarding-screen-with-lottie-animation-navigation-component-and-viewpager2-1dhb텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)