Строковый ресурс не найден в kotlin android с getPageTitle - PullRequest
0 голосов
/ 18 октября 2019

Новый для 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.

My 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

Я загрузил проект здесь , если кто-то захочет попробовать его.

Ответы [ 6 ]

6 голосов
/ 22 октября 2019

Вызов 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'sосновной конструктор и добавил Context в качестве третьего параметра. Теперь мы будем использовать это Context, чтобы получить строку вместо Resources.getSystem().

0 голосов
/ 28 октября 2019

Я думаю, что вы вызываете строковые ресурсы неправильно. это должно быть примерно так: -

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

Попробуйте, надеюсь, ваша проблема будет решена. Дайте мне знать, если возникнет какая-либо проблема. Удачного кодирования.

0 голосов
/ 26 октября 2019

Код, который работает с вашим методом:

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 () .

0 голосов
/ 22 октября 2019

Я знаю, что не отвечаю на ваш вопрос напрямую, но проблему можно решить, изменив способ создания / использования адаптера.

Основное изменение состоит в том, что вместо того, чтобы позволить адаптеру решать, как заполнятьпредставление, которое мы даем этой «ответственности» пользователю.

Мы делаем это, запрашивая список страниц, в этом примере я использовал 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
)

Таким образом, вы не только решаете проблему, но иВы также получаете масштабируемое решение, которое поддерживает не только этот вариант использования, но и любой другой вариант использования

0 голосов
/ 22 октября 2019

Как указано в документации к Ресурсам , метод getSystem () :

Возвращает глобальный объект общих ресурсов, который обеспечивает доступ только к системе. ресурсы (без ресурсов приложения), не настроен для текущего экрана (не может использовать единицы измерения, не изменяется в зависимости от ориентации и т. д.) и не подвержен наложению ресурсов времени выполнения.

Итаквы не можете получить доступ к ресурсам приложения этим методом. Но, глядя на ваш код, вы можете просто изменить

private class SectionsPagerAdapter

на:

private inner class SectionsPagerAdapter

, и когда вы хотите получить строку вместо

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

, сделайте это:

getString(R.string.kitten_tab)

Объяснение: Когда вы помечаете класс как inner, вы делаете каждый метод вместе с другими вещами во внешнем классе видимыми и доступными во внутреннем классе . В каждом действии (любом контексте ) существуют методы доступа к ресурсам. Одним из них является getString, который вы можете просто использовать, чтобы получить ваши строки по их идентификатору.

0 голосов
/ 18 октября 2019

Используйте

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

вместо

Resources.getSystem().getText(R.string.faa_user_tab)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...