我正在考虑编写一个自定义适配器来填充列表视图,每行有3个textview。我已经找到了相当多的示例代码来执行此操作,但看起来最好的代码是:http://www.anddev.org/custom_widget_adapters-t1796.html
经过一些小的调整来修复最新的Android SDK的一些编译器问题后,我让它运行,只是为了得到例外:
ERROR / AndroidRuntime(281):java.lang.UnsupportedOperationException:AdapterView不支持addView(View,LayoutParams)
所以我做了很多研究,发现了很多可能的原因和解决方法。这些都没有改变。我的适配器代码目前是:
public class WeatherAdapter extends BaseAdapter {
private Context context;
private List<Weather> weatherList;
public WeatherAdapter(Context context, int rowResID,
List<Weather> weatherList ) {
this.context = context;
this.weatherList = weatherList;
}
public int getCount() {
return weatherList.size();
}
public Object getItem(int position) {
return weatherList.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
Weather weather = weatherList.get(position);
//LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LayoutInflater inflater = LayoutInflater.from(context);
View v = inflater.inflate(R.layout.weather_row, null, true);
TextView cityControl = (TextView)v.findViewById( R.id.city );
TextView temperatureControl = (TextView)v.findViewById( R.id.temperature );
ImageView skyControl = (ImageView)v.findViewById( R.id.sky );
return v;
}
}
所以我已经尝试了注释的方式来获取inflater,并且当前没有注释掉。我已经尝试将“父”传递给inflate以及null,并传递“true”,“false”并完全省略最后一个参数。他们都没有工作,到目前为止我发现的所有例子都是从2008年开始的,我感觉有点过时了。
如果有人可以提供帮助,那么我很乐意解决这个问题。
答案 0 :(得分:16)
我相信这条线是错的:
View v = inflater.inflate(R.layout.weather_row, null, true);
您需要:
View v = inflater.inflate(R.layout.weather_row, parent, false);
false使得膨胀的视图独立于父级,而不是附加到父级,这在奇怪的情况下似乎是AdapterView
中自定义视图的可接受设计。为什么会这样,我觉得完全莫名其妙,但上面的模式对我有用。
答案 1 :(得分:6)
我也是初学者也是如此,所以只需要一点点盐就可以得到这个答案 - 如果它不起作用,继续前进,谷歌会更多。不熟悉AdapterView
,因为我传统上有ListView
或GridView
,自定义适配器扩展到BaseAdapter
然后listView.setAdapter(myCustomAdapter)
。
您可以尝试在WeatherAdapter
类中制作类似的内容:
public void addToList(Weather mWeather) {
weatherList.add(mWeather);
}
然后在调用WeatherAdapter
的课程中<:p>
weatherAdapter.addToList(weatherToAdd);
weatherAdapter.notifyDataSetChanged();
您还需要在getView方法中对其进行更多优化:
答案 2 :(得分:3)
对于AdaptertView addView
方法:
void addView(View child)
不支持此方法 抛出一个 UnsupportedOperationException时 叫。“(来自Android文档)
膨胀程序可能会调用addView
方法,但AdapterView
或其AdapterView
无效。
来自文档:
“Adapter对象充当桥梁 在AdapterView和。之间 该视图的基础数据。该 适配器提供对数据的访问 项目。适配器也负责 为每个项目制作一个视图 数据集“。
我认为膨胀操作可以通过一个简单的Activity来完成,它可以为您的视图和所有其他操作建模,例如,检索数据并在其他类中显示数据。
希望它会有所帮助!
答案 3 :(得分:1)
@ Axel22的答案很关键,但您的代码中还缺少一些其他内容。首先,您应该扩展BaseAdapter或ArrayAdapter,具体取决于您的偏好。其次,您希望使用ViewHolder来避免过多调用findViewById,并且(最重要的是)回收View。
private Class ViewHolder {
public TextView cityControl;
public TextView temperatureControl;
public ImageView skyControl;
public ViewHolder(TextView cityControl, TextView temperatureControl, ImageView skyControl) {
this.cityControl = cityControl;
this.temperatureControl = temperatureControl;
this.skyControl = skyControl;
}
您的getView函数可以回收视图并使用ViewHolder
类,如下所示:
public View getView(int position, View convertView, ViewGroup parent) {
Weather weather = weatherList.get(position);
// This is how you attempt to recycle the convertView, so you aren't
// needlessly inflating layouts.
View v = convertView;
ViewHolder holder;
if (null == v) {
v = LayoutInflater.from(getContext()).inflate(R.layout.weather_row, parent, false);
TextView cityControl = (TextView)v.findViewById( R.id.city );
TextView temperatureControl = (TextView)v.findViewById( R.id.temperature );
ImageView skyControl = (ImageView)v.findViewById( R.id.sky );
holder = new ViewHolder(cityControl, temperatureControl, skyControl);
v.setTag(holder);
} else {
holder = (ViewHolder) v.getTag();
}
holder.cityControl.setText("Metropolis");
holder.temperatureControl.setText("78");
holder.skyControl.setImageResource(R.drawable.daily_planet);
return v;
}
有关更多示例(以及其他优化提示),请参阅this blog post(或只是google for ViewHolder)。