Adapter笔记¶
适配器,适配器控件与数据之间的桥梁。
常用Adapter¶
ArrayAdapter¶
处理只含有文字信息的情况,使用数组或List<String>
形式的数据源
预定义资源 android.R.layout.Xxx
- simple_list_item_1 单独一行
- simple_list_item_2 两行
- simple_list_item_checked
- simple_list_item_multiple_choice
- simple_list_item_single_choice
静态创建
<!-- res/values/arrays.xml -->
<resources>
<string-array name="myarray">
<item>Hello<item>
<item>,<item>
<item>world<item>
</string-array>
</rsources>
<listView entries="@array/myarray" />
动态创建
ArrayAdapter<?>(context, 模板layout, data);
ArrayAdapter.createFromResource(context, R.array.myarry, 模板layout);
// 从String数组创建
String[] strs = {"This", "is", "my", "sentence"};
ArrayApater<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_expandable_list_item_1, strs);
ListView view = findViewById(R.id.listView);
view.setAdapter(adapter);
// 以CharSequence形式从文件创建
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, R.array.myarry, android.R.layout.simple_expandable_list_item_1);
SimpleAdapter¶
列表项较为复杂,或列表项含有不同类型的控件的情况,使用List<Map>
形式的数据源
创建ListItem中每个Item的布局
<!-- res/layout/list_item -->
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- 头图 -->
<ImageView
android:id="@+id/avatar"
android:layout_width="64dp"
android:layout_height="64dp"
android:paddingLeft="8dp"
android:baselineAlignBottom="true"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!-- 标题 -->
<TextView
android:id="@+id/caption"
android:paddingLeft="8dp"
android:textSize="20sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<!-- 箴言 -->
<TextView
android:id="@+id/says"
android:paddingLeft="8dp"
android:textSize="12sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
使用适配器
public class SettingsActivity extends AppCompatActivity
{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
int[] avatarIds = {R.drawable.ic_backup_black_24dp, R.drawable.ic_explore_black_24dp, R.drawable.ic_timer_black_24dp};
String[] captions = {"One", "Two", "Three"};
String[] says = {
"I would like to say",
"Once I have the power of Intel i7 CPU",
"I would like to run Android Studio"
};
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
for (int i = 0; i < captions.length; ++i)
{
Map<String, Object> item = new HashMap<String, Object>();
item.put("avatar", avatarIds[i]);
item.put("caption", captions[i]);
item.put("says", says[i]);
list.add(item);
}
SimpleAdapter adapter = new SimpleAdapter(
getApplicationContext(), list, R.layout.list_item,
new String[]{"avatar", "caption", "says"}, new int[]{R.id.avatar, R.id.caption, R.id.says}
);
ListView view = findViewById(R.id.listView);
view.setAdapter(adapter);
}
}
SimpleCursorAdapter¶
结合SQLite简化流程,使用Cursor作为数据源
自定义Adapter:继承BaseAdapter¶
public class AnimalAdapter extends BaseAdapter {
private LinkedList<Animal> data;
private Context context;
public AnimalAdapter(LinkedList<Animal> data, Context context) {
this.data = date;
this.context = context;
}
@Override
public int getCount() {
return date.size();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = LayoutInflater.from(context).inflate(R.layout.item_list_animal, parent, false);
// 视图中各项资源操作
return convertView;
}
// getItem()和getItemId()可根据需要进行编写
}
与适配器关联的View¶
Spinner¶
加载数据
- 在xml文件中预先定义
- 与ArrayAdapter关联
在xml文件中定义¶
- 在
res/values
中定义xml文件,结构resourse -> string-array -> item
- 通过设定
entries
属性为@array/spinner_item
来引用
示例:绑定ArrayAdapter¶
设置适配器
Spinner alphaSpinner = findViewById(R.id.spinner);
Spinner betaSpinner = findViewById(R.id.spinner2);
String[] data = {"one", "two", "three"};
final ArrayAdapter<CharSequence> alphaAdapter = ArrayAdapter.createFromResource(this, R.array.spinner, android.R.layout.simple_spinner_item);
alphaAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
ArrayAdapter<String> betaAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, data);
alphaSpinner.setAdapter(alphaAdapter);
betaSpinner.setAdapter(betaAdapter);
设置监听器
alphaSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int position, long id) {
// 通过适配器获取item
String item = (String)alphaAdapter.getItem(position);
Log.i("TAG", item);
// 通过适配器控件获取item
String str = (String)adapterView.getItemAtPosition(position);
Log.i("TAG", str);
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
ListView¶
数据更新 NotifyDataSetChanged()
示例:绑定BaseAdapter¶
绑定
// AnimalAdapter参见自定义Adapter一节
setAdapter(new AnimalAdapter(linkedlist, this));
监听单击事件
class MyActivity implements AdapterView.OnItemClickListener {
@Override
public void onItemClick(AdapterView<?> parent, View view, int positon, long id)
{
Toast.makeText(this, "You click" + position, Toast.LENGTH_SHORT).show();
}
}
此外还有OnNothingSelectedListener
优化:BaseAdapter优化¶
复用ConvertView,并创建静态类ViewHolder以减少findViewById()
的使用
- 定义静态类ViewHolder
- 检测convertView是否为空;若为空,将布局文件渲染成convertView,将ConvertView与ViewHolder关联,
setTag()
;若不为空,getTag()
。 - 设置ViewHolder。
public class MyAdapter extends BaseAdapter {
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getCount() {
return list.size();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null)
{
convertView = LayoutInflater.from(MainActivity.this).inflate(R.layout.list_item, null);
viewHolder = new ViewHolder();
viewHolder.textView = convertView.findViewById(R.id.textView);
viewHolder.imageView = convertView.findViewById(R.id.imageView);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.imageView.setImageResource((int)list.get(position).get("img"));
viewHolder.textView.setText((String)list.get(position).get("text"));
return convertView;
}
}
GridView¶
可以向两个方向滚动的控件,需要绑定BaseAdapter
用法与ListView类似
public class MyAdapter extends BaseAdapter
{
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public int getCount() {
return list.size();
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
convertView = LayoutInflater.from(MainActivity.this).inflate(R.layout.grid_item, null);
viewHolder = new ViewHolder();
viewHolder.imageView = convertView.findViewById(R.id.imageView);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder)convertView.getTag();
}
viewHolder.imageView.setImageResource((int)list.get(position).get("img"));
return convertView;
}
}
static class ViewHolder {
ImageView imageView;
}