【问题标题】:How to use a listOf rather than a string-array in Kotlin?如何在 Kotlin 中使用 listOf 而不是字符串数组?
【发布时间】:2022-01-22 22:03:12
【问题描述】:

目前我正在使用一个字符串数组来保存我的适配器使用的一些数据,但我需要使用列表中的数据:

目前我正在使用这个:

<string-array name="vegetables">
<item> Onion </item>
<item> Chillis </item>
<item> Tomatoes </item>
<item> Garlic Beans</item>

这是我需要使用的数据格式:

val VegName  = listOf(
Veg(0, "Onion", R.drawable.onion),
Veg(1, "Chillis", R.drawable.chilli),
Veg(2, "Tomatoes (indoor)", R.drawable.tomatoe),
Veg(3, "Garlic", R.drawable.garlic) 

)

适配器代码:

class SearchActivity : AppCompatActivity() {
private lateinit var toolbar: Toolbar
lateinit var adapter: ArrayAdapter<*>
private lateinit var listView: ListView
private lateinit var emptyView: TextView

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.search_main)
    title = "Search Veg"
    toolbar = findViewById(R.id.toolbar)
    listView = findViewById(R.id.listView)
    emptyView = findViewById(R.id.emptyView)
    adapter = ArrayAdapter<Any?>(this, android.R.layout.simple_list_item_1,
        resources.getStringArray(R.array.vegetables))
    adapter = ArrayAdapter<Any?>(this, android.R.layout.simple_list_item_1,
        resources.getStringArray(R.array.vegetables)) // I THINK THIS IS WHERE IT NEEDS CHANGING?
    listView.adapter = adapter
    listView.onItemClickListener = OnItemClickListener { adapterView, _, i, _ ->
        Toast.makeText(this@SearchActivity, adapterView.getItemAtPosition(i).toString(),
            Toast.LENGTH_SHORT).show()
    }
    listView.emptyView = emptyView
}

override fun onCreateOptionsMenu(menu: Menu): Boolean {
    menuInflater.inflate(R.menu.nav_menu, menu)
    menuInflater.inflate(R.menu.menu, menu)
    val search = menu.findItem(R.id.appSearchBar)
    val searchView : SearchView? = search?.actionView as SearchView?

    searchView?.queryHint = "Search"

    listView.setOnItemClickListener(OnItemClickListener { parent, view, position, id ->
        val intent = Intent()
        val theItemClicked = String()
        Toast.makeText(this@SearchActivity, listView.getItemAtPosition(position).toString(),
            Toast.LENGTH_SHORT).show()
        intent.putExtra("result",  listView.getItemAtPosition(position).toString() )
        intent.putExtra("position", position.toString())
        setResult(RESULT_OK, intent)
        finish()
    })
    searchView?.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
        override fun onQueryTextSubmit(query: String?): Boolean {
            return false
        }
        override fun onQueryTextChange(newText: String?): Boolean {
            adapter.filter.filter(newText)
            return true
        }
    })
    return super.onCreateOptionsMenu(menu)
}

}

非常感谢任何有关更改数据格式的帮助!

干杯

【问题讨论】:

  • 您可能会问的三个不同问题的三个很好的答案。不是很清楚。

标签: android arrays list android-studio kotlin


【解决方案1】:

您可以根据字符串数组数据构建您的列表,并将其传递给适配器:

val vegetables = context.resources.getStringArray(R.array.vegetables)
val vegNames  = listOf(
    Veg(0, vegetables[0], R.drawable.onion),
    Veg(1, vegetables[1], R.drawable.chilli),
    Veg(2, vegetables[2], R.drawable.tomatoe),
    Veg(3, vegetables[3], R.drawable.garlic)
)

【讨论】:

  • 非常感谢 - 谢谢!
【解决方案2】:

您可以通过执行resources.getStringArray(R.array.vegetables) 来提取Strings 的Array,但是您仍然必须将这些字符串与您的其他数据相关联(例如它的可绘制对象)。您需要将该数据存储在另一个结构中,并将其链接到数组中的特定字符串或索引是脆弱的。

如果可以,我建议将字符串添加为单独的资源,并在数组中引用它们:


<string name="onion">Onion</string>
<string name="chillis">Chillis</string>
<string name="tomatoes">Tomatoes</string>
<string name="garlic_beans">Garlic Beans</string>

<string-array name="vegetables">
    <item>@string/onion</item>
    <item>@string/chillis</item>
    <item>@string/tomatoes</item>
    <item>@string/garlic_beans</item>
</string-array>

然后您的代码可以在定义每个项目及其相关数据时仅引用这些字符串:

// The Veg class holds a string reference ID instead of an actual string
val VegName  = listOf(
    Veg(0, R.string.onion, R.drawable.onion),
    Veg(1, R.string.chillis, R.drawable.chilli),
    Veg(2, R.string.tomatoes, R.drawable.tomatoe),
    Veg(3, R.string.garlic_beans, R.drawable.garlic)
)

当您需要显示该文本时,您只需 context.getString(veg.stringId) 即可使用该 ID 属性,这与您在需要显示时提供可绘制 ID 的方式相同。

如果您不想这样做,或者您无法更改 Veg 类,则必须单独定义数据,然后对其进行转换(如果您正在拉动,则必须这样做无论如何来自string-array)。我喜欢这个的枚举,我认为它很整洁:

enum class VegData(@StringRes stringResId: Int, @DrawableRes drawableResId: Int) {
    ONION(R.string.onion, R.drawable.onion),
    CHILLIS(R.string.chillis, R.drawable.chilli),
    TOMATOES(R.string.tomatoes, R.drawable.tomatoe),
    GARLIC_BEANS(R.string.garlic_beans, R.drawable.garlic)
}

// might want to cache this result the first time it's called, or maybe not
// (e.g. if you want the strings to update with a language change)
fun getVeg(context: Context) = VegData.values().mapIndexed { index, veg ->
    Veg(index, context.getString(veg.stringResId), veg.drawableResId)
}

这样一来,每个事物的名称都有一个真实来源,使用它的所有事物都可以引用它。如果你仍然需要它,你有字符串数组,你有你的Veg 列表,它们都只是引用相同的字符串资源。如果您更新了字符串也没关系,如果您支持多种语言,它只会提取正确的语言

【讨论】:

  • 非常感谢 - 这真的帮助了这项工作!
猜你喜欢
  • 1970-01-01
  • 2013-09-19
  • 2016-06-19
  • 2021-04-07
  • 1970-01-01
  • 1970-01-01
  • 2018-03-30
  • 2022-01-25
  • 1970-01-01
相关资源
最近更新 更多