Problem Description:
I am facing some problem with AutoCompleteTextView where I have to show suggestions after each keypress.
Thing is that, list of suggestion is dynamic like google's suggestion feature.
It means the new suggestions should be added as user keeps typing in plus all matching old suggestions should be displayed.
For example
I write "te" and then it should display previous suggestions like "test1" & "test2" and the new suggestions that I will get from Web API. Suppose web api gives me word "tea"& "tension ".
Now the AutoCompleteTextView will have "te" as string with all four suggestions showing below it.
This is exactly what I am looking for.
looks simple but it is showing a strange behaviour.
I am using default ArrayAdapter class instance of which I am declaring globally.
arrayAdapter=new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line,suggestions);
word.setAdapter(arrayAdapter);
suggestions is ArrayList.
Upon getting new result from WebApi I simply call
arrayAdapter.notifyDataSetChanged();
to refresh the data observer and views attached with this (in our case AutoCompleteListView).
But it closes suggestions.
When I don't use notifyDataSetChanged(); it is showing all suggestions regardless of characters I have typed.
I tried it with custom filter as many suggested but none of them is helpful as I couldn't use notifyDataSetChanged().
I am posting an image to avoid confusions.
I have a confusion that why notifyDataSetChanged(); its not working. I haven't use any other reference of list with same arrayAdapter instance. I really doubt if it's a reference problem.
one of the easiest way of doing that (put the code in onCreate):
EDIT: addied wikipedia free opensearch (if https://en.wikipedia.org doesn't work try http://en.wikipedia.org)
AutoCompleteTextView actv = new AutoCompleteTextView(this);
actv.setThreshold(1);
String[] from = { "name", "description" };
int[] to = { android.R.id.text1, android.R.id.text2 };
SimpleCursorAdapter a = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_2, null, from, to, 0);
a.setStringConversionColumn(1);
FilterQueryProvider provider = new FilterQueryProvider() {
#Override
public Cursor runQuery(CharSequence constraint) {
// run in the background thread
Log.d(TAG, "runQuery constraint: " + constraint);
if (constraint == null) {
return null;
}
String[] columnNames = { BaseColumns._ID, "name", "description" };
MatrixCursor c = new MatrixCursor(columnNames);
try {
String urlString = "https://en.wikipedia.org/w/api.php?" +
"action=opensearch&search=" + constraint +
"&limit=8&namespace=0&format=json";
URL url = new URL(urlString);
InputStream stream = url.openStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
String jsonStr = reader.readLine();
// output ["query", ["n0", "n1", ..], ["d0", "d1", ..]]
JSONArray json = new JSONArray(jsonStr);
JSONArray names = json.getJSONArray(1);
JSONArray descriptions = json.getJSONArray(2);
for (int i = 0; i < names.length(); i++) {
c.newRow().add(i).add(names.getString(i)).add(descriptions.getString(i));
}
} catch (Exception e) {
e.printStackTrace();
}
return c;
}
};
a.setFilterQueryProvider(provider);
actv.setAdapter(a);
setContentView(actv, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
You have impletent the custome filter in the child class of ArrayAdapter, there in perform filter method you have to do network call and get data from server. You can set this data in your main arraylist.
Related
I need some help. Im quite new to android and java.
Right now i have a csv code reader. The code will read the csv and then puts it into a Spinner. the csv file i have is example like this
1,"Easy"
2,"Medium"
3,"Hard"
4, "Very Hard
My Code
try{
InputStreamReader csvStreamReader = new InputStreamReader(MainActivity.this.getAssets().open("Category.csv"));
CSVReader reader = new CSVReader(csvStreamReader);
Log.d("test", "reading csv");
String [] nextLine;
List<String> list = new ArrayList<String>();
while ((nextLine = reader.readNext()) != null) {
list.add(nextLine[0] + "," + nextLine[1]);} spinner1 =(Spinner)findViewById(R.id.spinner);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, list);
spinner1.setAdapter(adapter);
} catch (IOException e) {
e.printStackTrace();
}
The code works well. It does appear in the spinner.
Now i want to go a little further, i want to create a for loop the check the array for a particular text example "Medium". When the word is found, it will be stored into another array. I really cant figure out the code. Try searching for ideas in this forum but fail. Can some one give me some pointers, preferred a sample code.
i have a listview with data from database using an sqlite.
when first time (onCreate()) i show the data, there`s no problems, the data all shown.
the problem is, when i want to filter my list view using datepicker and button, the listview not change the data.
ive use listview.invalidateViews(), notifyDataSetChanged()... but still not solved yet. maybe theres some mistake with my code... hope you guys can give me some solution.
thx...
here`s my code
Getting Data From DataBase
public ArrayList<BonRokokModel> getBonRokokList(String userGUID, String transDate, String searchText){
dbPath = "/data/data/app.chameleon.mobile/databases/";
dbName = "SalesTrans.sqlite";
bonRokok = SQLiteDatabase.openDatabase(dbPath + dbName, null,SQLiteDatabase.OPEN_READWRITE);
String strQuery;
strQuery = "SELECT BonRokokID, TransDate, Gudang, Status FROM tblSATBonRokok WHERE UserGUID = ? AND TransDate = ?";
// if(!searchText.equals("")){
// strQuery += "AND (BonRokokID LIKE %'"+ searchText +"'% ) ORDER BY TransDate DESC, BonRokokID Desc";
// }
ArrayList<BonRokokModel> listRokok = new ArrayList<BonRokokModel>();
Cursor mCursor = bonRokok.rawQuery(strQuery, new String[]{userGUID, transDate});
if(mCursor.moveToFirst()){
do {
BonRokokModel dataRokok = new BonRokokModel();
dataRokok.setBonRokokID(mCursor.getString(mCursor.getColumnIndex("BonRokokID")));
dataRokok.setTransDate(mCursor.getString(mCursor.getColumnIndex("TransDate")));
dataRokok.setGudang(mCursor.getString(mCursor.getColumnIndex("Gudang")));
dataRokok.setStatus(mCursor.getString(mCursor.getColumnIndex("Status")));
listRokok.add(dataRokok);
} while (mCursor.moveToNext());
}
bonRokok.close();
return listRokok;
}
My Code to Get Data
public void settingTabItem() {
listView = (ListView) findViewById(R.id.bonRokokMain_lvMain);
listviewMain = new ArrayList<BonRokokModel>();
listviewMain = bonRokokDAO.getBonRokokList(Main_Login.userGUID,utilities.convertDateToDateDBString(edt1.getText().toString()),"");
BonRokokListAdapter adapter = new BonRokokListAdapter(this, listviewMain);
listView.setAdapter(adapter);
}
thank you
Try like this ..
ListArrayAdapter.clear(); // Clear your adapter
ListArrayAdapter.addAll(newItems); // Add new items to it
ListArrayAdapter.notifyDataSetChanged(); // Notify List view for new items in list
OR
You can update list view like this also ..
Firstly clear your list view ..
Then after fetching new data .... create complete list view again.
Use the logical of method settingTabItem() on refresh method. Don't forget to clear the listview. Sorry for the bad English.
I am working on android project and am making using of a ListView that retrieves data from the SQLite database.
I am making a dataset using an ArrayList and then adding this ArrayList into an ArrayAdapter.
When the data is being retrieved from the database, I am telling SQLite to do the sorting so everything is in alphabetical order when it is added into the ListView. At certain times, the information will be added dynamically to to the ListView without it requiring to re-fetch everythin from the database again. However, I want to keep everything in alphabetical order.
How would I do this, do I sort the DataSet and then call the notifyDataSet Changes or do I do the sort directly on the ArrayAdapter. I've looked into performing the sort on the ArrayAdapter but this wants an argument that uses a Comparator but not sure what this is and can't find any working examples that may be of any help for what I want to achieve.
Below is the code that populates the array and sets the list adapter
ArrayList<Spanned> passwords = managePasswordList.getPasswordList();
if (passwords != null && passwords.size() > 0)
{
passwordArrayAdapter = new ArrayAdapter<Spanned>(getActivity().getApplicationContext(),
android.R.layout.simple_list_item_activated_1, passwords);
setListAdapter(passwordArrayAdapter);
myListView.setTextFilterEnabled(true);
txtNoRecords.setVisibility(View.GONE);
}
else
{
txtNoRecords.setVisibility(View.VISIBLE);
}
I am then adding data to the dataset and refreshing the list view using the following
String company = Encryption.decrypt(passwords.get(i).company);
String username = Encryption.decrypt(passwords.get(i).username);
details = Html.fromHtml(company + "<br />" + "<small><font color=\"#767676\">" + username + "</b></small>");
passwords.add(details);
passwordArrayAdapter.notifyDataSetChanged();
Thanks for any help you can provide.
UPDATE 1
I've tried doing what Nick Bradbury suggested but I am having a problem with the comparator. I have the following code but I don't know where to go from here.
SQLiteDatabase myDb = null;
Cursor cursor = null;
ArrayList<Spanned> passwords = new ArrayList<Spanned>();
try
{
myDb = context.openOrCreateDatabase("PasswordManager", Context.MODE_PRIVATE, null);
cursor = myDb.rawQuery("SELECT * FROM password ASC", null);
while (cursor.moveToNext())
{
final String company = Encryption.decrypt(cursor.getString(2));
final String username = Encryption.decrypt(cursor.getString(4));
Spanned details = Html.fromHtml(company + "<br />" + "<small><font color=\"#767676\">" + username + "</b></small>");
passwords.add(details);
Collections.sort(passwords, new Comparator<Spanned>() {
public int compare(Spanned lhs, Spanned rhs) {
return 0;
}
});
}
}
catch (SQLiteException ex)
{
common.showBasicAlertDialog("Unfortunately something has gone wrong.\n\nWe will fix this as soon as we can", false);
Log.e("Database Error", ex.toString());
return null;
}
In the return statement I have no idea what to do, I've tried return lhs.compareTo but the lhs and rhs variables don't have the compareTo function so I have not got a clue what to do.
Here's a simple example of sorting an ArrayList using Comparator. In this example, the ArrayList is defined as:
public class StatusList extends ArrayList<Status>
A sort routine for this ArrayList could look like this:
public void sort() {
Collections.sort(this, new Comparator<Status>() {
#Override
public int compare(Status item1, Status item2) {
return item2.getDate().compareTo(item1.getDate());
}
});
}
Replace <Status> with whatever object your ArrayList contains, then change the comparison to compare the values of the object you wish to sort by.
I'm working on this tutorial, it's about querying the mysql database by using Json and a php script, and everything is just fine, but I'm working on listing these results you see here in a ListView and not as a TextView as you see below. Thats seems easy, but I can't make it work by replacing TextView with ListView.
image:
Here is the tutorial (code inside) :
http://blog.erlem.fr/fr/applications-mobiles/android/27-android-blog/applications-mobiles/android/59-android-connexion-a-mysql-a-laide-de-php.html
All of the below assumes you have already parsed the JSON out into an array. See this for parsing help.
ListViews use adapters to grab the elements to fill the list rows up with. You'll have to feed the JSON results into a SimpleListAdapter via a List or array (ArrayList, what have you.).
from this page about listviews:
SimpleAdapter nommes = new SimpleAdapter(
this,
list,
R.layout.main_item_two_line_row,
new String[] { "line1","line2" },
new int[] { R.id.text1, R.id.text2 } );
(in your case you could show/hide the id/name by using a one-line layout or a two-line layout like in this example)
Then apply the adapter
listView.setAdapter(nommes);
EDIT:
jObject = new JSONObject("<your JSON string from provider>");
// in my case:
res = jObject.getJSONObject("results");
**dataAdapter = new ArrayAdapter<String>(this, R.layout.item, R.id.itemName);**
try {
for (int r = 0; r < rslt.length(); r++){
JSONArray jA = rslt.getJSONArray(Integer.toString(r));
schoolLocString = jA.getString(0) +"|"+ jA.getString(1) +"[" + jA.optString(2);
**dataAdapter.add(schoolLocString);**
}
**myListView.setListAdapter(dataAdapter);**
} catch (JSONException e) {
Log.v(TAG, "Exception " + e);
} catch (NullPointerException e){
Log.v(TAG, "NPE, no rslt");
}
This is a really lazy way to do it and probably bad practice, but you can get the idea.
I am feeding a ListView from a database in this way (nothing special), except
COL_TXT_TRANSL2 contains html formatting:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle extras = getIntent().getExtras();
mCurrBookID = extras.getString("BookID");
mCurrChapterNum = extras.getString("ChapterNum");
mCurrChapterTitle = extras.getString("ChapterTitle");
mGitaDB= Central.mDB;
this.setTitle(mCurrChapterNum+"."+mCurrChapterTitle);
setContentView(R.layout.chapterdisplay);
//set chapter intro
TextView tvIntro=(TextView) findViewById(R.id.textIntro);
tvIntro.setText(Html.fromHtml(extras.getString("ChapterIntro")));
try {
String[] columns = new String[] { mGitaDB.COL_TXT_TEXT_NUM, mGitaDB.COL_TXT_TRANSL2 };
int[] to = new int[] { R.id.number_entry, R.id.title_entry };
mCursor=mGitaDB.GetGitaTexts(mCurrBookID, mCurrChapterNum);
mAdapter = new SimpleCursorAdapter(this,
R.layout.textslist_row, mCursor, columns, to);
setListAdapter(mAdapter);
}
catch (Exception e) {
String err="Error: " + e.getMessage();
Toast toast = Toast.makeText(Central.context, err, 15000);
toast.show();
}
}
Now the problem is that the text displayed in this ListView has HTML formatting.
How can I make listview display this HTML formatting? Currently it is displayed as a plain text with all tags.
Assuming the HTML is fairly simple you can run it through this method: http://developer.android.com/reference/android/text/Html.html#fromHtml(java.lang.String) The resulting Spannable can be sent to a TextView in the ListView. Beware the fromHtml method is very slow and may slow down scrolling, you might want to cache the Spannables.
Define a CharSequence ArrayList, include all the elements from your database to be displayed in this arraylist as HTML. Include a personal TextView layout for the individual entities of the listView, and display the Charsequence in the list. I had made use of the following code for my app:
List<CharSequence> styledItems = new ArrayList<CharSequence>();
droidDB.open();
articles = droidDB.getAllArticleTitles(feed.feedId);
droidDB.close();
for (Article article : articles) {
styledItems.add(Html.fromHtml(article.title));
}
ArrayAdapter<CharSequence> notes =
new ArrayAdapter<CharSequence>(this, R.layout.feeds_row,styledItems);
setListAdapter(notes);
For the feeds_row.xml:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="#FFFFFF"/>
Hope this helps.
My problem was similar to yours. I was reading data from file in json format, where I have objects with id and text fields. text field is html. I have resolved problem this way:
ArrayList<MyObject> myObjectsList = new ArrayList<MyObject>();
ArrayList<HashMap<String, CharSequence>> tableElements = new ArrayList<HashMap<String, CharSequence>>();
String keyword = in.getStringExtra(TAG_KEYWORD);
InputStream is = this.getResources().openRawResource(R.raw.data);
JSONParser jParser = new JSONParser();
myObjectsList = jParser.searchForObjects(is, keyword);
for (MyObject element : myObjectsList)
{
String id = Integer.toString(element.id);
CharSequence text = Html.fromHtml(element.text);
// creating new HashMap
HashMap<String, CharSequence> map = new HashMap<String, CharSequence>();
// adding each child node to HashMap key => value
map.put(TAG_ID, id);
map.put(TAG_TEXT, text);
// adding HashList to ArrayList
tableElements.add(map);
}
ListAdapter adapter = new SimpleAdapter(this,tableElements,
R.layout.search_item,
new String[] { TAG_ID, TAG_TEXT.toString()}, new int[] {
R.id.exercise_id, R.id.text });
setListAdapter(adapter);