简体   繁体   English

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

[英]String resource not found in kotlin android with getPageTitle

New to android and kotlin here.此处是 android 和 kotlin 的新手。 Making my first app and I'm trying to use the getPageTitle function to give my tabs their titles (of which are string resources).制作我的第一个应用程序,我正在尝试使用getPageTitle function 为我的标签提供标题(其中是字符串资源)。 The full implementation is as follows:完整的实现如下:

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"
    }
}
}

Trying to run the application gives the following 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

I don't understand why it cannot find the String resource.我不明白为什么它找不到字符串资源。

My strings.xml;我的字符串。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>

More information as I am putting a bounty on this:更多信息,因为我对此悬赏:

  • I can verify the resources are being placed in the app/build/generated/not_namespaced_r_class_sources/debug/r/uk/ac/aber/dcs/cs31620/faa/R.java file correctly.我可以验证资源是否正确放置在app/build/generated/not_namespaced_r_class_sources/debug/r/uk/ac/aber/dcs/cs31620/faa/R.java文件中。
  • However they are not put into the app/build/generated/not_namespaced_r_class_sources/debug/r/androidx/appcompat/R.java and I am not sure that is the cause of the issue.但是它们没有被放入app/build/generated/not_namespaced_r_class_sources/debug/r/androidx/appcompat/R.java我不确定这是问题的原因。
  • My imports for the FAAMainActivity class are:我对FAAMainActivity class 的进口是:

    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

I've uploaded the project here if anyone want's to try it out.如果有人想尝试一下,我已经在这里上传了这个项目。

Calling Resources.getSystem() provides System level resources and not your application level resources as per the doc:根据文档,调用Resources.getSystem()提供系统级资源,而不是您的应用程序级资源:

Return a global shared Resources object that provides access to only system resources (no application resources), and is not configured for the current screen (can not use dimension units, does not change based n orientation, etc).返回一个全局共享资源 object,它只提供对系统资源(无应用程序资源)的访问,并且没有为当前屏幕配置(不能使用维度单位,不改变基于 n 方向等)。

You'll need application or activity level context in order to retrieve the strings from your strings.xml.您需要应用程序或活动级别上下文才能从您的 strings.xml 中检索字符串。 I have changed your SectionsPagerAdapter to this in order to fix your error:我已将您的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 FAAMainActivity

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

Here, I have primarily changed following things in your code,在这里,我主要更改了您代码中的以下内容,

From

private class SectionsPagerAdapter : FragmentPagerAdapter{

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

To

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

I have changed your JAVA style constructor to kotlin's primary constructor and added Context as third parameter.我已将您的 JAVA 样式构造函数更改为 kotlin 的主构造函数,并将Context添加为第三个参数。 Now we will use that Context to get the string instead of Resources.getSystem() .现在我们将使用该Context而不是Resources.getSystem()来获取字符串。

Use利用

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

instead of代替

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

As stated in the documentation of Resources , the method getSystem() :Resources的文档中所述,方法getSystem()

Return a global shared Resources object that provides access to only system resources (no application resources), is not configured for the current screen (can not use dimension units, does not change based on orientation, etc), and is not affected by Runtime Resource Overlay.返回一个全局共享资源 object,它只提供对系统资源(没有应用程序资源)的访问,没有为当前屏幕配置(不能使用维度单位,不根据方向改变等),并且不受运行时资源的影响覆盖。

So you cannot access your application resources by this method.因此,您无法通过此方法访问您的应用程序资源。 But looking at your code you can simply change但是看看你的代码,你可以简单地改变

private class SectionsPagerAdapter

to:至:

private inner class SectionsPagerAdapter

and when you want to get the string instead of当你想获取字符串而不是

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

do this:做这个:

getString(R.string.kitten_tab)

Explanation: When you mark a class as inner you are making every method along with other things in outer class visible and accessible in the inner class .说明:当您将 class 标记为inner时,您正在使外部 class 中的每个方法以及其他内容在内部 class中可见和可访问。 In every Activity (any Context ) there are methods for accessing resources.在每个Activity (任何Context )中都有访问资源的方法。 One of them is getString which you can simply use to get your strings by their id.其中之一是getString ,您可以简单地使用它来通过它们的 id 获取字符串

I know I'm not answering your question directly but the issue can be solved by changing the way you create/use the adapter.我知道我没有直接回答您的问题,但可以通过更改您创建/使用适配器的方式来解决问题。

The main change is that instead of letting the adapter decide how to populate the view we give that "responsibilty" to the user.主要的变化是,我们将“责任”交给用户,而不是让适配器决定如何填充视图。

We do that by requesting a list of pages, in this example I used a Pair<String, Fragment> but you can create an actual data model with all the necessary information you need.我们通过请求页面列表来做到这一点,在此示例中,我使用了Pair<String, Fragment>但您可以使用所需的所有必要信息创建实际数据 model。

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
}

And when you are creating the adapter you create it inside your Activity/Fragment like this当您创建适配器时,您可以像这样在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
)

This way, you do not only solve the problem, but you also achive a scalable solution that supports not only this use case but any other use case这样,您不仅可以解决问题,还可以获得一个可扩展的解决方案,该解决方案不仅支持此用例,还支持任何其他用例

The code that works with your method are:适用于您的方法的代码是:

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

But in all the cases the string used starts with android.R that means you can access only the androids built in resources using these methods.但在所有情况下,使用的字符串都以android.R开头,这意味着您只能使用这些方法访问内置资源的 android。

I dont know why you are trying to access your string resource using the above method.我不知道您为什么要尝试使用上述方法访问您的字符串资源。

Below I have listed certains methods to access your app related resources:下面我列出了访问您的应用相关资源的某些方法:

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

Also you can use the context to access the methods starting with getResources() as well.您也可以使用上下文来访问以getResources()开头的方法。

I think you are calling the string resources in a wrong way.我认为您以错误的方式调用字符串资源。 it should be something like this:-它应该是这样的: -

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"
}

Try this, hope your problem will be solved.试试这个,希望你的问题能得到解决。 Let me know if any issue arises further.如果有任何问题进一步出现,请告诉我。 Happy coding.快乐编码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM