I created an app that has an autoCompleteTextView in order to allow the user to perform search queries.
Once they start typing, a dropdown appears and offers the results.
Now, I would like to make the first item to be fixed and unscrollable which will say something like: can't find? add manually.
How can I make the first item in the suggested dropdown list to be fixed and appear always?
My code for the adapter is:
public class AutoCompleteImageAdapter extends ArrayAdapter<String> implements Filterable {
private ArrayList<String> fullList;
private ArrayList<String> mOriginalValues;
private ArrayFilter mFilter;
private Boolean noResults;
private TextView tv_name;
private ImageView im_cover;
private List<String> url, id;
private StorageReference storageRef;
private FirebaseFirestore db;
public AutoCompleteImageAdapter(Context context, int resource, int textViewResourceId, List<String> objects, List<String> url, List<String> id, Boolean noResult) {
super( context, resource, textViewResourceId, objects );
fullList = (ArrayList<String>) objects;
mOriginalValues = new ArrayList<String>( fullList );
noResults = noResult;
this.url = url;
this.id = id;
}
#Override
public int getCount() {
if (fullList.size() > 40) {
return 40;
} else {
return fullList.size();
}
}
#Override
public String getItem(int position) {
return fullList.get( position );
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
db = FirebaseFirestore.getInstance();
storageRef = FirebaseStorage.getInstance().getReference();
View row = convertView;
String id = this.id.get( position );
LayoutInflater inflater = LayoutInflater.from( getContext() );
if (row == null) {
row = inflater.inflate( R.layout.item_auto_add, parent, false );
}
tv_name = (TextView) row.findViewById( R.id.item_drop );
tv_name.setText( fullList.get( position ) );
im_cover = row.findViewById( R.id.iv_itemCover );
String Url = url.get( position );
if (id.length() > AppConstants.UPLOADED_item_LENGTH) {
storageRef.child( "/itemCovers/" + Url + "/" + Url + ".jpg" ).getDownloadUrl().addOnSuccessListener( new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
Picasso.with( parent.getContext() ).load( uri ).resize( 110, 160 ).into( im_cover );
}
} ).addOnFailureListener( new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
Log.d( "ERROR", exception + "" );
}
} );
} else {
Picasso.with( parent.getContext() ).load( Uri.parse( Url ) ).error( R.drawable.ic_nocover ).resize( 110, 160 ).into( im_cover );
}
return row;
}
#Override
public Filter getFilter() {
if (mFilter == null) {
mFilter = new ArrayFilter();
}
return mFilter;
}
private class ArrayFilter extends Filter {
private Object lock;
#Override
protected FilterResults performFiltering(CharSequence prefix) {
FilterResults results = new FilterResults();
if (mOriginalValues == null) {
synchronized (lock) {
mOriginalValues = new ArrayList<String>( fullList );
}
}
if (prefix == null || prefix.length() == 0) {
synchronized (lock) {
ArrayList<String> list = new ArrayList<String>( mOriginalValues );
results.values = list;
results.count = list.size();
}
} else {
final String prefixString = prefix.toString().toLowerCase();
ArrayList<String> values = mOriginalValues;
int count = values.size();
ArrayList<String> newValues = new ArrayList<String>( count );
for (int i = 0; i < count; i++) {
String item = values.get( i );
if (item.toLowerCase().contains( prefixString )) {
newValues.add( item );
}
}
results.values = newValues;
results.count = newValues.size();
}
return results;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if (results.values != null) {
fullList = (ArrayList<String>) results.values;
} else {
fullList = new ArrayList<String>();
}
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
}
public void clear() {
if (fullList != null) {
fullList.clear();
notifyDataSetChanged();
}
}
}
Thank you
add it as the first item to your List objects before you pass it to the adapter and then populate the list with data you wanna show as search result so that element 0 is always "can't find? add manually". This way it is always there and the other items change.
and then in the item click listener you can check for the item text and act accordingly if it matches "can't find? add manually".
I think the code below solves your requirement to some level. Do try and comment.
<AutoCompleteTextView
android:layout_below="#+id/edit_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/project"
android:id="#+id/edit_project"
android:completionThreshold="0"
android:completionHint="#string/message"
android:inputType="text"
/>
This code gives a hint at the bottom of the list to the user.
Related
I use a recyclerview which I modify thanks to Diffutils. Unfortunately, when I filter my recyclerview and delete items, the index of the deleted items does not match that of my list.
For instance, if I have 3 items: [a, ab,abc] with the index (0,1,2) and I filter with the word "ab", the newly displayed items are [ab, abc] with the index (0,1) so when I try to delete items from the recyclerView, index are wrong.
This is a part of my recycler code
public class NoteListAdapter extends RecyclerView.Adapter<NoteListAdapter.NoteListViewHolder> implements Filterable {
private List<Note> noteList;
private List<Note> noteListFull;
private NoteEventListener listener;
private CustomFilter filter;
public NoteListAdapter(List<Note> noteList, NoteEventListener noteEventListener) {
this.noteList = noteList;
this.noteListFull = noteList;
this.listener = noteEventListener;
}
public void updateList(List<Note> newList) {
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new DiffUtils(this.noteList, newList));
noteList.clear();
noteList.addAll(newList);
diffResult.dispatchUpdatesTo(this);
}
public void insertList(List<Integer> index, List<Note> newList) {
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new DiffUtils(this.noteList, newList));
for (int i =0; i < newList.size(); i++)
noteList.add(index.get(i), newList.get(i));
diffResult.dispatchUpdatesTo(this);
}
#Override
public void onBindViewHolder(#NonNull final NoteListViewHolder holder, int position) {
final Note note = noteList.get(position);
if (note != null) {
holder.itemView.setOnClickListener(v -> listener.onNoteClick(position, note));
holder.itemView.setOnLongClickListener(v -> {
listener.onNoteLongClick(position, note);
return true;
});
}
}
#Override
public Filter getFilter() {
if(filter == null)
filter = new CustomFilter();
return filter;
}
class CustomFilter extends Filter {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults filterResults = new FilterResults();
if(constraint == null || constraint.length() == 0) {
filterResults.values = noteListFull;
filterResults.count = noteListFull.size();
}
else {
String pattern = constraint.toString().toLowerCase();
List<Note> filters = new ArrayList<>();
for(Note item: noteListFull) {
if (item.getTitle().toLowerCase().contains(pattern)) {
Note n = new Note(item.getTitle(), item.getContent());
filters.add(n);
}
}
filterResults.values = filters;
filterResults.count = filters.size();
}
return filterResults;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
noteList = (List) results.values;
notifyDataSetChanged();
}
}
}
And this is my code when I delete an item:
private void delete_note() {
// Position of all selected items ready to be deleted (but with wrong index)
List<Integer> selectedItems = noteListAdapter.getSelectedItems();
List<Note> temp = new ArrayList<>(notes);
List<Note> deletedItems = selectedItems.stream().map(notes::get).collect(Collectors.toList());
temp.removeAll(deletedItems);
noteListAdapter.updateList(temp);
}
I implemented the displaying contacts with checkboxes. When I selected the multiple contacts and click the button it shows this error "
Attempt to invoke virtual method 'boolean
java.lang.Boolean.booleanValue()' on a null object reference"
. at mCustomAdapter.mCheckedStates.get(i). So i wrote like this in adapter class is "
mCheckedStates = new LongSparseArray<>(ContactList.size())
And again it shows the same error after assigning some value. When I print the size of the mCustomAdapter.mCheckedStates.size it show the correct value of how many contacts I selected but when getting the value it shows the error. How to solve that?
This is My adapter class :
public class Splitadapter extends BaseAdapter implements Filterable,CompoundButton.OnCheckedChangeListener
{
// public SparseBooleanArray mCheckStates;
LongSparseArray<Boolean> mCheckedStates = new LongSparseArray<>();
private ArrayList<COntactsModel> ContactList;
private Context mContext;
private LayoutInflater inflater;
private ValueFilter valueFilter;
ArrayList<COntactsModel> ContactListCopy ;
public Splitadapter(Context context, ArrayList<COntactsModel> ContactList) {
super();
mContext = context;
this.inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.ContactList = ContactList;
this.ContactListCopy = this.ContactList;
mCheckedStates = new LongSparseArray<>(ContactList.size());
System.out.println("asdfghjk" + mCheckedStates);
getFilter();
}//End of CustomAdapter constructor
#Override
public int getCount() {
return ContactListCopy.size();
}
#Override
public Object getItem(int position) {
return ContactListCopy.get(position).getName();
}
#Override
public long getItemId(int position) {
return ContactListCopy.get(position).getId();
}
public class ViewHolder {
TextView textviewName;
TextView textviewNumber;
CheckBox checkbox;
Button b;
int id;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
final int pos = position;
//
if (convertView == null) {
holder = new ViewHolder();
convertView = LayoutInflater.from(mContext).inflate(R.layout.list, null);
holder.textviewName = (TextView) convertView.findViewById(R.id.name);
holder.textviewNumber = (TextView) convertView.findViewById(R.id.mobile);
holder.checkbox = (CheckBox) convertView.findViewById(R.id.check);
holder.b = convertView.findViewById(R.id.round_icon);
convertView.setTag(holder);
}//End of if condition
else {
holder = (ViewHolder) convertView.getTag();
}//End of else
COntactsModel c = ContactListCopy.get(position);
holder.textviewName.setText(c.getName());
holder.textviewNumber.setText(c.getPhonenum());
holder.checkbox.setTag(c.getId());
holder.checkbox.setChecked(mCheckedStates.get(c.getId(), false));
holder.checkbox.setOnCheckedChangeListener(this);
holder.b.setText(c.getName().substring(0,1));
//holder.id = position;
return convertView;
// }//End of getView method
}
boolean isChecked(long id) {// it returns the checked contacts
return mCheckedStates.get(id, false);
}
void setChecked(long id, boolean isChecked) { //set checkbox postions if it sis checked
mCheckedStates.put(id, isChecked);
System.out.println("hello...........");
notifyDataSetChanged();
}
void toggle(long id) {
setChecked(id, !isChecked(id));
}
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
mCheckedStates.put((Long) buttonView.getTag(), true);
} else {
mCheckedStates.delete((Long) buttonView.getTag());
}
}
#Override
public Filter getFilter() {
if (valueFilter == null) {
valueFilter = new ValueFilter();
}
return valueFilter;
}
private class ValueFilter extends Filter {
//Invoked in a worker thread to filter the data according to the constraint.
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if (constraint != null && constraint.length() > 0) {
ArrayList<COntactsModel> filterList = new ArrayList<COntactsModel>();
for (int i = 0; i < ContactList.size(); i++) {
COntactsModel ca = ContactList.get(i);
if ((ca.getName().toUpperCase())
.contains(constraint.toString().toUpperCase())) {
//COntactsModel contacts = new COntactsModel();
filterList.add(ca);
}
}
results.count = filterList.size();
results.values = filterList;
} else {
results.count = ContactList.size();
results.values = ContactList;
}
return results;
}
//Invoked in the UI thread to publish the filtering results in the user interface.
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
ContactListCopy = (ArrayList<COntactsModel>) results.values;
notifyDataSetChanged();
}
}
}
This my Main Activity :
public class MainActivity extends AppCompatActivity implements AdapterView.OnItemClickListener {
public static String TAG = "amount";
ListView mainListView;
ProgressDialog pd;
public static final int PERMISSIONS_REQUEST_READ_CONTACTS = 100;
final static List<String> name1 = new ArrayList<>();
List<String> phno1 = new ArrayList<>();
List<Long> bal = new ArrayList<>();
List<Bitmap> img = new ArrayList<>();
private Splitadapter mCustomAdapter;
private ArrayList<COntactsModel> _Contacts = new ArrayList<COntactsModel>();
HashSet<String> names = new HashSet<>();
Set<String>phonenumbers = new HashSet<>();
Button select;
int amount=100;
float result;
String ph;
String phoneNumber;
EditText search;
String contactID;
String name;
// private FirebaseAuth mAuth;
// FirebaseUser firebaseUser;
//
// FirebaseFirestore db = FirebaseFirestore.getInstance();
#SuppressLint("StaticFieldLeak")
#Override
protected void onCreate(Bundle savedInstanceState) {
setTitle("Split");
if (getSupportActionBar() != null) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
search = findViewById(R.id.search_bar);
final List<String> phonenumber = new ArrayList<>();
System.out.print(phonenumber);
mainListView = findViewById(R.id.listview);
showContacts();
select = findViewById(R.id.button1);
search.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
// When user chan ged the Text
mCustomAdapter.getFilter().filter(cs.toString());
//
}
#Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable arg0) {
// TODO Auto-generated method stub
//ma.filter(text);
}
});
select.setOnClickListener(new View.OnClickListener() {
#SuppressLint("NewApi")
#Override
public void onClick(View v) {
StringBuilder checkedcontacts = new StringBuilder();
ArrayList checkedcontacts1 = new ArrayList();
ArrayList names = new ArrayList();
System.out.println(".............." + (mCustomAdapter.mCheckedStates.size()));
System.out.println("name size is" + name1.size());
int a = mCustomAdapter.mCheckedStates.size();
result = ((float) amount / a);
System.out.println("final1 amount is " + result);
long result1 = (long) result;
System.out.println("final amount is " + result1);
for (int k = 0; k < a; k++) {
bal.add(result1);
}
System.out.println("balance" + bal);
System.out.println("selected contacts split amount" + result);
System.out.println("names" + name1.size());
// int as = name1.size();
// mCustomAdapter.mCheckedStates = new LongSparseArray<>(as);
System.out.println("cjgygytygh" + mCustomAdapter.mCheckedStates);
for (int i = 0; i < name1.size(); i++) // it displays selected contacts with amount
{
System.out.println("checked contcts" + mCustomAdapter.mCheckedStates.get(i));
if (mCustomAdapter.mCheckedStates.get(i)) {
checkedcontacts.append(phno1.get(i)).append("\t").append("\t").append("\t").append(result1);
checkedcontacts1.add((phno1.get(i)));
names.add((name1.get(i)));
checkedcontacts.append("\n");
System.out.println("checked contacts:" + "\t" + phno1.get(i) + "\t" + "amount" + "\t" + result1);
}
}
System.out.println("checked names" + names);
System.out.println(
"checkec contcts foggfgfgfgfgf" + checkedcontacts1
);
List<Object> list = new ArrayList<>();
for (Object i : checkedcontacts1) {
list.add(i);
}
System.out.println("checked contacts size is" + checkedcontacts1.size());
HashMap<String, HashMap<String, Object>> Invites = new HashMap<>();
for (int i = 0; i < checkedcontacts1.size(); i++) {
HashMap<String, Object> entry = new HashMap<>();
entry.put("PhoneNumber", list.get(i));
entry.put("Name", names.get(i));
System.out.println("entry is" + entry);
for (int j = i; j <= i; j++) {
System.out.println("phonenumber" + i + ":" + list.get(i));
System.out.println("amount" + j + ":" + bal.get(j));
//dataToSave.put("phonenumber" +i, list.get(i));
entry.put("Amount", bal.get(j));
}
Invites.put("Invite" + i, entry);
}
Intent intent = new Intent(MainActivity.this, Display.class);
intent.putExtra("selected", checkedcontacts1.toString().split(","));
startActivity(intent);
}
});
}
private void showContacts() // it is for to check the build versions of android . if build version is >23 or above it is set the permissions at the run time . if the build version is less than 23 the we give the permissions at manifest file .
{if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.READ_CONTACTS}, PERMISSIONS_REQUEST_READ_CONTACTS);
}
else {
mCustomAdapter = new Splitadapter(MainActivity.this,_Contacts);
//ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1,aa);
mainListView.setAdapter(mCustomAdapter);
mainListView.setOnItemClickListener(this);
mainListView.setItemsCanFocus(false);
mainListView.setTextFilterEnabled(true);
getAllContacts();
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, // it is display the request access permission dilogue box to access the contacts of user.
#NonNull int[] grantResults) {
if (requestCode == PERMISSIONS_REQUEST_READ_CONTACTS) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission is granted
showContacts();
} else {
Toast.makeText(this, "Until you grant the permission, we canot display the names", Toast.LENGTH_SHORT).show();
}
}
}
private void getAllContacts() {
// it displays the contact phonenumber and name rom the phone book. and add to the list.
ContentResolver cr = getContentResolver();
String[] PROJECTION = new String[] {
ContactsContract.RawContacts._ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.PHOTO_URI,
ContactsContract.CommonDataKinds.Phone.NUMBER,
ContactsContract.CommonDataKinds.Phone.NORMALIZED_NUMBER,
ContactsContract.CommonDataKinds.Photo.CONTACT_ID };
Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
String filter = ""+ ContactsContract.Contacts.HAS_PHONE_NUMBER + " > 0 and " + ContactsContract.CommonDataKinds.Phone.TYPE +"=" + ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE;
String order = ContactsContract.Contacts.DISPLAY_NAME + " ASC";
Cursor phones = cr.query(uri, PROJECTION, filter, null, order);
while (phones.moveToNext()) {
long id = phones.getLong(phones.getColumnIndex(ContactsContract.Data._ID));
name = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
_Contacts.add(new COntactsModel(id,name,phoneNumber));
name1.add(name);
phno1.add(phoneNumber);
}
phones.close();
}
public static Bitmap loadContactPhoto(ContentResolver cr, long id) {
Uri uri = ContentUris.withAppendedId(
ContactsContract.Contacts.CONTENT_URI, id);
InputStream input = ContactsContract.Contacts
.openContactPhotoInputStream(cr, uri);
if (input == null) {
return null;
}
return BitmapFactory.decodeStream(input);
}
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
mCustomAdapter.toggle(arg3);
}
This my Model Class :
public class COntactsModel
{
String phonenum;
long id;
String cname;
boolean selected = false;
public COntactsModel(long id, String name,String phonenumber) {
this.id = id;
this.cname = name;
this.phonenum = phonenumber;
}
public long getId() {
return this.id;
}
public String getName() {
return this.cname;
}
public String getPhonenum() {
return this.phonenum;
}
}
How to solve that error?
So I have this fun little list adapter I'm trying to figure out, in addition to Android/Java as a whole. It started with just compiling a simple list of RFID tags picked up by a scanner. The API that came with the scanner made that part pretty easy. It later evolved into fetching JSON objects associated with the tags the scanner would pick up via a URL that needed to be built using the tag ID itself.
Fast forward to today, I'm now trying to figure out a way to filter the finished list items, but I need it be done by the 'status' of the tag; not the actual 10-digit string, 'tagTitle'. Unfortunately, the working spinner filter I have set up now only does it by 'tagTitle' because I can't figure out how to access the other two TextViews to use them as a constraint instead. However, the array used by the spinner is populated with all the possible status we have in our system. So obviously any filter selection I pick, the list goes blank.
With that said, any help that'll get me to Point-B would be greatly appreciated. If there's any more information I should've included in this, please let me know. Thanks.
public class rfid_status extends UgiUiActivity implements
UgiInventoryDelegate,
UgiInventoryDelegate.InventoryDidStopListener,
UgiInventoryDelegate.InventoryTagFoundListener {
public UgiRfidConfiguration rfidConfig;
public EPCAdapter epcAdapter;
public List<UgiTag> tagArray = new ArrayList<>();
public RequestQueue rQ;
public Spinner tagSearch;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rfid_status);
ListView tagListView = (ListView) findViewById(R.id.tagList);
String[] statStrings = {
"",
"In",
"Filled",
"Out",
"Repair",
"Lost",
"QC",
"Missing",
"Sold",
"In Transfer"
};
ArrayAdapter<String> statusArray = new ArrayAdapter<>(this, android.R.layout.simple_spinner_dropdown_item, statStrings);
tagSearch = (Spinner) findViewById(R.id.tagSearch);
tagSearch.setAdapter(statusArray);
tagSearch.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String constraint = parent.getItemAtPosition(position).toString();
epcAdapter.getFilter().filter(constraint);
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
// Do Nothing
}
});
this.setDisplayDialogIfDisconnected(true);
UgiTitleView titleView = (UgiTitleView) findViewById(R.id.status_title);
titleView.setTheTitle(getResources().getString(R.string.status_title));
this.configureTitleViewNavigation(titleView);
titleView.setBatteryStatusIndicatorDisplayVersionInfoOnTouch(true);
titleView.setUseBackgroundBasedOnUiColor(true);
titleView.setThemeColor(ContextCompat.getColor(this, msq_black));
titleView.setTextColorOnThemeColor(ContextCompat.getColor(this, msq_red));
titleView.setDisplayWaveAnimationWhileScanning(true);
rQ = Volley.newRequestQueue(this);
rfidConfig = UgiRfidConfiguration.INVENTORY_SHORT_RANGE;
epcAdapter = new EPCAdapter(this);
tagListView.setAdapter(epcAdapter);
updateUI();
}
public class EPCAdapter extends BaseAdapter implements Filterable {
rfid_status rfidStatus;
List<UgiTag> origTags;
EPCAdapter(rfid_status rfidStatus) {
super();
this.rfidStatus = rfidStatus;
}
class TagHolder {
TextView tagNumber, tagDetails, tagStatus;
}
#Override
public boolean hasStableIds() {
return true;
}
#Override
public int getCount() {
return tagArray.size();
}
#Override
public Object getItem(int position) {
return position < tagArray.size() ? tagArray.get(position) : null;
}
#Override
public long getItemId(int position) {
return position < tagArray.size() ? tagArray.get(position).getEpc().hashCode() : 0;
}
#SuppressLint("InflateParams")
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final TagHolder tagHolder;
final UgiTag ugiTag = tagArray.get(position);
final String tagTitle = ugiTag.toString().substring(14);
Uri.Builder jsonBuild = new Uri.Builder();
jsonBuild.scheme("http").authority("thirdstreamv2").appendPath("utilities").appendPath("HandheldGreenScreen").appendQueryParameter("assetid", tagTitle);
String jsonURL = jsonBuild.build().toString();
if (convertView == null) {
convertView = LayoutInflater.from(rfid_status.this).inflate(R.layout.tag_row, null);
tagHolder = new TagHolder();
tagHolder.tagNumber = (TextView) convertView.findViewById(R.id.tagHere);
tagHolder.tagStatus = (TextView) convertView.findViewById(R.id.statHere);
tagHolder.tagDetails = (TextView) convertView.findViewById(R.id.descHere);
convertView.setTag(tagHolder);
} else {
tagHolder = (TagHolder) convertView.getTag();
}
JsonObjectRequest jObj = new JsonObjectRequest(Request.Method.GET, jsonURL, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
String displayIf = response.getString("display");
if (!displayIf.equals("true")) {
tagArray.remove(ugiTag);
notifyDataSetChanged();
} else {
tagHolder.tagNumber.setText(tagTitle);
tagHolder.tagStatus.setText(response.getString("status"));
// I need to filter by the above somehow...
tagHolder.tagDetails.setText(response.getString("description"));
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
});
rQ.add(jObj);
return convertView;
}
#Override
public Filter getFilter() {
return new Filter() {
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
tagArray = (List<UgiTag>) results.values;
notifyDataSetChanged();
}
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
List<UgiTag> filteredTags = new ArrayList<>();
constraint = constraint.toString();
if (origTags == null) {
origTags = new ArrayList<>(tagArray);
}
if (constraint.length() == 0) {
results.count = origTags.size();
results.values = origTags;
} else {
for (int position = 0; position < origTags.size(); position++) {
UgiTag ugiTag = origTags.get(position);
String tagString = ugiTag.toString().substring(14);
if (tagString.contains(constraint)) {
filteredTags.add(ugiTag);
}
}
results.count = filteredTags.size();
results.values = filteredTags;
}
return results;
}
};
}
}
Never mind, answered it myself. I trashed my old array and created a new one using a custom object I put together to store the JSON responses instead of listing only the RFID tags (UgiTag). With the values being in the object, I can now access them within the filter and use it as a constraint.
public class EPCAdapter extends BaseAdapter implements Filterable {
rfid_status rfidStatus;
List<TagInfo> origTags = null;
EPCAdapter(rfid_status rfidStatus) {
super();
this.rfidStatus = rfidStatus;
}
class TagHolder {
TextView tagNumber, tagDetails, tagStatus;
}
#Override
public boolean hasStableIds() {
return true;
}
#Override
public int getCount() {
return tagList.size();
}
#Override
public Object getItem(int position) {
return position < tagList.size() ? tagList.get(position) : null;
}
#Override
public long getItemId(int position) {
return position < tagList.size() ? tagList.get(position).hashCode() : 0;
}
#SuppressLint("InflateParams")
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final TagInfo tagItem = tagList.get(position);
final String tagTitle = tagItem.getUgiTag().toString().substring(14);
final TagHolder tagHolder;
Uri.Builder jsonBuild = new Uri.Builder();
jsonBuild.scheme("http").authority("thirdstreamv2").appendPath("utilities").appendPath("HandheldGreenScreen").appendQueryParameter("assetid", tagTitle);
String jsonURL = jsonBuild.build().toString();
if (convertView == null) {
convertView = LayoutInflater.from(rfid_status.this).inflate(R.layout.tag_row, null);
tagHolder = new TagHolder();
tagHolder.tagNumber = (TextView) convertView.findViewById(R.id.tagHere);
tagHolder.tagStatus = (TextView) convertView.findViewById(R.id.statHere);
tagHolder.tagDetails = (TextView) convertView.findViewById(R.id.descHere);
convertView.setTag(tagHolder);
} else {
tagHolder = (TagHolder) convertView.getTag();
}
JsonObjectRequest jObj = new JsonObjectRequest(Request.Method.GET, jsonURL, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
tagItem.setTagStatus(response.getString("status"));
tagItem.setTagDescription(response.getString("description"));
tagItem.setTagDisplay(response.getString("display"));
tagHolder.tagNumber.setText(tagTitle);
tagHolder.tagStatus.setText(tagItem.getTagStatus());
tagHolder.tagDetails.setText(tagItem.getTagDescription());
if (!tagItem.getTagDisplay().equals("true")) {
tagList.remove(tagItem);
notifyDataSetChanged();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
});
rQ.add(jObj);
return convertView;
}
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
List<TagInfo> filteredTags = new ArrayList<>();
constraint = constraint.toString();
if (origTags == null) {
origTags = new ArrayList<>(tagList);
}
if (constraint.length() == 0) {
results.count = origTags.size();
results.values = origTags;
} else {
for (int position = 0; position < origTags.size(); position++) {
TagInfo origPos = origTags.get(position);
String tagString = origPos.getTagStatus();
if (tagString.contains(constraint)) {
filteredTags.add(origPos);
}
}
results.count = filteredTags.size();
results.values = filteredTags;
}
return results;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
tagList = (List<TagInfo>) results.values;
notifyDataSetChanged();
}
};
}
}
Currently i can search only one string word. example, I need to search for multiple words i type "nougat,donut" and they show me these two? What i need to put in code for this to work?
DataAdapter.java
public class DataAdapter extends RecyclerView.Adapter<DataAdapter.ViewHolder> implements Filterable {
private ArrayList<AndroidVersion> mArrayList;
private ArrayList<AndroidVersion> mFilteredList;
public DataAdapter(ArrayList<AndroidVersion> arrayList) {
mArrayList = arrayList;
mFilteredList = arrayList;
}
#Override
public DataAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.card_row, viewGroup, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(DataAdapter.ViewHolder viewHolder, int i) {
viewHolder.tv_name.setText(mFilteredList.get(i).getName());
viewHolder.tv_version.setText(mFilteredList.get(i).getVer());
viewHolder.tv_api_level.setText(mFilteredList.get(i).getApi());
}
#Override
public int getItemCount() {
return mFilteredList.size();
}
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence charSequence) {
String charString = charSequence.toString();
if (charString.isEmpty()) {
mFilteredList = mArrayList;
} else {
ArrayList<AndroidVersion> filteredList = new ArrayList<>();
for (AndroidVersion androidVersion : mArrayList) {
if (androidVersion.getApi().toLowerCase().contains(charString) || androidVersion.getName().toLowerCase().contains(charString) || androidVersion.getVer().toLowerCase().contains(charString)) {
filteredList.add(androidVersion);
}
}
mFilteredList = filteredList;
}
FilterResults filterResults = new FilterResults();
filterResults.values = mFilteredList;
return filterResults;
}
#Override
protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
mFilteredList = (ArrayList<AndroidVersion>) filterResults.values;
notifyDataSetChanged();
}
};
}
public class ViewHolder extends RecyclerView.ViewHolder{
private TextView tv_name,tv_version,tv_api_level;
public ViewHolder(View view) {
super(view);
tv_name = (TextView)view.findViewById(R.id.tv_name);
tv_version = (TextView)view.findViewById(R.id.tv_version);
tv_api_level = (TextView)view.findViewById(R.id.tv_api_level);
}
}
json recycler view
this is search but only for one word
you can try this
if (charString.contains(",")) {
String searchChar[] = charString.split(",");
for (int i = 0; i < searchChar.length; i++) {
if (androidVersion.getApi().toLowerCase().contains(searchChar[i]) || androidVersion
.getName()
.toLowerCase().contains(searchChar[i]) || androidVersion.getVer().toLowerCase()
.contains(searchChar[i])) {
filteredList.add(androidVersion);
}
}
} else {
if (androidVersion.getApi().toLowerCase().contains(charString) || androidVersion.getName()
.toLowerCase().contains(charString) || androidVersion.getVer().toLowerCase()
.contains(charString)) {
filteredList.add(androidVersion);
}
}
replace the code :
if (androidVersion.getApi().toLowerCase().contains(charString) ||
androidVersion.getName().toLowerCase().contains(charString) ||
androidVersion.getVer().toLowerCase().contains(charString)) {
filteredList.add(androidVersion);
}
You need to add some pre-processing to determine if there are multiple values
#Override
protected FilterResults performFiltering(CharSequence charSequence) {
String splitter = ",";
final String[] multipleValues = charSequence.toString().split(splitter);
//your null check
List<AndroidVersions> filteredList = new ArrayList()
for (String value : multipleValues) {
filteredList.addAll(internalFilter(mArrayList, value));
}
//the rest of your code
}
private List<AndroidVersions> internalFilter(ArrayList<AndroidVersions> listToFilter, String value) {
List<AndroidVersions> filteredList = new ArrayList()
for (AndroidVersion androidVersion : listToFilter) {
if (androidVersion.getApi().toLowerCase().contains(value)
|| androidVersion.getName().toLowerCase().contains(value)
|| androidVersion.getVer().toLowerCase().contains(value)) {
filteredList.add(androidVersion);
}
}
return filteredList;
}
This code will also work perfectly fine with only 1 value
I have a problem with my filter method it didnt display the filter result in my listview
here is my code:
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
//
final FilterResults searchResults = new FilterResults();
final ArrayList<music> resulta = new ArrayList<music>();
//
if (_musicList == null)
_musicList = musicList;
//
if (constraint != null) {
if (_musicList != null && _musicList.size() > 0) {
for (final music _music : _musicList) {
//
Log.d("constraint", constraint.toString() + " " + _music.getTitle().toString());
if (_music.getTitle().toLowerCase().startsWith(constraint.toString())){
Log.d("add items", _music.getTitle());
resulta.add(_music);
}
}
//
for (music music : resulta) {
Log.d("result item", music.getTitle());
}
searchResults.values = resulta;
}
}
else{
searchResults.values = musicList;
}
return searchResults;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
//
Log.d("final result", results.values.toString());
//
if (results.count == 0)
notifyDataSetInvalidated();
//
musicList = (ArrayList<music>) results.values;
//
notifyDataSetChanged();
}
};
}
I check the items being filter and its correct but
It display the wrong items it just display the last two items in the listview instead of the filter items
here is the code in my textview:
#Override
public void onTextChanged(CharSequence s, int start,
int before, int count) {
musicListAdapter.getFilter().filter(s.toString());
}
what am i doing wrong? I really need some help please...
The above code is right, the problem is my getView method i just modify it now and it works perfectly fine now.... here is my entire code
public static final int SEARCH_TITLE = 12;
public static final int SEARCH_ARTIST = 23;
public static final int SEARCH_KARAOKENUMBER = 34;
#Override
public View getView(int position, View convertView, ViewGroup parent) {
songListWidgetHolder viewHolder = null;
String title;
String artist;
if (convertView == null) {
//
if (musicList != null && musicList.size() > 0) {
// Log.d("size", String.valueOf(musicList.size()));
LayoutInflater mInflater = (LayoutInflater) Act
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
//
convertView = mInflater.inflate(R.layout.list_row, null);
final String _title = musicList.get(position).getTitle();
title = AppUtils.ShortText(_title, 7);
final String _artist = musicList.get(position).getArtist();
artist = AppUtils.ShortText(_artist, 5);
switch (sortkey) {
case SORT_ARTIST_DESC:
case SORT_ARTIST_ASC:
viewHolder = new songListWidgetHolder();
//
viewHolder.ArtistTV = (TextView) convertView
.findViewById(R.id.artisttx);
viewHolder.ArtistTV = (TextView) convertView
.findViewById(R.id.artisttv);
viewHolder.TitleTV = (TextView) convertView
.findViewById(R.id.titletv);
viewHolder.MusicIcon = (ImageView) convertView
.findViewById(R.id.musicImage);
//
viewHolder.TitleTV.setText(artist);
viewHolder.ArtistTV.setText(title);
viewHolder.MusicIcon.setImageResource(R.drawable.music);
//
convertView.setTag(viewHolder);
return convertView;
default:
break;
}
viewHolder = new songListWidgetHolder();
viewHolder.ArtistTV = (TextView) convertView
.findViewById(R.id.artisttv);
viewHolder.TitleTV = (TextView) convertView.findViewById(R.id.titletv);
viewHolder.MusicIcon = (ImageView) convertView
.findViewById(R.id.musicImage);
viewHolder.NewMusicTV = (TextView) convertView
.findViewById(R.id.newmusicTV);
convertView.setTag(viewHolder);
}
} else {
viewHolder = (songListWidgetHolder) convertView.getTag();
}
if (musicList.size() > 0 && musicList != null){
final String _title = musicList.get(position).getTitle();
title = AppUtils.ShortText(_title, 7);
final String _artist = musicList.get(position).getArtist();
artist = AppUtils.ShortText(_artist, 5);
viewHolder.TitleTV.setText(title);
viewHolder.ArtistTV.setText(artist);
viewHolder.MusicIcon.setImageResource(R.drawable.music);
Date musicModifiedDate = musicList.get(position)
.getDatemodified();
Date systemDate = new Date(System.currentTimeMillis());
if (musicModifiedDate != null)
if (AppUtils.GetDateDifference(systemDate, musicModifiedDate)) {
viewHolder.NewMusicTV.setText("New");
}
AnimationManager.StartAnimation(Act, AnimationManager.PUSH_UP_IN_ANIMATION, convertView,1000);
}
return convertView;
}
// --------------------------------------------------------------------------------
// We used it to Search songs in our musicList arraylist
public Filter getFilter(final int keySearch) {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
final FilterResults oReturn = new FilterResults();
// final CarouselDataItem[] musicList;
final ArrayList<music> results = new ArrayList<music>();
//
if (_musicList == null)
_musicList = musicList;
// check if constraint is not null
if (constraint != null) {
// check if the music List have data
if (_musicList != null && _musicList.size() > 0) {
// loop to the arraylist of music list
for (final music _music : _musicList) {
// check if the music object is equals to the
// constraint character
switch (keySearch) {
case SEARCH_TITLE:
if (searchTitle(_music, constraint.toString()))
results.add(_music);
break;
case SEARCH_ARTIST:
if (searchArtist(_music, constraint.toString()))
results.add(_music);
break;
case SEARCH_KARAOKENUMBER:
if (searchKaraokeNumber(_music,
constraint.toString()))
results.add(_music);
break;
default:
break;
}
//
}
}
// set results of the filter search in oReturn
oReturn.values = results;
}
// return the results
return oReturn;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
musicList = (ArrayList<music>) results.values;
notifyDataSetChanged();
}
};
}
private boolean searchTitle(music song, String title) {
String _title = song.getTitle().toLowerCase();
return _title.startsWith(title.toLowerCase());
}
private boolean searchArtist(music song, String artist) {
String _artist = song.getArtist().toLowerCase();
return _artist.startsWith(artist.toLowerCase());
}
private boolean searchKaraokeNumber(music song, String karaokenum) {
String _karaokenum = song.getMusicrefID();
return _karaokenum.contains(karaokenum);
}