使用getPageTitle在Kotlin android中找不到字符串资源

时间:2019-10-18 14:17:10

标签: android kotlin

Android和Kotlin的新功能在这里。制作我的第一个应用程序后,我正在尝试使用getPageTitle函数为选项卡提供其标题(其中是字符串资源)。完整的实现如下:

class FAAMainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    setSupportActionBar(toolbar as Toolbar)

    val pagerAdapter = SectionsPagerAdapter(supportFragmentManager, FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT)
    pager.adapter = pagerAdapter
    tabs.setupWithViewPager(pager)
}

private class SectionsPagerAdapter : FragmentPagerAdapter{

    constructor(fm: FragmentManager, behavior: Int) : super(fm, behavior)

    override fun getItem(position: Int): Fragment {
        when (position) {
            0 -> return HomeFragment()
            1 -> return KittensFragment()
            2 -> return CatsFragment()
            3 -> return FosterersFragment()
            4 -> return FAAUsersFragment()
            else -> {
                return HomeFragment()
            }
        }
    }

    override fun getCount(): Int {
        return 5
    }

    override fun getPageTitle(position: Int): CharSequence? {
        when(position) {
            0 ->  Resources.getSystem().getText(R.string.home_tab)
            1 ->  Resources.getSystem().getText(R.string.kitten_tab)
            2 ->  Resources.getSystem().getText(R.string.cat_tab)
            3 ->  Resources.getSystem().getText(R.string.fosterer_tab)
            4 ->  Resources.getSystem().getText(R.string.faa_user_tab)
            else -> "Error"
        }
        return "Error"
    }
}
}

尝试运行该应用程序会出现以下错误:

java.lang.RuntimeException: Unable to start activity ComponentInfo{uk.ac.aber.dcs.cs31620.faa/uk.ac.aber.dcs.cs31620.faa.ui.FAAMainActivity}: android.content.res.Resources$NotFoundException: String resource ID #0x7f0d0027

我不明白为什么它找不到String资源。

我的strings.xml;

<resources>
    <string name="app_name">Feline Adoption Agency</string>
    <string name="hello_blank_fragment">Hello blank fragment</string>
    <string name="home_tab">Home</string>
    <string name="kitten_tab">Kittens</string>
    <string name="cat_tab">Cats</string>
    <string name="fosterer_tab">Fosterers</string>
    <string name="faa_user_tab">FAA Users</string>
</resources>

更多信息,我为此悬赏:

  • 我可以验证资源是否正确放置在app/build/generated/not_namespaced_r_class_sources/debug/r/uk/ac/aber/dcs/cs31620/faa/R.java文件中。
  • 但是他们没有放入app/build/generated/not_namespaced_r_class_sources/debug/r/androidx/appcompat/R.java中,我不确定这是问题的原因。
  • 我对FAAMainActivity类的导入是:

    import android.content.res.Resources import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.Toolbar import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentPagerAdapter import kotlinx.android.synthetic.main.activity_main.* import uk.ac.aber.dcs.cs31620.faa.R import uk.ac.aber.dcs.cs31620.faa.ui.cats.CatsFragment import uk.ac.aber.dcs.cs31620.faa.ui.faa_users.FAAUsersFragment import uk.ac.aber.dcs.cs31620.faa.ui.fosterers.FosterersFragment import uk.ac.aber.dcs.cs31620.faa.ui.home.HomeFragment import uk.ac.aber.dcs.cs31620.faa.ui.kittens.KittensFragment

如果有人想尝试,我已经上传了项目here

6 个答案:

答案 0 :(得分:6)

致电Resources.getSystem()提供系统级资源,而不是您的 根据文档的应用程序级别资源:

  

返回一个全局共享资源对象,该对象仅提供对   系统资源(无应用程序资源),且未配置   当前屏幕(不能使用尺寸单位,不会更改   n方向等)。

您将需要应用程序或活动级别的上下文,以便从strings.xml中检索字符串。我已将您的SectionsPagerAdapter更改为此,以解决您的错误:

private class SectionsPagerAdapter(fm: FragmentManager, behavior: Int, private val context: Context) :
        FragmentPagerAdapter(fm, behavior) {

        override fun getItem(position: Int): Fragment {
            return when (position) {
                0 -> HomeFragment()
                1 -> KittensFragment()
                2 -> CatsFragment()
                3 -> FosterersFragment()
                4 -> FAAUsersFragment()
                else -> {
                    HomeFragment()
                }
            }
        }

        override fun getCount(): Int {
            return 5
        }

        override fun getPageTitle(position: Int): CharSequence? {
           return when(position) {
                0 ->  context.getString(R.string.kitten_tab)
                1 ->  context.getString(R.string.kitten_tab)
                2 ->  context.getString(R.string.cat_tab)
                3 ->  context.getString(R.string.fosterer_tab)
                4 ->  context.getString(R.string.faa_user_tab)
               else -> context.getString(R.string.home_tab)
            }
        }
    }

FAAMainActivity

