android - 无法消除 ListView 内的 View

标签 android android-listview android-arrayadapter layout-inflater

我的 ListView 有几个问题。我将首先通过解释 ListView 的目的来尝试解释我的问题,然后通过显示一些代码和图像来逐步解释我的问题。在页面底部,我有与 ListView 相关的 3 个类的完整代码。

此 ListView 用于修改一系列公交车站。每行包含一个带有公交车站名称的 TextView 和一个用于消除它的 Button。如果用户点击 TextView,此 View 将替换为新布局。在这个新布局中,有一个 EditText 用于插入将与旧巴士站交换的新巴士站的名称。 EditText旁边有一个按钮,用于完成操作。

问题:

  • 第一个问题:如果我尝试从 UI 中删除原始 TextView,我也会删除所选行下的行(从 UI)。这里有几张图片。 在此之前,我点击:enter image description here

然后我点击一个TextView:(应该是最后一行,包含Crocetta,但是它已经被删除了,我不知道它是什么时候发生的,是什么原因那个)enter image description here

更新:我忘了说,当您单击确定按钮时,ListView 变成了第一张图片中的样子。即我可以看到似乎已被消除的元素。

管理用新布局替换 View 的代码如下:

    ViewGroup parent = (ViewGroup) ((TextView)v).getParent();
    int index = parent.indexOfChild((TextView)v);   
    parent.removeView((TextView)v);

    final LinearLayout nuovoLiInserimento = (LinearLayout) li.inflate(R.layout.edit_text_modifica_fermata, parent, false);
    final AutoCompleteTextView nuovaFermata = (AutoCompleteTextView) nuovoLiInserimento.findViewById(R.id.edtModificaFermataInModificaLinea);
    Button confermaModificaFermata = (Button) nuovoLiInserimento.findViewById(R.id.btnModificaFermataInModificaLinea);
    nuovaFermata.setAdapter(new ArrayAdapter<String>(context,android.R.layout.simple_dropdown_item_1line, caricaFermate()));
    nuovaFermata.setText(fermataPrecedente);

    [...]

    parent.addView(nuovoLiInserimento, index);
  • 第二个问题:当我点击 Elimina Button 时会发生这种情况,其目的是删除它所在的行。我从 fermate 中删除数据,ArrayList 包含 ListView 的数据,然后调用 notifyDataSetChanged。当程序稍后进入 getView 时,出现以下错误:

    05-03 19:26:12.684: E/AndroidRuntime(1818): 致命异常: main 05-03 19:26:12.684: E/AndroidRuntime(1818): java.lang.IndexOutOfBoundsException: 索引 3 无效,大小为 3

因为getView调用次数多了一次,所以它搜索fermate中我删除的元素。如何避免这种情况?

这是一段代码:

private void eliminaFermata(View v){
    Toast.makeText(context, "elimina", Toast.LENGTH_LONG).show();       
    LinearLayout parent = (LinearLayout)((Button) v).getParent();
    TextView busStop = (TextView)(parent).findViewById(textViewDaCompletare);
    fermate.remove(fermate.indexOf(busStop.getText().toString()));
    this.notifyDataSetChanged();
}

最后我发布了 3 个类的代码:一个包含 ListViewArrayAdapter 和一个实现 OnClickListener TextView 。此外,我发布了在此类中膨胀的 xml 文件。

包含 ListView 的类

    package fragments;

import [...]

public class FragmentModificaLinea extends Fragment {

private Button btnModificaLinea = null;
private Button btnConfermaModifica = null;
private AutoCompleteTextView edtModificaLinea = null;
private ArrayList<String> contenitoreLinee;
private ListView listView;
@SuppressWarnings("unused")
private static final String TAG = FragmentModificaLinea.class.getSimpleName();


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    return inflater.inflate(R.layout.fragment_modifica_linea, container, false);
}

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    btnModificaLinea = (Button) getView().findViewById(R.id.btnModificaLinea);
    edtModificaLinea = (AutoCompleteTextView) getView().findViewById(R.id.edtModificaLinea);
    contenitoreLinee = new ArrayList<String>();
    caricaLinee();
    edtModificaLinea.setAdapter(new ArrayAdapter<String>(getActivity(),android.R.layout.simple_dropdown_item_1line, contenitoreLinee));
    listView = (ListView) getView().findViewById(R.id.listViewModificaLinea);
    btnConfermaModifica = (Button) getView().findViewById(R.id.btnConfermaModifica);

    btnModificaLinea.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            if(!edtModificaLinea.getText().toString().matches(""))
                if(contenitoreLinee.contains(edtModificaLinea.getText().toString())){
                    listView.setAdapter(new AdapterModificaLinea(getActivity(), R.layout.elemento_modifica_linea,
                            R.id.txtCambiaFermata, caricaFermate(edtModificaLinea.getText().toString().split(" Cod: ")[1])));
                    listView.setVisibility(ListView.VISIBLE);
                }else Toast.makeText(getActivity(), "Inserire una delle linee suggerite.", Toast.LENGTH_LONG).show();
            else Toast.makeText(getActivity(), "Inserire il nome della linea", Toast.LENGTH_LONG).show();
        }
    });
}

