我有一个让我疯狂的奇怪问题。在我的Android应用程序中,我定制了自己的适配器,它从ArrayAdapter扩展而来。我添加了适配器的ListView项可以标记为文本(不可编辑),可编辑文本或微调器。 疯狂的东西是:当我滚动ListView时,有两个问题:
(1)微调器项目中显示的(强选)值 更改有时虽然我只滚动!!当我点击微调器时,仍会显示旧的选定值(一个应该由微调器显示) (2)滚动时ListViewItems 的顺序更改!
=>但是适配器中的数据不会改变(数据本身和订单都没有) - 所以它一定是View本身的问题?!也许android缓存在后台并且不会很快刷新ListViewItems或者像那样?!
有人可以帮帮我吗?
很多!
好的,我找到了一个不太好的解决方案,但它确实有效。我只是不再使用convertView,尽管这对于内存和性能来说并不是最理想的。在我的情况下它应该没问题,因为我的ListView的最大项目数量是15。 这是我的Adapter-Class:
public class FinAdapter extends ArrayAdapter<Param>{
public Param[] params;
private boolean merkzettel;
protected EditText pv;
public FinAdapter(Context context, int textViewResourceId, Param[] items, boolean merkzettel) {
super(context, textViewResourceId, items);
this.params = items;
this.merkzettel = merkzettel;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final Param p = params[position];
if(p != null){
if(merkzettel){
if (convertView == null) {
LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(R.layout.merk_det_item, null);
}
TextView tvl = (TextView) convertView.findViewById(R.id.paramM);
TextView edl = (TextView) convertView.findViewById(R.id.param_valueM);
TextView pal = (TextView) convertView.findViewById(R.id.param_unitM);
if (tvl != null) {
tvl.setText(p.getName());
}
if(pal != null){
pal.setText(p.getUnit());
}
if(edl != null){
edl.setText(p.getDefData());
}
}
else{
if(p.isSelect()){
if (convertView == null) {
LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(R.layout.fin_prod_list_item_select, null);
}
TextView tvs = (TextView) convertView.findViewById(R.id.paramS);
Spinner sp = (Spinner) convertView.findViewById(R.id.spinner_kalk);
TextView paU = (TextView) convertView.findViewById(R.id.param_unitS);
if (tvs != null) {
tvs.setText(p.getName());
}
if(paU != null){
paU.setText(p.getUnit());
}
if(sp != null){
String[] values = new String[p.getData().size()];
for(int i=0; i<values.length; i++){
values[i] = p.getData().get(i);
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this.getContext(), android.R.layout.simple_spinner_item, values);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
sp.setAdapter(adapter);
sp.setSelection(p.getData().indexOf(p.getDefData()));
sp.setOnItemSelectedListener(new OnItemSelectedListener(){
public void onItemSelected(AdapterView<?> parent,
View convertView, int pos, long id) {
p.setDefData(p.getData().get(pos));
p.setChanged(true);
}
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
});
}
}
else if(p.isEdit()){
if (convertView == null) {
LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(R.layout.fin_prod_list_item_edit, null);
}
TextView pa = (TextView) convertView.findViewById(R.id.param);
pv = (EditText) convertView.findViewById(R.id.param_value);
TextView paE = (TextView) convertView.findViewById(R.id.param_unit);
if (pa != null) {
pa.setText(p.getName());
}
if(paE != null){
paE.setText(p.getUnit());
}
if(pv != null){
pv.setText(p.getDefData());
pv.setOnEditorActionListener(new OnEditorActionListener(){
public boolean onEditorAction(TextView convertView, int actionId,
KeyEvent event) {
// TODO Auto-generated method stub
p.setDefData(pv.getText().toString());
p.setChanged(true);
return false;
}
});
}
}
else if(p.isLabel()){
if (convertView == null) {
LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(R.layout.fin_prod_list_item_label, null);
}
TextView tvl = (TextView) convertView.findViewById(R.id.paramL);
TextView edl = (TextView) convertView.findViewById(R.id.param_valueL);
TextView pal = (TextView) convertView.findViewById(R.id.param_unitL);
if (tvl != null) {
tvl.setText(p.getName());
}
if(pal != null){
pal.setText(p.getUnit());
}
if(edl != null){
edl.setText(p.getDefData());
}
}}
}
return convertView;
}
}
答案 0 :(得分:5)
我在列表中有多个项目类型的类似问题。在我的例子中,列表项是部分(标签)项或公共列表项。
要使用此类类型的列表,您应该覆盖getViewTypeCount
和getItemViewType
方法。
像这样:
private static final int ITEM_VIEW_TYPE_ITEM = 0;
private static final int ITEM_VIEW_TYPE_SEPARATOR = 1;
@Override
public int getViewTypeCount() {
return 2;
}
@Override
public int getItemViewType(int position) {
return this.getItem(position).isSection() ? ITEM_VIEW_TYPE_SEPARATOR : ITEM_VIEW_TYPE_ITEM;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final Item item = this.getItem(position);
if (convertView == null) {
convertView = mInflater.inflate(item.isSection() ? R.view1 : R.view2, null);
}
if(item.isSection()){
//...
}
else{
//...
}
return convertView;
}
然后convertView参数将始终正确并包含您需要的类型。
另一件事:当您已在基类public Param[] params
中使用ArrayAdapter<Param>
字段时,您明确添加了该字段。
我建议继承BaseAdapter
类。
修改强>
以下是您可以尝试使用Spinner
工作的代码:
sp.setTag(p);
sp.setOnItemSelectedListener(new OnItemSelectedListener(){
public void onItemSelected(AdapterView<?> parent, View convertView, int pos, long id) {
Param currentItem = (Param)parent.getTag();
currentItem.setDefData(currentItem.getData().get(pos));
currentItem.setChanged(true);
}
//...
尝试使用getTag
和setTag
方法的组合。我记得我在事件处理程序和最终变量方面遇到了类似的问题,但是我完全忘记了它们的原因,所以我无法解释为什么会发生这种情况。
答案 1 :(得分:1)
如Sam所述,Android系统总是尽可能地回收以节省资源。
这意味着,开发人员需要自己跟踪View
ListView
。
对于实体或所谓的表示数据结构,您可以有一些东西来跟踪所选/取消选择的状态,例如:
class PresentationData {
// other stuffs..
boolean isSelected = false;
}
将这些数据结构映射到Adapter
,如果点击了任何项目,请将状态设置为true:listPresentationData.get(selected_position).isSelected = true
好的,在适配器的getView()
中,请正确跟踪您的数据的演示文稿。
if(listPresentationData.get(position).isSelected)
{
// set background color of the row layout..or something else
}
另外,值得一提的是,每个视图都有一个内存缓存,通常称为ViewHolder
,以提高性能。
答案 2 :(得分:0)
正如大家所说,Android会回收视图。这意味着什么?假设您的列表中有10个项目,但屏幕上仅显示3个项目。向下滚动时,第一个将消失,而第四个将出现。第四项已经在Android系统中,但是第五项是从第一项使用相同的视图创建的。 就我而言,我有一个具有默认背景的TextView。但是如果满足某些条件,我会更改背景。
@Override
public View getView(int position, View convertView, ViewGroup parent) {
...
if (someCondition) {
holder.textView.setBackground(R.drawable.different_background)
}
...
}
问题在于,如果不满足条件,我不会设置默认背景(因为我认为为每个项目都创建了视图)。当第一个项目的条件为true时,就会出现问题,因此将回收的视图与different_background而不是默认背景一起使用。为避免此问题,我必须始终设置条件的两个分支并按如下所示设置默认值:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
...
if (someCondition) {
holder.textView.setBackground(R.drawable.different_background)
} else {
holder.textView.setBackground(R.drawable.default_background)
}
...
}