我的ListView
有几个问题。我将首先通过解释ListView
的目标来解释我的问题,然后通过展示一些代码和图像来逐步解释。在页面的底部,我有与ListView相关的3个类的完整代码。
此ListView用于修改一系列公交车站。每行包含一个TextView
,其中包含公交车站的名称和Button
以消除它。如果用户点击TextView
,则此视图将替换为新布局。在这个新布局中,有一个EditText
用于插入一个新旧公交车站的名称,该公交车站将与旧公交车站交换。 EditText
旁边有一个按钮,用于完成操作。
问题:
TextView
,我也会删除所选内容(来自UI)下的行。这里有几张图片。
在此之前,我点击: 之后我点击TextView
:(应该有最后一行,包含Crocetta,但它已被删除,我不知道它何时发生,原因是什么){ {0}}
更新:我忘了说当您点击确定按钮时,ListView
变为第一张图片中的原样。即我可以看到似乎被淘汰的元素。
使用新布局管理视图替换的代码如下:
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): FATAL EXCEPTION: main
05-03 19:26:12.684: E/AndroidRuntime(1818): java.lang.IndexOutOfBoundsException: Invalid index 3, size is 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
的{{1}}的代码。此外,我发布了在这个类中膨胀的xml文件。
包含ListView的类
TextView
扩展ArrayAdapter的类
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;
}
}
实现OnClickListener的类
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();
}
}
elemento_modifica_linea.xml
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;
}
}
<?xml version="1.0" encoding="utf-8"?>
edit_text_modifica_fermata.xml
<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" />
我不知道我的问题是什么原因,你能帮帮我吗? 非常感谢你!
答案 0 :(得分:0)
关于问题2
您最好从BaseAdapter
而不是ArrayAdapter
延伸。有一个名为getCount()
的方法可以返回项目数,您必须实现它才能返回fermate.size()
。
我认为ArrayAdapter假定您最初传递的数组的计数,当您从数组中删除条目时,计数大于数组中的项目数,从而导致OutOfBoundsException
。
答案 1 :(得分:0)
好的,让我们从你的第二个问题开始吧。尝试覆盖适配器中的getCount()方法。 ListView在您的适配器中调用getCount方法,然后在调用getView()之后返回getCount()。尝试在适配器中添加这样的东西:
@Override
public int getCount() {
return fermate.size();
}
第二个问题怎么样?我认为在listView中删除和添加视图并不是一个好主意。更好的方法是在创建布局时添加EditText和TextView,并将EditText的可见性设置为GONE。然后单击简单更改TextView和EditText的可见性。它会更快,更轻松。
答案 2 :(得分:0)
要删除行,我建议您将适配器中的广播发送到活动中,并将行索引作为“额外”传递。然后,您可以正常从列表适配器中删除它并重置列表视图。在适配器内部进行操作可能会导致问题。