This feels strange as normally the widgets work as they are supposed to. I have an AutoCompleteTextView that I want to populate with a list of city names. It seems simple but doesn't work as I intend to. Here is the resulting output:
Here is the layout in picture:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity1">
<AutoCompleteTextView
android:id="#+id/autocomptv_city_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="12dp"
android:layout_marginEnd="20dp"
android:layout_marginRight="20dp"
android:background="#drawable/bg_edittext_rect_opd"
android:hint="Select City"
android:text=""
android:inputType="text"
android:maxLines="1"
android:completionThreshold="0"
android:padding="10dp"
android:singleLine="true"
android:textColor="#000000"
android:textSize="15sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
And below is the java code for the same:
public class MainActivity1 extends AppCompatActivity {
AutoCompleteTextView mAutCompleteTextViewSelfCity;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main1);
mAutCompleteTextViewSelfCity = ((AutoCompleteTextView) findViewById(R.id.autocomptv_city_list));
setupCityDropdownwidget();
}
private void setupCityDropdownwidget() {
Type listType = new TypeToken<List<CityName>>() {}.getType();
List<CityName> citiesList = Singletons.getGsonInstance().fromJson(TestData.cityDataJson, listType);
CityArrayAdapter adapter = new CityArrayAdapter(this, R.layout.item_spinner_city, citiesList);
mAutCompleteTextViewSelfCity.setAdapter(adapter);
adapter.notifyDataSetChanged();
mAutCompleteTextViewSelfCity.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
CityName selectedCitySelf = ((CityName) parent.getItemAtPosition(position));
mAutCompleteTextViewSelfCity.setText(selectedCitySelf.getCityName());
}
});
}
}
Problem:
Well, I want the view to be such that as soon as the user taps on it, it shows a dropdown of cities and when the user starts typing their city for filtering, the view keeps showing narrowed down suggestions for the same.
Currently, the only time it is able to suggest is when I type in something and empty out the text view. If I change the completion threshold to 1, no suggestions are shown ever.
What's wrong with my code?
Here is the complete source for reference: https://wetransfer.com/downloads/ce4017f5f2488288ef7494dc029e033420191019092536/7afa9a3e64afb257293533bd634d6c3220191019092536/dc2341
So ultimately, it turned out to be about the basics - The data item that ArrayAdapter works with, should provide a meaningful toString() override. That is what had been missing from my implementation.
From the docs:
By default, the array adapter creates a view by calling
Object#toString() on each data object in the collection you provide,
and places the result in a TextView.
I did end up wasting up some time but the experience and knowledge would surely come in handy some day.
YOu don't need to set adapter.notifyDataSetChanged();, just set your adapter and everything goes fine.
Related
I am working with a Fragment that handles a RecyclerView with different adapters, but when I try to show my emptyView TextView in the RecyclerView it simply stops the RecyclerView from working properly.
I created the following filter in my adapter:
/**
* Method that filters the data using the onQueryTextSubmit and onQueryTextChange.
*
* #return a Filter class that calls the method performFiltering of the FilterResults class
* and this method applies the filter and returns a list with the resulting data filtered.
*/
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence querySample) {
if (emptyView.getVisibility() == View.VISIBLE) {
emptyView.setVisibility(View.GONE);
}
/*
* Verifies the value of the sampleNameSearched and compares the data.
*/
if (querySample == null) {
// Updates the recyclerView with the sampleList.
sampleListFiltered.submitList(sampleList);
// holder.sampleView.setTextColor(ContextCompat.getColor(inflater.getContext(), R.color.BaseColor_1));
} else {
// Cleans the accentuation, letter case and other symbols of the querySample.
sampleNameSearched = Normalizer.normalize(querySample.toString(), Normalizer.Form.NFD)
.replaceAll("[^\\p{ASCII}]", "").toLowerCase();
// Creates the list that will save the filtered samples.
List<Sample> filteredSampleList = new LinkedList<>();
// Gets the data filtered in the for loop.
for (Sample sample : sampleList) {
// Cleans the accentuation, letter case and other symbols.
String sampleName = Normalizer.normalize(sample.getName(), Normalizer.Form.NFD)
.replaceAll("[^\\p{ASCII}]", "").toLowerCase();
// Adds the sample that matches the filter in the filteredSampleList.
if (sampleName.contains(sampleNameSearched)) {
filteredSampleList.add(sample);
}
}
// Updates the RecyclerView.
sampleListFiltered.submitList(filteredSampleList);
// TODO: Find a solution for not showing the emptyView instantly (not entering the onBindViewHolder).
/*
* if filteredSampleList is empty, shows the emptyView with the proper message.
*/
if (filteredSampleList.isEmpty()) {
// Updates the RecyclerView.
emptyView.setVisibility(View.VISIBLE);
} else {
if (emptyView.getVisibility() == View.VISIBLE) {
emptyView.setVisibility(View.GONE);
}
}
}
// Returns the filterResults.
FilterResults filterResults = new FilterResults();
filterResults.values = sampleListFiltered;
return filterResults;
}
// Publish the results on the RecyclerView.
#Override
protected void publishResults(CharSequence constraint, FilterResults filterResults) {
notifyDataSetChanged();
}
};
}
I cannot find out why my emptyView.setVisibility() sometimes works and others simply doesn't.
My layout is the following:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="#id/search_sample_field"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="25dp"
android:layout_marginTop="25dp"
android:layout_marginEnd="25dp"
app:layout_constraintTop_toBottomOf="#+id/sample_folder_selector">
<SearchView
android:id="#+id/sample_search_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:background="#drawable/search_box_border"
android:clickable="true"
android:iconifiedByDefault="false"
android:layoutDirection="rtl"
android:queryHint="#string/sample_search" />
</RelativeLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/ListNavigatorRecyclerview"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginStart="25dp"
android:layout_marginTop="25dp"
android:layout_marginEnd="25dp"
app:layout_constraintBottom_toTopOf="#+id/ButtonPanel"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/search_sample_field"
app:layout_constraintVertical_bias="1.0" />
<TextView
android:id="#+id/emptyListNavigatorView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginStart="25dp"
android:layout_marginEnd="25dp"
android:layout_marginBottom="100dp"
android:gravity="center"
android:text=""
android:visibility="gone"
app:layout_constraintBottom_toTopOf="#+id/ButtonPanel"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/search_sample_field"
app:layout_constraintVertical_bias="1.0" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/ButtonPanel"
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="#color/BaseColor_4"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent">
<ImageButton
android:id="#+id/remove_sample_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="25dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:src="#drawable/btn_delete"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
style="#style/IconButton" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Just to make sure that you understand the problem you can see some prints of the problem below:
What was supposed to happen:
Step 1 - Filter:
Filtering
Step 2 - Writing a sample that doesn't exist:
Sample that doesn't exist
Step 3 - Removing the wrong character:
The wrong character removed
What is happening right now (not supposed to happen):
Step 1 - Filter (working):
Filtering
Step 2 - Writing a sample that doesn't exist (not showing the emptyView):
Not showing the emptyView
Step 3 - Removing the wrong character (not showing the sample nor the bold character):
Not showing the sample
If I press the search button on the keyboard it works, but it was intended to work without pressing the search button...
Can someone help me with this problem?
I used a toast, and the toast works, but when it comes to using any kind of set method in the performFiltering or layout that requires a set method it seems that Android somehow losses its working flow.
I tried the following implementations:
How to show an empty view with a RecyclerView?
https://alexzh.com/how-to-setemptyview-to-recyclerview/
https://www.reddit.com/r/androiddev/comments/3bjnxi/best_way_to_handle_recyclerview_empty_state/
How to solve this problem?
I created an EmptyRecyclerView that extends the RecyclerView behaviours and added an updateEmptyView() method that verifies how many items I have in my RecyclerView and updates the view accordingly. My solution was based on this answer by maff91. And another source that helped me solve the problem is this Google Application that creates an EmptyView message like the one I needed.
My thanks to maff91 and the Google Application that has the same behaviour.
I want to get the text of a TextView that is in a ListView's item.
See the code and you will find what's my question.
Activity.java:
SimpleAdapter adapter = new SimpleAdapter(
rootView.getContext(),
result,
R.layout.article_list_item,
new String[]{"article_title", "article_PubDate", "article_category", "article_articleNo"},
new int[]{R.id.article_title, R.id.article_PubDate, R.id.article_category, R.id.article_articleNo});
ListView articleItem.setAdapter(adapter);
articleItem.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//I want get the text of R.id.article_articleNo(see article_list_item.xml)?
//What should I do?
}
});
article_list_item.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="#+id/article">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="文章标题"
android:id="#+id/article_title"
android:layout_gravity="center_horizontal" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="30-Apr-2014"
android:id="#+id/article_PubDate"
android:layout_gravity="center_horizontal"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="personal_finance"
android:id="#+id/article_category"
android:layout_gravity="center_horizontal"
android:layout_marginLeft="20dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="9312"
android:id="#+id/article_articleNo"
android:layout_gravity="center_horizontal"
android:layout_marginLeft="20dp"/>
</LinearLayout>
</LinearLayout>
That's all!!
I want to get the text of R.id.article_article (see article_list_item.xml).
How can I do it?
Does this work for you?
articleItem.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String text = result.get(position).get("article_articleNo");
//^^ does not necessarily need to be a string,
// make this whatever data type you are storing in the map
}
});
The idea is that in your SimpleAdapter, you are populating your ListView with a List<Map<String,Object>> (in this case named result).
Therefore, you can get that specific Map<String,Object> from the List by using .get(position), then once again using .get("article_articleNo") to get the Object from the map.
Edit after seeing your comment: Try this:
articleItem.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
TextView tv = (TextView) view.findViewById(R.id.article_articleNo);
String text = tv.getText().toString();
}
});
First of all, forget about the xml layout. It's just a placeholder for data, which is used to define the layout of the data, and has got nothing to do with storing the data.
Now, your problem statement can be re-stated as: how to fetch data from an array (or list or arraylist or whatever the format of your result is) on clicking list item.
Hmm. Sounds simple now.
Refer to #RougeBaneling's answer for technical details.
OK I've searched and seen similar issues, tried them and no avail. I have a listView with some elements and I want to click on one element and display a detail somewhere else.
This is my listView
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pedidos);
ListView listView = (ListView) findViewById(R.id.actualStoresList);
Model.initialize();
Vector<String> values = Model.stores;
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapter, View view, int position,
long id) {
Object o = adapter.getItemAtPosition(position);
String str_text = o.toString();
Log.i("", "I have selected this: " + str_text);
}
});
CustomStringAdapter adapter = new CustomStringAdapter(this, R.layout.my_list_layout, R.id.list_content, values);
listView.setAdapter(adapter);
}
This is the my_list_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:gravity="center_vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="#+id/list_content"
android:textColor="#000000"
android:gravity="center"
android:layout_margin="4dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="20dp"/>
</LinearLayout>
The list gets displayed correctly. When I click on an element of the list (A textView) it "steals" the click event so nothing happens (the onItemClickListener is attached to the listView, not the TextView).
The textView has an small margin where, if careful, I can click just behind it, in fact, touching the listView. In this case, the event gets fired ok and I see the log.
I've tried to set the TextView android:focusable="false" but still, the TextView is "above" of the listView and always gets the click events.
How can I either make the TextView "transparent" so it actually clicks on the listView, or add a onclickListener to the TextView so I can handle its events?
Thanks!
Alejandro
Setting clickable property of TextView to false should solve this problem. Try this:
<TextView
android:id="#+id/list_content"
android:textColor="#000000"
android:gravity="center"
android:layout_margin="4dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="20dp"
android:clickable="false" />
To make items not focusable, do this:
listView.setItemsCanFocus(false);
source
I think this will solve your issue.
Also make sure the
android:textIsSelectable
property is not set to true.
I have a ListView with SimpleCursorAdapter. The layout was using a LinearLayout, but when reading manuals about memory consumption for complex (nested) layouts, I switched to RelativeLayout instead and I've managed to setup the layout exactly as I want.
Now, there's one quirk. In the emulator, I cannot click the list items. It seems as if the elements are one big "no button". However, if I use the emulator arrows and select the listview element (highlights it) and click the button, it works fine.
Why can't I "click" the listview items since I switched to RelativeLayout?
Here's the XML:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<TextView
android:id="#+id/locationName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Junk text"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="#+id/numStores"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/locationName"
android:text="Junk text #1: 117"
android:textSize="10dp" />
<TextView
android:id="#+id/numItems"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/numStores"
android:text="Junk text #2: 42"
android:textSize="10dp" />
</RelativeLayout>
I even tried android:clickable="true" for RelativeLayout, to no avail.
EDIT
Code for onClick is as follows:
listItems.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
int countyID = cursor.getInt(cursor.getColumnIndex(LocationDB.C_ID));
int numItems = cursor.getInt(cursor.getColumnIndex(LocationDB.C_NUM_ITEMS));
int numStores = cursor.getInt(cursor.getColumnIndex(LocationDB.C_NUM_STORES));
String countyName = cursor.getString(cursor.getColumnIndex(LocationDB.C_NAME));
String foo = String.format(TAG + "Clicked ID #%d (%s), stores = %d, items = %d", countyID, countyName, numStores, numItems);
Log.i(LOG_TAG, foo);
// Show the item in a new activity
Intent apan = new Intent(avBase, Browser.class);
apan.putExtra("countyID", countyID);
startActivity(apan);
}
});
EDIT 2
The code is now tested on my phone, and I get the same error; can't click the items when using RelativeLayout.
I faced some issues with this, too, which seemed to be related to the combination of the ListView's on click listeners and those I assigned each individual item in my Adapter.
In my Adapter.getView() I had to make sure the items were configured like:
item.setLongClickable( false );
item.setClickable( false );
item.setOnClickListener( null );
while my ListView had to have its OnItemClickListener and/or its OnItemLongClickListener set.
Turning on clicks on the individual items and on the listview would not work. Maybe that's what's causing your issue, too.
Seems this is a bug that Google ignores: http://code.google.com/p/android/issues/detail?id=3414
I wanted to create a search view like the one Google uses. For this I created the following XML layout, which basically is a search bar and a button in the upper section of the screen and a ListView at the bottom of it.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/LinearLayoutSearch"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:background="#FF394952">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true" >
<EditText android:layout_height="wrap_content" android:id="#+id/searchTextBar" android:layout_width="wrap_content" android:layout_weight="1">
<requestFocus></requestFocus>
</EditText>
<Button android:layout_height="fill_parent" android:layout_width="wrap_content" android:id="#+id/searchButton" android:text="Buscar"></Button>
</LinearLayout>
<ListView
android:id="#+id/searchResultList"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_alignParentBottom="true"
android:layout_weight="1.0" />
</LinearLayout>
And this is the code of the textViewResource that the ArrayAdapter demands on its constructor:
<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
</TextView>
Now, this is the code of the activity. So far, I just want to display the view with the contents (that's why I'm using a static String array for now).
public class SearchActivity extends Activity{
static final String[] COUNTRIES = new String[] {
"Afghanistan", "Albania", "Algeria"};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.searchview);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,R.layout.list_item, COUNTRIES);
ListView lv = (ListView)this.findViewById(R.id.searchResultList);
lv.setAdapter(adapter);
lv.setTextFilterEnabled(true);
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// When clicked, show a toast with the TextView text
Toast.makeText(getApplicationContext(), ((TextView) view).getText(),
Toast.LENGTH_SHORT).show();
}
});
}
}
However, when I run the activity I see the search bar but it doesn't display the ListView.
I've tried changing the extension of SearchActivity to ListActivity, but the program just crashes when I try to start it. I'm also aware of the existence of the Search Interface, but I just want to see this particular method work.
Why it doesn't display the contents of the ListView? Is there a way to fix this?
Thanks in advance
If you are going to use ListActivity you should be aware that ListActivity already has a ListView instance. You need to call its setListAdapter method to set the adapter for its ListView instead of instantiating your own ListView and setting the adapter on it. You can call getListView to get a handle on ListActvity's ListView and then set the click listener on that.
If you want to extend ListActivity then you must have a ListView with id #android:id/list. Change the id of your ListView, that should fix the crash when extending ListActivity.