介绍
通常一个项目中要用到好多次下拉框,但是每次下拉框的数据来源都不一样,需要展示在界面上的字段都不一样,不能每次都写一遍适配器,所以就需要通用的适配器来帮助。
适配器的实现
SpinnerAdapter
//
/** 一个通用的下拉适配器,下拉的数据的类不一样,需要展示在界面上的字段也不一样的时候
* @param context 上下文
* @param data 下拉的数据源
* @param visibleField 用来展示的字段
* @param class1 数据源的类型
*/
class SpinnerAdapter<T>(val context: Context, val data:ArrayList<T>, val visibleField:String, val class1:Class<T> ) : BaseAdapter() {
//下拉中每个item的显示的样子
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
val view: View
if (convertView==null){
view= LayoutInflater.from(context).inflate(R.layout.item_spinner,parent,false)
}else{
view =convertView
}
val textView= view.findViewById<TextView>(R.id.textView)
//获取到当前位置的item数据
val dic:T=getItem(position)
//通过反射得到该字段的值,并且显示在textview上面
val nameField: Field = class1.getDeclaredField(visibleField)
nameField.isAccessible=true
if (nameField.get(dic)==null){ //如果该字段的值为null的话
val text="null"
textView.text=text
}else{
val text:String=nameField.get(dic) as String
textView.text=text
}
return view;
}
override fun getItem(position: Int): T{
return data[position]
}
override fun getItemId(position: Int): Long {
return position.toLong();
}
override fun getCount(): Int {
return data.size;
}
}
适配器布局
item_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:orientation="vertical"
android:padding="5dp"
android:layout_marginVertical="5dp">
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="TextView"
android:textSize="16sp"
android:textColor="@color/black"
android:gravity="center_vertical"
/>
</LinearLayout>
项目实战
两个类充当不同的数据来源
//数据字典的类
data class Dictionary(val label:String,val value:String)
//一个普通的学生类
data class Student(val id:String,val name:String,val no:String)
新建一个空的activity
布局里面放了两个spinner,用来展示两个不同数据来源的下拉框
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical">
<Spinner
android:id="@+id/studentSpinner"
android:layout_width="match_parent"
android:layout_height="40dp" />
<Spinner
android:id="@+id/dicSpinner"
android:layout_width="match_parent"
android:layout_height="40dp" />
</androidx.appcompat.widget.LinearLayoutCompat >
activity逻辑 (如果要获取选中的item, 以数据字典下拉为例 val item =dicSpinner.selectedItem as Dictionary ,就可以拿到然后就可以取item的任何字段来进行传递到数据库保存了)
class MainActivity : AppCompatActivity() {
lateinit var studentAdapter:SpinnerAdapter<Student>
lateinit var dictionaryAdapter:SpinnerAdapter<Dictionary>
val studentList= arrayListOf<Student>()
val dictionaryList= arrayListOf<Dictionary>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//学生下拉框配置(需要显示在界面上的值是name字段)
studentAdapter= SpinnerAdapter(this,studentList,"name",Student::class.java)
//studentSpinner 没有findviewbyid是因为有插件,直接用布局里面的id作为变量名了
studentSpinner.adapter=studentAdapter
//字典下拉框配置(需要显示在界面上的值是label字段)
dictionaryAdapter= SpinnerAdapter(this,dictionaryList,"label",Dictionary::class.java)
dicSpinner.adapter=dictionaryAdapter
doQueryDictionary()//查询字典数据
doQueryStudent()//查询学生数据
}
//假装从网络查来的
private fun doQueryDictionary(){
dictionaryList.add(Dictionary("北京","BJ"))
dictionaryList.add(Dictionary("上海","SH"))
dictionaryList.add(Dictionary("杭州","HZ"))
dictionaryAdapter.notifyDataSetChanged()
}
//假装从网络查来的
private fun doQueryStudent(){
studentList.add(Student("1","小张","20220507001"))
studentList.add(Student("2","小王","20220507002"))
studentList.add(Student("3","小陈","20220507003"))
studentAdapter.notifyDataSetChanged()
}
}
效果展示
|