Kotlin:来自 AppCompatActivity 的片段

Kotlin: Fragment from AppCompatActivity

已将 AppCompatActivity() 转换为 Fragment() 并根据主题进行了一些更改: 并更新了 Gradle .

carouselView 在我制作片段视图之前工作。它编译:

Executing tasks: [:app:assembleDebug] in project /Users/jaskier/Documents/Android/GoodTogether

Configure project :app Warning: The 'kotlin-android-extensions' Gradle plugin is deprecated. Please use this migration guide (https://goo.gle/kotlin-android-extensions-deprecation) to start working with View Binding (https://developer.android.com/topic/libraries/view-binding) and the 'kotlin-parcelize' plugin.

Configure project :tabview Warning: The 'kotlin-android-extensions' Gradle plugin is deprecated. Please use this migration guide (https://goo.gle/kotlin-android-extensions-deprecation) to start working with View Binding (https://developer.android.com/topic/libraries/view-binding) and the 'kotlin-parcelize' plugin.

Task :app:preBuild UP-TO-DATE Task :app:preDebugBuild UP-TO-DATE Task :tabview:preBuild UP-TO-DATE Task :tabview:preDebugBuild UP-TO-DATE Task :tabview:packageDebugRenderscript NO-SOURCE Task :app:generateDebugBuildConfig UP-TO-DATE Task :app:compileDebugRenderscript NO-SOURCE Task :tabview:compileDebugAidl NO-SOURCE Task :app:compileDebugAidl NO-SOURCE Task :app:generateDebugResValues UP-TO-DATE Task :app:generateDebugResources UP-TO-DATE Task :tabview:generateDebugResValues UP-TO-DATE Task :tabview:compileDebugRenderscript NO-SOURCE Task :tabview:generateDebugResources UP-TO-DATE Task :tabview:packageDebugResources UP-TO-DATE Task :app:mergeDebugResources UP-TO-DATE Task :app:createDebugCompatibleScreenManifests UP-TO-DATE Task :app:extractDeepLinksDebug UP-TO-DATE Task :tabview:extractDeepLinksDebug UP-TO-DATE Task :tabview:processDebugManifest UP-TO-DATE Task :app:processDebugManifest UP-TO-DATE Task :tabview:compileDebugLibraryResources UP-TO-DATE Task :tabview:parseDebugLocalResources UP-TO-DATE Task :tabview:generateDebugRFile UP-TO-DATE Task :app:processDebugResources UP-TO-DATE Task :tabview:generateDebugBuildConfig UP-TO-DATE Task :tabview:javaPreCompileDebug UP-TO-DATE Task :tabview:compileDebugKotlin UP-TO-DATE Task :tabview:compileDebugJavaWithJavac UP-TO-DATE Task :tabview:bundleLibCompileToJarDebug UP-TO-DATE Task :app:compileDebugKotlin UP-TO-DATE Task :app:javaPreCompileDebug UP-TO-DATE Task :app:compileDebugJavaWithJavac UP-TO-DATE Task :app:compileDebugSources UP-TO-DATE Task :app:mergeDebugShaders UP-TO-DATE Task :app:compileDebugShaders NO-SOURCE Task :app:generateDebugAssets UP-TO-DATE Task :tabview:mergeDebugShaders UP-TO-DATE Task :tabview:compileDebugShaders NO-SOURCE Task :tabview:generateDebugAssets UP-TO-DATE Task :tabview:packageDebugAssets UP-TO-DATE Task :app:mergeDebugAssets UP-TO-DATE Task :app:processDebugJavaRes NO-SOURCE Task :tabview:processDebugJavaRes NO-SOURCE Task :tabview:bundleLibResDebug UP-TO-DATE Task :app:mergeDebugJavaResource UP-TO-DATE Task :tabview:bundleLibRuntimeToJarDebug UP-TO-DATE Task :app:dexBuilderDebug UP-TO-DATE Task :app:checkDebugDuplicateClasses UP-TO-DATE Task :app:mergeExtDexDebug UP-TO-DATE Task :app:mergeDexDebug UP-TO-DATE Task :app:mergeDebugJniLibFolders UP-TO-DATE Task :tabview:mergeDebugJniLibFolders UP-TO-DATE Task :tabview:mergeDebugNativeLibs UP-TO-DATE Task :tabview:stripDebugDebugSymbols NO-SOURCE Task :tabview:copyDebugJniLibsProjectOnly UP-TO-DATE Task :app:mergeDebugNativeLibs UP-TO-DATE Task :app:stripDebugDebugSymbols NO-SOURCE Task :app:validateSigningDebug UP-TO-DATE Task :app:packageDebug UP-TO-DATE Task :app:assembleDebug UP-TO-DATE

BUILD SUCCESSFUL in 829ms 40 actionable tasks: 40 up-to-date Build Analyzer results available

但是当我将此片段切换为活动状态(带有片段的 tabView)时,它给出:

Unfortunately, Application has stopped

AppCompatActivity() 转换时我会遗漏什么?

之前:

package com.myPackage.application
import android.annotation.SuppressLint
import android.app.PendingIntent.getActivity
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.ImageView
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.core.content.res.ResourcesCompat
import kotlinx.android.synthetic.main.activity_start_carousel.*

class StartCarouselActivity : AppCompatActivity() {

    private val movies = arrayListOf(R.drawable.ic_action_tab1, R.drawable.ic_action_tab2, R.drawable.ic_action_tab3)
    private val moviesTitles = arrayListOf("Harry Potter", "Konosuba", "I Am Legend")
    private val trending = arrayListOf(R.drawable.ic_action_tab1, R.drawable.ic_action_tab2, R.drawable.ic_action_tab3)

    private val trendingTitles = arrayListOf("Lord of the Rings", "The Last Naruto the Movie", "Spirited Away")

    @SuppressLint("UseCompatLoadingForDrawables")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_start_carousel)

        carouselView1.apply {
            size = movies.size
            resource = R.layout.start_carousel_movies_item
            scaleOnScroll = true
            spacing = 50
            hideIndicator(true)
            setCarouselViewListener { view, position ->
                val imageView = view.findViewById<ImageView>(R.id.imageView)
                imageView.setImageDrawable(ResourcesCompat.getDrawable(resources, movies[position], null))
                val textView = view.findViewById<TextView>(R.id.textViewTitle)
                textView.text = moviesTitles[position]
            }
            show()
        }

        carouselView2.apply {
            val trendingMovies = trending + movies
            val trendingTitle = trendingTitles + moviesTitles

            size = trendingMovies.size
            resource = R.layout.start_carousel_trending_item
            spacing = 50
            hideIndicator(true)
            setCarouselViewListener { view, position ->
                val imageView = view.findViewById<ImageView>(R.id.imageView)
                imageView.setImageDrawable(ResourcesCompat.getDrawable(resources, trendingMovies[position], null))
                val textView = view.findViewById<TextView>(R.id.textViewTitle)
                textView.text = trendingTitle[position]
            }
            show()
        }

    }
}