val pagerAdapter = SectionsPagerAdapter(supportFragmentManager, FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT, this) // Passed "this" as context

在这里,我主要对您代码中的以下内容进行了更改,

发件人

private class SectionsPagerAdapter : FragmentPagerAdapter{

    constructor(fm: FragmentManager, behavior: Int) : super(fm, behavior)
    ...
}

收件人

private class SectionsPagerAdapter(fm: FragmentManager, behavior: Int, private val context: Context) :
        FragmentPagerAdapter(fm, behavior) {
        ...
}

我已将您的JAVA样式构造函数更改为kotlin的主要构造函数,并添加了Context作为第三个参数。现在,我们将使用该Context而不是Resources.getSystem()来获取字符串。

答案 1 :(得分:0)

使用

Resources.getSystem().getString(R.string.faa_user_tab)

代替

Resources.getSystem().getText(R.string.faa_user_tab)

答案 2 :(得分:0)

Resources的文档所述,方法getSystem()

  

返回一个全局共享资源对象,该对象仅提供对   系统资源(无应用程序资源)未配置   当前屏幕(不能使用尺寸单位,不会基于   方向等),并且不受运行时资源覆盖的影响。

因此,您无法通过此方法访问应用程序资源。但是查看您的代码,您只需更改

private class SectionsPagerAdapter

收件人:

private inner class SectionsPagerAdapter

以及要获取的字符串代替

Resources.getSystem().getString(R.string.kitten_tab)

执行此操作:

getString(R.string.kitten_tab)

说明::将一个类标记为inner时,您将在inner class中使所有方法以及外部类中的其他内容可见并可以访问。在每个Activity(任何Context)中,都有访问资源的方法。其中之一是getString,您只需输入get your strings的ID即可。

答案 3 :(得分:0)

我知道我不是直接回答您的问题,但是可以通过更改您创建/使用适配器的方式来解决此问题。

主要变化是,我们没有让适配器决定如何填充视图,而是向用户提供了“责任”。

我们通过请求页面列表来完成此操作,在本示例中,我使用了Pair<String, Fragment>,但是您可以使用所需的所有必要信息来创建实际的数据模型。

class SectionsPagerAdapter(
    fragmentManager: FragmentManager,
    behavior: Int,
    val pages: List<Pair<String, Fragment>>
) : FragmentPagerAdapter(fragmentManager, behavior) {

    override fun getItem(position: Int): Fragment = pages[position].second

    override fun getCount(): Int = pages.size

    override fun getPageTitle(position: Int): CharSequence = pages[position].first
}

在创建适配器时,您可以在Activity/Fragment内部创建适配器,如下所示

val pages = listOf( /* Change the list to fit your exact needs*/
    context.getString(R.string.kitten_tab) to HomeFragment(),
    context.getString(R.string.kitten_tab) to KittensFragment(),
    context.getString(R.string.cat_tab) to CatsFragment(),
    context.getString(R.string.fosterer_tab) to FosterersFragment(),
    context.getString(R.string.faa_user_tab) to FAAUsersFragment()
)

val adapter = SectionsPagerAdapter(
    supportFragmentManager,
    FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT,
    pages
)

这样,您不仅可以解决问题,而且还可以获得可扩展的解决方案,该解决方案不仅支持此用例,还支持任何其他用例

答案 4 :(得分:0)

与您的方法配合使用的代码是:

Resources.getSystem().getText(android.R.string.cancel)   // returns Cancel 
Resources.getSystem().getString(android.R.string.cancel) // returns Cancel 
Resources.getSystem().getResourceName(android.R.string.cancel)) //returns android:string/cancel
Resources.getSystem().getResourceEntryName(android.R.string.cancel)) returns cancel

但是在所有情况下,使用的字符串均以 android.R 开头,这意味着您只能使用这些方法访问内置资源的Android

我不知道您为什么尝试使用上述方法访问您的字符串资源。

下面我列出了某些方法来访问与您应用相关的资源:

getResources().getText(R.string.app_name)); // returns Test App
getResources().getString(R.string.app_name)); // returns Test App
getResources().getResourceEntryName(R.string.app_name)); // returns app_name
getResources().getResourceName(R.string.app_name)); //returns com.example.testapp:string/app_name
context.getText(R.string.app_name)); // returns Test App
context.getString(R.string.app_name)); // returns Test App

您还可以使用上下文来访问以 getResources()开头的方法。

答案 5 :(得分:0)

我认为您在错误地调用字符串资源。应该是这样的:-

override fun getPageTitle(position: Int): CharSequence? {
    when(position) {
        0 ->  getString(R.string.home_tab) // just call getString() bcz, calling from AppCompatActivity
        1 ->  getString(R.string.kitten_tab) // if you use fragment and try to call 
        2 ->  getString(R.string.cat_tab) // getString(), use resources.getString(...)
        3 ->  getString(R.string.fosterer_tab)
        4 ->  getString(R.string.faa_user_tab)
        else -> "Error"
    }
    return "Error"
}

尝试一下,希望您的问题得到解决。让我知道是否还有任何问题。 编码愉快。