Kotlin의 안드로이드 애니메이션: 러티 애니메이션, 내비게이션 구성 요소, ViewPager2가 있는 로그인 화면

안드로이드의 애니메이션은 사용자에게 정보를 전달하는 동시에 응용 프로그램을 생동감 있게 하는 방법이다.안드로이드에는 다른 API가 있습니다. 애니메이션을 만들 수 있습니다. 그것에 대한 더 많은 정보를 읽어 주십시오. here이 글은 Lottie 이라는 라이브러리를 사용해서 프로그램에 애니메이션을 쉽게 추가할 수 있습니다.너는 무엇을 배울 거니
  • 입사 화면 만들기
  • 탐색 구성 요소 사용
  • 로티 애니메이션

  • 입사 화면은 주로 응용 프로그램의 기능을 설명하고 이미지, 텍스트 또는 애니메이션을 사용하는 데 사용된다.응용 프로그램 모듈 구축에 다음 의존항을 추가하기 시작합니다.그레델 줄
    //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'
    
    우리는 초기 화면에서 입사 화면으로 내비게이션할 것이다.
    탐색 프로세스는 시작 화면 -> 입사 화면 -> 홈 페이지입니다.단일 활동 원칙에 따라 프로젝트는 하나의 활동(주요 활동)과 세 개의 부분만 있을 것이다.
  • 빈 템플릿으로 새 프로젝트 만들기
  • res 폴더를 우클릭하고 New->Android 자원 파일
  • 을 선택하십시오
  • 탐색 차트 파일의 이름을 입력하고 탐색을 자원 유형으로 선택한 다음 확인
  • 을 클릭합니다.
    내비게이션 맵.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로 변경할 수 있습니다.
  • 세션 추가하기;왼쪽 위 모서리의 [디자인] 뷰에서 [추가] 버튼을 클릭하여 선택할 수 있는 세그먼트 목록을 봅니다.
  • Splash Fragment를 Onboarding Fragment에 연결하는 동작을 추가합니다.Splash Fragment에 마우스를 놓고 표시된 원형 연결점을 Onboarding Fragment
  • 에 드래그합니다.
  • OnboardingFragment에서WelcomeFragment
  • 까지 같은 절차를 반복
  • action 라벨은 목적지에 도달할 수 있는 가능한 경로를 표시한다
  • app:destination목표 세션
  • 의 id 포함
  • 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
    <?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를 보실 수 있습니다.
    만약 당신에게 어떤 건의나 문제가 있다면, 그것들을 평론 구역에 놓으세요.고마워요

    좋은 웹페이지 즐겨찾기