private void caricaLinee(){
    // I get the local database.
    DatabaseLocale db = new DatabaseLocale(getActivity());
    SQLiteDatabase dbLeggibile = db.getReadableDatabase();

    // Execute the query.
    Cursor cursore = dbLeggibile.rawQuery("SELECT " + DatabaseLocale.getTagNomeLinea() + " || ' Cod: ' || " + DatabaseLocale.getTagCodiceLinea()
            + " AS linea FROM " + DatabaseLocale.getTableNameLinea(), null);
    while(cursore.moveToNext()){
        contenitoreLinee.add(cursore.getString(0));
    }

    // Close connections.
    cursore.close();
    db.close();
}

private ArrayList<String> caricaFermate(String CodLinea){
    ArrayList<String> listaDelleFermate = new ArrayList<String>();

    // I get the local database.
    DatabaseLocale db = new DatabaseLocale(getActivity());
    SQLiteDatabase dbLeggibile = db.getReadableDatabase();

    Cursor fermate = dbLeggibile.rawQuery("SELECT f." + DatabaseLocale.getTagNomeFermata() + 
            " FROM " + DatabaseLocale.getTableNameTratta() + " t JOIN " + DatabaseLocale.getTableNameFermata() + " f "
            + "ON f." + DatabaseLocale.getTagCodiceFermata() + " = t." + DatabaseLocale.getTagCodiceFermata()
            + " WHERE " + DatabaseLocale.getTagCodiceLinea() + " = '" + CodLinea + "'", null);

    while(fermate.moveToNext()){
        // Successiva - NomeFermata
        listaDelleFermate.add(fermate.getString(0));        
    }
    fermate.close();
    db.close();

    return listaDelleFermate;
}

}

扩展ArrayAdapter的类

    package listViewModificaLinea;

import [...]

public class AdapterModificaLinea extends ArrayAdapter<String> {

Context context;
int layoutResourceId;   
int textViewDaCompletare;   
ArrayList<String> fermate = null;
private LayoutInflater li = null;

public AdapterModificaLinea(Context context, int resource,
        int textViewResourceId, List<String> objects) {
    super(context, resource, textViewResourceId, objects);
    this.context = context;
    layoutResourceId = resource;
    textViewDaCompletare = textViewResourceId;
    fermate = new ArrayList<String>(objects);   
    li = ((LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE));
}

@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    TextView text = null;
    Button btn = null;
    if(convertView == null){
        convertView = li.inflate(layoutResourceId, null);
    }
    text = (TextView) convertView.findViewById(textViewDaCompletare);
    // If I delete an element from fermate, it looks however for it and I get outofbound, why?
    String fermata = fermate.get(position);
    text.setText(fermata);
    // If I click on the textView, I exchange with the new layout
    text.setOnClickListener(new onClickListenerPerTextViewFermata(context, textViewDaCompletare));

    btn = (Button) convertView.findViewById(R.id.btnEliminaFermataModificaLinea);
    btn.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            eliminaFermata(v);
        }
    });

    return convertView;
}

private void eliminaFermata(View v){
    Toast.makeText(context, "elimina", Toast.LENGTH_LONG).show();       
    LinearLayout parent = (LinearLayout)((Button) v).getParent();
    TextView busStop = (TextView)(parent).findViewById(textViewDaCompletare);
    fermate.remove(fermate.indexOf(busStop.getText().toString()));
    this.notifyDataSetChanged();
}


}

实现OnClickListener的类

    package listViewModificaLinea;

import [...]

