我正在研究编写一个自定义的适配器来填充每行3个textviews的列表视图。 我已经find了相当多的示例代码来做到这一点,但似乎最好的代码是: http : //www.anddev.org/custom_widget_adapters-t1796.html
经过一些小的调整,以解决最新的Android SDK的一些编译器问题,我得到它运行,只是为了得到exception:
ERROR / AndroidRuntime(281):java.lang.UnsupportedOperationException:addView(View,LayoutParams)在AdapterView中不受支持
所以我做了大量的研究,并find了很多可能的原因和解决办法。 没有一件事改变了。 我的适配器代码目前是:
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; } }
所以我试了一下把注射器的注意方式和目前的注释掉了。 我曾尝试通过“父”来夸大和空,并通过“真”,“假”,完全省略最后一个参数。 他们都没有工作,而我迄今发现的所有例子都是从2008年开始的,我感觉有些过时了。
如果有人可以帮助,那么我很乐意解决这个问题。
我也是一个初学者,所以拿一点盐的这个答案 – 如果它不工作,继续和谷歌一些。 不熟悉AdapterView
因为我传统上有一个ListView
或GridView
和一个自定义适配器扩展BaseAdapter
然后listView.setAdapter(myCustomAdapter)
。
你可以尝试在WeatherAdapter
类中做这样的事情:
public void addToList(Weather mWeather) { weatherList.add(mWeather); }
然后在调用WeatherAdapter
的类中:
weatherAdapter.addToList(weatherToAdd); weatherAdapter.notifyDataSetChanged();
你也需要在getView方法中进行更多的优化:
我相信这条线是错的:
View v = inflater.inflate(R.layout.weather_row, null, true);
您需要改为:
View v = inflater.inflate(R.layout.weather_row, parent, false);
虚假使膨胀的视图独立于父,而不是附加到它,这非常奇怪似乎是AdapterView
视图内自定义视图的公认的devise。 为什么这是这样,我觉得非常莫名其妙,但上面的模式为我工作。
对于AdaptertView addView
方法:
void addView(View child)
此方法不受支持,并在调用时引发UnsupportedOperationException。“(来自Android文档)
可能膨胀过程调用addView
方法,这是不可能从一个AdapterView
,或它的AdapterView
。
从文档:
“Adapter对象充当AdapterView和该视图底层数据之间的桥梁,Adapter提供对数据项的访问,Adapter也负责为数据集中的每个项目创build一个View。
我认为膨胀操作可以从一个简单的Activity来完成,这个简单的Activity可以模拟你的视图和所有其他操作,例如检索数据并在其他类中显示数据。
希望它会有帮助!
@ 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;
}
对于更多的例子(和其他优化技巧),请参阅此博客文章 (或只是谷歌的ViewHolder)。