Kotlin开发全语言翻译安卓App如何在searchable spinner添加国家图标
实现方案
完成以下4步即可实现带国旗图标的searchable spinner效果:
- 第一步:准备国旗资源
将所有需要用到的国旗矢量图以对应国家/地区小写简码命名(比如中国国旗命名为cn.xml、美国国旗命名为us.xml),统一放入res/drawable目录下,同时提前准备一张默认国旗图作为资源找不到时的兜底显示。 - 第二步:定义语言数据类
新建数据类存储每个语言条目的完整信息:
data class LanguageItem( // 语言code,用于翻译逻辑调用 val langCode: String, // 展示给用户的语言名称 val langName: String, // 国家/地区码,用于匹配国旗资源 val countryCode: String )
- 第三步:自定义spinner条目布局
在res/layout目录下新建item_language_spinner.xml,布局内包含横向排列的国旗显示控件和语言名称控件即可,示例如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingHorizontal="16dp" android:paddingVertical="12dp" android:gravity="center_vertical" android:orientation="horizontal"> <ImageView android:id="@+id/iv_flag" android:layout_width="24dp" android:layout_height="24dp" android:layout_marginEnd="12dp" android:scaleType="centerCrop"/> <TextView android:id="@+id/tv_lang_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="16sp" android:textColor="@color/black"/> </LinearLayout>
- 第四步:实现自定义适配器
自定义适配器继承BaseAdapter,重写条目渲染逻辑,通过国家码匹配对应国旗资源,同时适配下拉展开和选中态的样式:
class LanguageSpinnerAdapter( private val context: Context, private val languageList: List<LanguageItem> ) : BaseAdapter(), Filterable { // 用于搜索过滤后的列表 private var filteredList = languageList override fun getCount(): Int = filteredList.size override fun getItem(position: Int): Any = filteredList[position] override fun getItemId(position: Int): Long = position.toLong() override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View { val view = convertView ?: LayoutInflater.from(context).inflate(R.layout.item_language_spinner, parent, false) val currentItem = filteredList[position] // 匹配国旗资源 val flagResId = context.resources.getIdentifier( currentItem.countryCode.lowercase(), "drawable", context.packageName ) view.findViewById<ImageView>(R.id.iv_flag).setImageResource( if (flagResId != 0) flagResId else R.drawable.default_flag ) // 设置语言名称 view.findViewById<TextView>(R.id.tv_lang_name).text = currentItem.langName return view } override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup?): View { return getView(position, convertView, parent) } // 适配searchable spinner的搜索功能 override fun getFilter(): Filter { return object : Filter() { override fun performFiltering(constraint: CharSequence?): FilterResults { val query = constraint?.toString()?.lowercase() ?: "" filteredList = if (query.isEmpty()) { languageList } else { languageList.filter { it.langName.lowercase().contains(query) || it.langCode.lowercase().contains(query) } } return FilterResults().apply { values = filteredList } } override fun publishResults(constraint: CharSequence?, results: FilterResults?) { @Suppress("UNCHECKED_CAST") filteredList = results?.values as? List<LanguageItem> ?: emptyList() notifyDataSetChanged() } } } }
最终调用
初始化语言列表后直接将适配器设置给searchable spinner即可:
// 初始化语言列表,按实际需求补充所有选项 val languageList = listOf( LanguageItem("zh", "简体中文", "cn"), LanguageItem("en", "English", "us"), LanguageItem("ja", "日本語", "jp"), LanguageItem("ko", "한국어", "kr") ) val adapter = LanguageSpinnerAdapter(this, languageList) // 给searchable spinner设置自定义适配器 searchableSpinner.adapter = adapter
注意事项
- 若使用矢量图作为国旗资源,需要在模块级
build.gradle的defaultConfig块中添加vectorDrawables.useSupportLibrary = true,适配低版本安卓系统 - 所有国家码命名要和资源文件名保持一致,避免出现资源找不到走兜底图标的情况
内容的提问来源于stack exchange,提问作者Muhammad Hamza
相关产品推荐
相关产品推荐