public class onClickListenerPerTextViewFermata implements View.OnClickListener{

private Context context = null;
private LayoutInflater li = null;
private int textViewDaCompletare = 0;

public onClickListenerPerTextViewFermata(Context context, int textViewResourceId){
    this.context = context;
    li = ((LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE));
    this.textViewDaCompletare = textViewResourceId;
}

@Override
public void onClick(View v) {

    String fermataPrecedente = ((TextView)v).getText().toString();  
    ViewGroup parent = (ViewGroup) ((TextView)v).getParent(); // parent
    int index = parent.indexOfChild((TextView)v);       
    parent.removeView((TextView)v);  // I remove it

        // new layout
    final LinearLayout nuovoLiInserimento = (LinearLayout) li.inflate(R.layout.edit_text_modifica_fermata, parent, false);
    // AutoCompleteTextView and Button, I put the adapter for the AutoCompleteTextView
    final AutoCompleteTextView nuovaFermata = (AutoCompleteTextView) nuovoLiInserimento.findViewById(R.id.edtModificaFermataInModificaLinea);
    Button confermaModificaFermata = (Button) nuovoLiInserimento.findViewById(R.id.btnModificaFermataInModificaLinea);
    nuovaFermata.setAdapter(new ArrayAdapter<String>(context,android.R.layout.simple_dropdown_item_1line, caricaFermate()));
    nuovaFermata.setText(fermataPrecedente);

    // click listener al bottone
    confermaModificaFermata.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {

            // text of AutoCompleteTextView
            String fermata = nuovaFermata.getText().toString();
            // layout edit_text_modifica_fermata, later layout inside the listview              ViewGroup parent = (ViewGroup)(((Button)v).getParent()).getParent();
            int index = parent.indexOfChild(nuovoLiInserimento);
            parent.removeView(nuovoLiInserimento);
            TextView fermataCambiata = new TextView(context);
            fermataCambiata.setText(fermata);
            fermataCambiata.setId(textViewDaCompletare);
                        // i  add this OnClickListener
            fermataCambiata.setOnClickListener(new onClickListenerPerTextViewFermata(context,  textViewDaCompletare));
            parent.addView(fermataCambiata, index);
        }
    });

    // aggiungo il nuovo layout al parent
    parent.addView(nuovoLiInserimento, index);
}

private ArrayList<String> caricaFermate(){
    ArrayList<String> listaDelleFermate = new ArrayList<String>();

    DatabaseLocale db = new DatabaseLocale(context);
    SQLiteDatabase dbLeggibile = db.getReadableDatabase();

    // Tutte le fermate
    Cursor fermate = dbLeggibile.rawQuery("SELECT " + DatabaseLocale.getTagNomeFermata() + 
            " FROM " + DatabaseLocale.getTableNameFermata(), null);

    while(fermate.moveToNext()){
        listaDelleFermate.add(fermate.getString(0));        
    }
    fermate.close();
    db.close();

    return listaDelleFermate;
}

}

elemento_modifica_linea.xml

<?xml version="1.0" encoding="utf-8"?>

<TextView
    android:id="@+id/txtCambiaFermata"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="" />

<Button
    android:id="@+id/btnEliminaFermataModificaLinea"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/eliminaFermataInModificaLinea" />

edit_text_modifica_fermata.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/LinearLayout1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >

    <TextView
        android:id="@+id/txtCambiaFermata"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="" />

    <Button
        android:id="@+id/btnEliminaFermataModificaLinea"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/eliminaFermataInModificaLinea" />

</LinearLayout>

我不知道我的问题是什么原因造成的,你能帮帮我吗? 非常感谢!

最佳答案

关于问题2

您最好从 BaseAdapter 而不是 ArrayAdapter 进行扩展。有一个名为 getCount() 的方法可以返回项目的数量,您必须实现它才能返回 fermate.size()

我认为 ArrayAdapter 假定您最初传递的数组的计数,当您从数组中删除条目时,计数大于数组中的项目数,从而导致 OutOfBoundsException

关于android - 无法消除 ListView 内的 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23449110/

相关文章:

安卓 Ice Cream Sandwich : why ListView items remain selected by default?

java - ListView 行不可点击(添加两个按钮后)

android - 如何在扩展 ArrayAdapter<String> 的类中获取共享首选项

android - Array List Adapter - 如何实例化一个对象?

android - 在回收站 View 中更新微调器

android - Android 上应用程序管理器中的图标未从 phonegap 中的默认值更改

java - 如何在 Android 中使用 httpclient "log out"?

android - 如何在应用程序最小化时暂停/停止收集/发送流中的数据?

java - 将数组列表从一个 Activity 发送到另一个 Activity 到 ListView android中

Android - 唤醒锁线程没有打开屏幕