我的 ListView
有几个问题。我将首先通过解释 ListView
的目的来尝试解释我的问题,然后通过显示一些代码和图像来逐步解释我的问题。在页面底部,我有与 ListView 相关的 3 个类的完整代码。
此 ListView 用于修改一系列公交车站。每行包含一个带有公交车站名称的 TextView
和一个用于消除它的 Button
。如果用户点击 TextView
,此 View 将替换为新布局。在这个新布局中,有一个 EditText
用于插入将与旧巴士站交换的新巴士站的名称。 EditText
旁边有一个按钮,用于完成操作。
问题:
- 第一个问题:如果我尝试从 UI 中删除原始
TextView
,我也会删除所选行下的行(从 UI)。这里有几张图片。 在此之前,我点击:
然后我点击一个TextView
:(应该是最后一行,包含Crocetta,但是它已经被删除了,我不知道它是什么时候发生的,是什么原因那个)
更新:我忘了说,当您单击确定按钮时,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 个类的代码:一个包含 ListView
、ArrayAdapter
和一个实现 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/