之后:

package com.myPackage.application
import android.annotation.SuppressLint
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.core.content.res.ResourcesCompat
import androidx.fragment.app.Fragment
import kotlinx.android.synthetic.main.activity_start_carousel.*
import kotlinx.android.synthetic.main.fragment_tab2.view.*

class TabFragment2 : Fragment() {
    private val movies = arrayListOf(
        R.drawable.ic_action_tab1,
        R.drawable.ic_action_tab2,
        R.drawable.ic_action_tab3
    )
    private val moviesTitles = arrayListOf("Harry Potter", "Konosuba", "I Am Legend")
    private val trending = arrayListOf(
        R.drawable.ic_action_tab1,
        R.drawable.ic_action_tab2,
        R.drawable.ic_action_tab3
    )

    private val trendingTitles = arrayListOf(
        "Lord of the Rings",
        "The Last Naruto the Movie",
        "Spirited Away"
    )

    @SuppressLint("UseCompatLoadingForDrawables")
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        super.onCreate(savedInstanceState)
        val v: View = inflater.inflate(R.layout.activity_start_carousel, container, false)

        carouselView1.apply {
            size = movies.size
            resource = R.layout.start_carousel_movies_item
            scaleOnScroll = true
            spacing = 50
            hideIndicator(true)
            setCarouselViewListener { view, position ->
                val imageView = view.findViewById<ImageView>(R.id.imageView)
                imageView.setImageDrawable(
                    ResourcesCompat.getDrawable(
                        resources,
                        movies[position],
                        null
                    )
                )
                val textView = view.findViewById<TextView>(R.id.textViewTitle)
                textView.text = moviesTitles[position]
            }
            show()
        }

        carouselView2.apply {
            val trendingMovies = trending + movies
            val trendingTitle = trendingTitles + moviesTitles

            size = trendingMovies.size
            resource = R.layout.start_carousel_trending_item
            spacing = 50
            hideIndicator(true)
            setCarouselViewListener { view, position ->
                val imageView = view.findViewById<ImageView>(R.id.imageView)
                imageView.setImageDrawable(
                    ResourcesCompat.getDrawable(
                        resources,
                        trendingMovies[position],
                        null
                    )
                )
                val textView = view.findViewById<TextView>(R.id.textViewTitle)
                textView.text = trendingTitle[position]
            }
            show()
        }
        return  v
    }
}

假设您的轮播视图 ID 是 carouselView1 和 carouselView2,您应该使用

v.findViewById<CarouselView>(R.id.carouselView1).apply { ... }

v.findViewById<CarouselView>(R.id.carouselView2).apply { ... }

onCreateView 中实例化轮播视图。

kotlin中的apply函数是一个作用域函数,引用上下文对象(本例中是你的两个CarouselView) 和 returns 它。

所以在你的情况下 v.findViewById<CarouselView>(R.id.carouselView1).apply { ... }v.findViewById<CarouselView>(R.id.carouselView2).apply { ... } returns一个CarouselView.

如果您需要在 Fragment:

中全局使用视图,此行为可能很有用
    private var carouselView1: CarouselView? = null

    @SuppressLint("UseCompatLoadingForDrawables")
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        super.onCreate(savedInstanceState)
        val v: View = inflater.inflate(R.layout.activity_start_carousel, container, false)

        carouselView1 = v.findViewById<CarouselView>(R.id.carouselView1).apply { ... }
    }

    fun exampleFunction() {
        // Example operation to explain the global use of this variable
        carouselView1?.spacing = 10
    }

有关 Kotlin 范围函数的更多信息,请参阅 here

您的片段代码的主要问题是您没有在膨胀视图 (v) 中搜索您的 CarouselView。 事实上,在你的 AppCompactActivity 中你不需要参考 findViewById 之前的特定视图,因为 onCreate 中的 setContentView 方法, 自动膨胀布局。

这些是代码语法 v.findViewById<ViewType>(<view-id>) 的原因。