I am facing problem while filtration of list .I am using onTextChange() method for it .It is working properly but problem is that as i type single character in edit Text the soft keyboard gets disappear and I have to tap edit text again to type complete string .I have also done code so that soft keyboard does not disappear after text change but to type still I have to tap on edit text.Here is my code :
search.addTextChangedListener(new TextWatcher() {
# Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// TODO Auto-generated method stub
String startwith = s.toString();
ArrayList < Myshares > filterList = new ArrayList < Myshares > ();
for (int i = 0; i < fileList.size(); i++) {
if (fileList.get(i).getName().toLowerCase().startsWith(startwith) || fileList.get(i).getName().toUpperCase().startsWith(startwith)) {
filterList.add(fileList.get(i));
}
}
adapter = new MListAdapter(PlayListActivity.this, filterList);
playListView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
#
Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
#
Override
public void afterTextChanged(Editable s) {
search.setSelection(search.getText().length());
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(search, InputMethodManager.SHOW_IMPLICIT);
}
});
here is my xml code for edit text:
<EditText
android:ems="10"
android:id="#+id/search_bar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="5dp"
android:layout_weight="2"
android:background="#drawable/searchbox"
android:editable="true"
android:focusable="true"
android:inputType="textFilter"
android:hint="Search"
android:keepScreenOn="true"
android:paddingLeft="10dp"
android:textSize="15dp" />
i have also set android:focusable="false " property on list view so that it doesn't overlap soft keyboard. But the problem with edit text is still same .Here are screenshots
As I insert A Single character list gets filter and cursor is gone from edit text box.
//ArrayAdapter Definition. Make it activity class field.
ArrayAdapter<String> adapter;
//initialize the adapter by loading complete data and set Adapter to ListView.
//**Note: I have used ArrayList<String> below.**
ArrayList <String> filterList = new ArrayList <Myshares> ();
for (int i = 0; i < fileList.size(); i++) {
if (fileList.get(i).getName().toLowerCase() || fileList.get(i).getName().toUpperCase()) {
filterList.add(fileList.get(i));
}
}
adapter = new ArrayAdapter<String>(this, R.layout.searchresult_item, R.id.search_item_name,filterList);
//Here, searchresult_item is the layout file name. and search_item_name is the Textview inside it.
search.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence cs, int start, int before, int count) {
YourActivity.this.Youradapter.getFilter().filter(cs);
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,int after) {
}
#Override
public void afterTextChanged(Editable s) {
}
});
I guess you have added the edit text in list view by addView() Method. It is indeed happening because all the views are redrawn, so the edit text representing whatever row used to be focused is now a completely different object. Set a variable in your adapter: int currentlyFocusedRow;
in getView for your adapter:
Add an onFocusChanged listener to edit text
and when that edit text gains focus, set
currentlyFocusedRow (int variable) = row that focused(contained) edit text happens to be in. Also set any edited text that is in the currentlyFocusedRow to be focused.
Reply me if you see some problems in this.
Related
I have implemented a search bar which fills a list of search results every time a search token is inserted. My XML goes like this:
<android.widget.SearchView
android:id="#+id/my_searchView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:queryHint="Search Here" />
<ListView
android:id="#+id/my_listView"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
Once the token is inserted, an api is invoked and the results are stored in a list called resultUsers. I am populating the ListView like this:
runOnUiThread(new Runnable() {
#Override
public void run() {
ListView list = findViewById(R.id.my_listView);
adapter = new ArrayAdapter<>(MyActivity.this, android.R.layout.simple_list_item_1, userNames);
list.setAdapter(adapter);
getSelectedUserDetails(list);
}
});
getSelectedUserDetails() function is called to prepare the listener for the item click:
public void getSelectedUserDetails(ListView list){
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
String selection = (String) list.getItemAtPosition(i);
User selectedUser = new User();
for(int j = 0; j < resultUsers.size(); j++) {
if(selection.equals(resultUsers.get(j).getName())){
selectedUser = resultUsers.get(j);
System.out.print(selectedUser.getId());
Toast.makeText(getBaseContext(), selectedUser.getId().toString(), Toast.LENGTH_SHORT).show();
}
}
}
});
}
2 unexpected results occur:
The system output appears not when i click the item on the list but after clicking the item and reinserting a search token
The Toast does not appear at all
Is this a bug or have i got it wrong all together and there's a different approach for search results lists?
there is a drop-down menu with a custom listView in my app. The data in this listView comes from an arraylist (one image and 2 strings for each entry). When the user selects an option from this list, it shows the image and the first string value in an imageview and a textview - see picture below.
Listview
After selection
Now I want the selection by the user to be saved and automatically loaded and displayed upon the next app start.
Here is my code for opening the list and selecting an option:
fromDropDown.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
fromDialog = new Dialog(ActivityMain.this);
fromDialog.setContentView(R.layout.from_spinner);
fromDialog.getWindow().setLayout(MATCH_PARENT,1200);
fromDialog.show();
EditText editText = fromDialog.findViewById(R.id.edit_text);
ListView listView = fromDialog.findViewById(R.id.list_view);
JavaAdapter javaAdapter = new JavaAdapter(ActivityMain.this,R.layout.list_row,arrayList);
listView.setAdapter(javaAdapter);
editText.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence cs, int start, int before, int count) {
javaAdapter.getFilter().filter(cs);
}
#Override
public void afterTextChanged(Editable s) {
}
});
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
fromDropDown.setText(javaAdapter.getItem(position).getExample());
picLeft.setImageResource(javaAdapter.getItem(position).getImage());
fromDialog.dismiss();
}
});
}
});
Right now I set the "default" value for the first start by doing this:
fromDropDown.setText(javaAdapter.getItem(0).getExample());
picLeft.setImageResource(javaAdapter.getItem(0).getImage());
But after the user selects an option, I want the app to save that selection and display this new selection on the next app start instead of my "default" value.
This presumably works with sharedpreferences, but I can't figure it out... Maybe someone can give me a hint in the right direction how this could be implemented.
you can save in shared preferences the position of selected item, and instead to set by default 0 you to this one:
save position
val sharedPref = context.getSharedPreferences("APP_SHARED", Context.MODE_PRIVATE)
with(sharedPref.edit()) {
putInt("position", selectedPosition).apply()
}
///after application loaded
val sharedPref = context.getSharedPreferences("APP_SHARED",Context.MODE_PRIVATE)
val position = sharedPref.getInt("position", 0) //0 default value in case when nothing was setted
fromDropDown.setText(javaAdapter.getItem(position).getExample());
picLeft.setImageResource(javaAdapter.getItem(position).getImage());
Problem: MyAutoCompleteTextView.**showDropDown()** will work when called by the onFocusChange but won't work when called by the onTextChanged. During my debug, the onTextChanged method gets called correctly when I want it to execute the showDropDown() according to the logging message I created, just nothing happens. I noticed there is a SpannableStringBuilder error that occurs prior, but as I recall (could be wrong) when I checked on this error in the past, this is a common error with an open ticket. I wasn't really sure it is the cause.
What I'm trying to do: ... is what everyone that asks this type of question wants to do, get the AutoCompleteTextView to show the full list anytime the AutoCompleteTextView is focused and empty (my first item is: "")
What I have tried: I've tried many "green checked" solutions on this forum, but none of them have worked at present EXCEPT when first focused. They will cause the full items list to present, but it is on the backspacing back to zero that it will not. I'm using a combination of change listeners as most suggestions have. I just really thought this would work based on the logging values and it being called at the proper time?
My logging statement: which writes when I want it to showing the method gets called when I like.
E/SpannableStringBuilder: SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length
SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length
E/OnTextChanged: showDropDown()
start: 0
before: 1
count: 0
length: 0
My current version and effort:
ArrayAdapter<String> topicsAdapter = DBQueryTools.captureDBTopics(this);
topic.setAdapter(topicsAdapter);
topic.setOnItemClickListener((parent, view, position, id) -> {
if(!topic.getText().toString().equals("")) {
question.setText("");
rListNotes.setAdapter(null);
customSearch.setText(null);
loadNotes(captureNotes(researchDatabase.getNotesDao().getNotesOnTopic(topic.getText().toString())));
}
});
topic.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if(before == 1 && count == 0 && s.length()==0) {
topic.showDropDown();
Log.e("OnTextChanged", "showDropDown() " + s + "\n" + "start: " + start + "\nbefore: " + before + "\ncount: " + count + "\nlength: " + s.length());
}
}
#Override
public void afterTextChanged(Editable s) {
}
});
topic.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
topic.showDropDown();
Log.e("HasFocus", "showDropDown");
}
}
});
I was able to get a modified version of the InstantAutoComplete view working (combining from here and here)
public class InstantAutoComplete extends AppCompatAutoCompleteTextView {
public InstantAutoComplete(Context context) {
super(context);
}
public InstantAutoComplete(Context arg0, AttributeSet arg1) {
super(arg0, arg1);
}
public InstantAutoComplete(Context arg0, AttributeSet arg1, int arg2) {
super(arg0, arg1, arg2);
}
#Override
public boolean enoughToFilter() {
return true;
}
#Override
protected void onFocusChanged(boolean focused, int direction,
Rect previouslyFocusedRect) {
super.onFocusChanged(focused, direction, previouslyFocusedRect);
if (focused && getAdapter() != null) {
// This part was necessary to get it working when not
// inside a TextInputLayout and multiple per activity
if( !maybeShowSuggestions() ) {
post(this::maybeShowSuggestions);
}
}
}
private boolean maybeShowSuggestions() {
if( getWindowVisibility() == View.VISIBLE ) {
performFiltering(getText(), 0);
showDropDown();
return true;
}
else {
return false;
}
}
}
The XML for inserting it looks like (also worked without the TextInputLayout)
<com.google.android.material.textfield.TextInputLayout
android:id="#+id/text_layout"
style="#style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Type words here"
android:layout_margin="16dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#id/focus_stealer" >
<com.example.autocompletetextviewdemo.InstantAutoComplete
android:id="#+id/autocomplete_text_view"
android:layout_width="match_parent"
android:completionThreshold="0"
android:layout_height="wrap_content"/>
</com.google.android.material.textfield.TextInputLayout>
and for setting it up with an adapter
private static final String[] WORDS = new String[] {
"Aardvark", "Apple", "Baby", "Boron", "Carbon"
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_dropdown_item_1line, WORDS);
AutoCompleteTextView textView = findViewById(R.id.autocomplete_text_view);
textView.setAdapter(adapter);
}
This works with multiple InstantAutoComplete dropdowns per activity, and after navigating back and forth between activities. Without the extra changes to the custom class it didn't work with multiple instances in an activity that weren't in a TextInputLayout.
Hey guys what is the best way to search through my list of objects, they return a few strings, last name and first name for example.
Here how i'm currently searching but my search needs to match the entire string which I don't want. The search needs it to match part of the string like our contacts list on our phone and ignore the case.
if (searchQ.equalsIgnoreCase(child.first_name)) {
addChildToList(child);
}
Ive tried contains and starts with for example, they did not work. Whats going on?
Thanks! Cheers!
You can use a TextWatcher to search in a list, as an example you define a TextWatcher for an EditText(search box) in this way :
TextWatcher filterTextWatcher = new TextWatcher() { //TextWatcher to Filter RealTime Input Data
public void beforeTextChanged(CharSequence s, int start, int count,int after)
{
}
public void onTextChanged(CharSequence s,int start, int before,int count) //Filter Data When Entering Data On ItemType Dialog TextView
{
}
#Override
public void afterTextChanged(Editable arg0)
{
}
};
EditText filterText = (EditText)dialog.findViewById(R.id.edtItemFilter);
filterText.addTextChangedListener(filterTextWatcher);
then in onTextChange() callback function you can send inserted characters as parameter s to your adapter to filter your List with getFilter or setup your list with filtered Cursor :
public void onTextChanged(CharSequence s,int start, int before,int count)
{
ListView lv = getListView();
ListAdapter adapter = (ListAdapter) lv.getAdapter();
lv.setTextFilterEnabled(true);
adapter.getFilter().filter(s.toString());
}
In my activity there is an error in this line (Home.this,android.R.layout.activity_home, searchResults)); which says "activity_home cannot be resolved" but if i give as single_list_item_1 as mentioned in one of the tutorial, error disappears, for this error i had checked in res for capital letters, then cleaned the project but still not able to get rid of this.
searchBox.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence s, int start, int before, int count) {
//get the text in the EditText
String searchString=searchBox.getText().toString();
int textLength=searchString.length();
//clear the initial data set
searchResults.clear();
for(int i=0;i<songsList.size();i++)
{
String playerName=songsList.get(i).get("title").toString();
if(textLength<=playerName.length()){
//compare the String in EditText with Names in the ArrayList
if(searchString.equalsIgnoreCase(playerName.substring(0,textLength)))
Toast.makeText(getApplicationContext(),playerName,1).show();
searchResults.add(songsList.get(i));
}
list.setAdapter(new ArrayAdapter<HashMap<String, String>>
(Home.this,android.R.layout.single_list_item, searchResults));
}
adapter.notifyDataSetChanged();
}
public void beforeTextChanged(CharSequence s, int start, int count,int after) {
}
public void afterTextChanged(Editable s) {
}
});
android.R.layout.activity_home
Something which starts with android is a predfined android resource.
if you want to use your own layout like activity_home.xml
you must use it this way
R.layout.activity_home
which means your application resource.
you have to learn the difference between android.R.layout.activity_home and R.layout.activity_home. the first one will try to load layout from android's predefined layout collection, while the other one is located in your projects layout folder