I'm working on an android application which shows a list view with data from SQL database.
After a click on a list view element, a new Activity opens with information about it.
I already implemented a Textwatcher
to do the search in a list and the list is updated as it should work.
The Problem is that when I click on a list element of updated list, it opens an activity with data from old position e.g by click on Zinn ID: 939. It opens a new Activity with Altbach ID: 940 data.
What is the best way to updated the position for the element after TextWatcher
works and pass it in onItemClick
method? Or how can I get the updated list after TextWatcher
works?
Thank you in advance!
That is my class.
public class LibraryActivity extends AppCompatActivity implements View.OnClickListener {
static String db_name = "test_stolpersteine_db.sqlite";
StolpersteineDAO stolpersteinedao;
List<Stolpersteine> stolpersteine_list;
ListView list_view;
private ArrayAdapter<CharSequence> adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_library);
////////////////////////////// Database ////////////////////////////////////////////////////
final File dbFile = this.getDatabasePath(db_name); // we create a database path
if (!dbFile.exists()) { // we checking if the directory is existing
try {
copyDatabaseFile(dbFile.getAbsolutePath()); // method to copy the database
} catch (IOException e) {
e.printStackTrace();
}
}
////// Database
startDatabase();
stolpersteine_list = stolpersteinedao.getAllStolpersteine();
list_view = findViewById(R.id.list);
adapter = createAdapterHtml(stolpersteine_list);
list_view.setAdapter(adapter);
////////////////////////////// Database ////////////////////////////////////////////////////
//////////////////////////// Buttons ///////////////////////////////////////////////////////
Button button_home = findViewById(R.id.button_home);
Button button_map = findViewById(R.id.button_map);
Button button_library = findViewById(R.id.button_library);
button_home.setOnClickListener(this);
button_map.setOnClickListener(this);
button_library.setOnClickListener(this);
button_library.setEnabled(false);
/////////////////////////// Buttons ////////////////////////////////////////////////////////
EditText theFilter = findViewById(R.id.edit_text);
theFilter.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
(LibraryActivity.this).adapter.getFilter().filter(charSequence);
}
@Override
public void afterTextChanged(Editable charSequence) {
}
});
//// OnClickListener
list_view.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String url = stolpersteine_list.get(position).getURL();
Intent i = new Intent(getApplicationContext(), RecordActivity.class);
i.putExtra("url", url);
i.putExtra("first_name", stolpersteine_list.get(position).getFirst_Name());
i.putExtra("name", stolpersteine_list.get(position).getName());
startActivity(i);
} // end of listener
});
} // end of onCreate method
////////////////////////////// Database ////////////////////////////////////////////////////////
private void copyDatabaseFile(String destinationPath) throws IOException {
InputStream assetsDB = this.getAssets().open(db_name);
OutputStream dbOut = new FileOutputStream(destinationPath);
byte[] buffer = new byte[1024];
int length;
while ((length = assetsDB.read(buffer)) > 0) {
dbOut.write(buffer, 0, length);
}
dbOut.flush();
dbOut.close();
} //end of copyDatabaseFile method
private ArrayAdapter<CharSequence> createAdapterHtml(List<Stolpersteine> s_list) {
Spanned[] html_array = new Spanned[s_list.size()];
for (int i = 0; i < s_list.size(); i++) {
html_array[i] = Html.fromHtml(
s_list.get(i).getName()
+ " "
+ "ID: "+ s_list.get(i).getID() + "<br></i>"
+ s_list.get(i).getHouse_Number() +" "
+ s_list.get(i).getHouse_Number_Extension() + "</i>");
}
ArrayAdapter<CharSequence> my_adapter =
new ArrayAdapter<CharSequence>(this, R.layout.list_item, html_array);
return my_adapter;
} // end of createAdapterHtml
private void startDatabase() {
AppDatabase database = Room.databaseBuilder(this, AppDatabase.class, db_name)
.allowMainThreadQueries()
.build();
stolpersteinedao = database.getStolpersteineDAO();
} // end of startDatabase method
////////////////////////////// Database ////////////////////////////////////////////////////////
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button_home:
startActivity(new Intent(this, MainActivity.class));
break;
case R.id.button_map:
startActivity(new Intent(this, MapboxActivity.class));
break;
case R.id.button_library:
startActivity(new Intent(this, LibraryActivity.class));
break;
}
}
} // end of class
The problem is that the onItemClick()
callback has a parameter of the position after filtering the list; i.e. this position is relative to the filtered list not the original list, although you need to get the actual position from the original list.
To get the original position (not the filtered one), you can get the filtered item first and get its position using indexOf()
from the original list.
To apply this, change the list_view
OnItemClickListener
to:
//// OnClickListener
list_view.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// Getting the clicked item from the filtered list
Stolpersteine filteredItem = (Stolpersteine) ((ListView) parent).getAdapter().getItem(position);
// Getting the original position
int originalPos = getList().indexOf(filteredItem);
// Use originalPos instead of position in your code:
String url = stolpersteine_list.get(originalPos).getURL();
Intent i = new Intent(getApplicationContext(), RecordActivity.class);
i.putExtra("url", url);
i.putExtra("first_name", stolpersteine_list.get(originalPos).getFirst_Name());
i.putExtra("name", stolpersteine_list.get(originalPos).getName());
startActivity(i);
} // end of listener
});