I'm trying to get the fast scroll pop up containing the large letter to appear when I the fast scroll feature in my list (just like in the image below), but for some reason it won't appear. I've consulted various tutorials but it still doesn't seem to work + I'm not sure if code is missing or some code is in the wrong place. All help would be appreciated.
strings.xml
<resources>
<string name="app_name">World</string>
<string name="action_search">Search</string>
<string name="search_hint">Continent name</string>
<string name="item0">Azerbaijan</string>
<string name="item1">Bosnia & Herzegovina</string>
<string name="item2">Brazil</string>
<string name="item3">China</string>
<string name="item4">Denmark</string>
<string name="item5">France</string>
<string name="item6">Hungary</string>
<string name="item7">Italy</string>
<string name="item8">Japan</string>
<string name="item9">Lithuania</string>
<string name="item10">Luxembourg</string>
<string name="item11">Malta</string>
<string name="item12">Monaco</string>
<string name="item13">Norway</string>
<string name="item14">Portugal</string>
<string name="item15">Thailand</string>
<string name="item16">Singapore</string>
<string name="item17">South Korea</string>
<string name="item18">Sweden</string>
<string name="item19">United Kingdom</string>
<string name="item20">United States</string>
<string name="item0_description">Item 0 description</string>
<string name="item1_description">Item 1 description</string>
<string name="item2_description">Item 2 description</string>
<string name="item3_description">Item 3 description</string>
<string name="item4_description">Item 4 description</string>
<string name="item5_description">Item 5 description</string>
<string name="item6_description">Item 6 description</string>
<string name="item7_description">Item 7 description</string>
<string name="item8_description">Item 8 description</string>
<string name="item9_description">Item 9 description</string>
<string name="item10_description">Item 10 description</string>
<string name="item11_description">Item 11 description</string>
<string name="item12_description">Item 12 description</string>
<string name="item13_description">Item 13 description</string>
<string name="item14_description">Item 14 description</string>
<string name="item15_description">Item 15 description</string>
<string name="item16_description">Item 16 description</string>
<string name="item17_description">Item 17 description</string>
<string name="item18_description">Item 18 description</string>
<string name="item19_description">Item 19 description</string>
<string name="item20_description">Item 20 description</string>
<string-array name="items">
//item 0 <item>@string/item0</item>
//item 1 <item>@string/item1</item>
//item 2 <item>@string/item2</item>
//item 3 <item>@string/item3</item>
//item 4 <item>@string/item4</item>
//item 5 <item>@string/item5</item>
//item 6 <item>@string/item6</item>
//item 7 <item>@string/item7</item>
//item 8 <item>@string/item8</item>
//item 9 <item>@string/item9</item>
//item 10 <item>@string/item10</item>
//item 11 <item>@string/item11</item>
//item 12 <item>@string/item12</item>
//item 13 <item>@string/item13</item>
//item 14 <item>@string/item14</item>
//item 15 <item>@string/item15</item>
//item 16 <item>@string/item16</item>
//item 17 <item>@string/item17</item>
//item 18 <item>@string/item18</item>
//item 19 <item>@string/item19</item>
//item 20 <item>@string/item20</item>
</string-array>
<string-array name="item_descriptions">
//item 0 <item>@string/item0_description</item>
//item 1 <item>@string/item1_description</item>
//item 2 <item>@string/item2_description</item>
//item 3 <item>@string/item3_description</item>
//item 4 <item>@string/item4_description</item>
//item 5 <item>@string/item5_description</item>
//item 6 <item>@string/item6_description</item>
//item 7 <item>@string/item7_description</item>
//item 8 <item>@string/item8_description</item>
//item 9 <item>@string/item9_description</item>
//item 10 <item>@string/item10_description</item>
//item 11 <item>@string/item11_description</item>
//item 12 <item>@string/item12_description</item>
//item 13 <item>@string/item13_description</item>
//item 14 <item>@string/item14_description</item>
//item 15 <item>@string/item15_description</item>
//item 16 <item>@string/item16_description</item>
//item 17 <item>@string/item17_description</item>
//item 18 <item>@string/item18_description</item>
//item 19 <item>@string/item19_description</item>
//item 20 <item>@string/item20_description</item>
</string-array>
</resources>
FragmentCountries.java
public class FragmentCountries extends ListFragment implements SearchView.OnQueryTextListener {
private CountriesListAdapter mAdapter;
public FragmentCountries() {
// Required empty constructor
}
public static FragmentCountries newInstance() {
return new FragmentCountries();
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_countries, container, false);
setHasOptionsMenu(true);
initialize(view);
return view;
}
List<Countries> list = new ArrayList<Countries>();
private void initialize(View view) {
String[] items = getActivity().getResources().getStringArray(R.array.country_names);
String[] itemDescriptions = getActivity().getResources().getStringArray(R.array.country_descriptions);
for (int n = 0; n < items.length; n++){
Countries countries = new Countries();
countries.setID();
countries.setName(items[n]);
countries.setDescription(itemDescriptions[n]);
list.add(countries);
}
mAdapter = new CountriesListAdapter(list, getActivity());
setListAdapter(mAdapter);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// Set up search view
inflater.inflate(R.menu.menu_countries, menu);
MenuItem item = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) MenuItemCompat.getActionView(item);
searchView.setIconifiedByDefault(true);
searchView.clearAnimation();
searchView.setOnQueryTextListener(this);
searchView.setQueryHint(getResources().getString(R.string.search_hint));
View close = searchView.findViewById(R.id.search_close_btn);
close.setBackgroundResource(R.drawable.ic_action_content_clear);
}
@Override
public boolean onQueryTextSubmit(String newText) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
mAdapter.getFilter().filter(newText);
return false;
}
@Override
public int getPositionForSection(int section) {
return alphaIndexer.get(sections[section]);
}
@Override
public int getSectionForPosition(int position) {
return 0;
}
@Override
public Object[] getSections() {
return sections;
}
}
CountriesListAdapter.java
public class CountriesListAdapter extends BaseAdapter implements Filterable, SectionIndexer {
private String mSections = "#ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private List<Countries> mData;
private List<Countries> mFilteredData;
private LayoutInflater mInflater;
private ItemFilter mFilter;
public CountriesListAdapter (List<Countries> data, Context context) {
mData = data;
mFilteredData = new ArrayList(mData);
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount() {
return mFilteredData.size();
}
@Override
public String getItem(int position) {
return mFilteredData.get(position).getName();
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_item_dualline, parent, false);
holder = new ViewHolder();
holder.title = (TextView) convertView.findViewById(R.id.item_name);
holder.description = (TextView) convertView.findViewById(R.id.item_description);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.title.setText(mFilteredData.get(position).getName());
holder.description.setText(mFilteredData.get(position).getDescription());
return convertView;
}
@Override
public Filter getFilter() {
if (mFilter == null) {
mFilter = new ItemFilter();
}
return mFilter;
}
/**
* View holder
*/
static class ViewHolder {
private TextView title;
private TextView description;
}
private class ItemFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if (TextUtils.isEmpty(constraint)) {
results.count = mData.size();
results.values = new ArrayList(mData);
} else {
//Create a new list to filter on
List<Countries> resultList = new ArrayList<Countries>();
for (Countries str : mData) {
if (str.getName().toLowerCase().contains(constraint.toString().toLowerCase())) {
resultList.add(str);
}
}
results.count = resultList.size();
results.values = resultList;
}
return results;
}
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if (results.count == 0) {
mFilteredData.clear();
notifyDataSetInvalidated();
} else {
mFilteredData = (ArrayList<Countries>)results.values;
notifyDataSetChanged();
}
}
}
@Override
public int getPositionForSection(int section) {
return alphaIndexer.get(sections[section]);
}
@Override
public int getSectionForPosition(int position) {
return 0;
}
@Override
public Object[] getSections() {
String[] sections = new String[mSections.length()];
for (int i = 0; i < mSections.length(); i++)
sections[i] = String.valueOf(mSections.charAt(i));
return sections;
}
}
Main.java
public class Main {
public Main(){}
private String continent;
private String description;
private boolean selected;
public String getContinent(){
return continent;
}
public void setContinent(String continent){
this.continent = continent;
}
public String getDescription(){
return description;
}
public void setDescription(String description){
this.description = description;
}
private int _id;
public void getID(int _id){
this._id = _id;
}
public int setID(){
return _id;
}
public boolean isSelected() {
return selected;
}
public void setSelected(boolean selected) {
this.selected = selected;
}
}
drawable/orange_fastscroll_thumb.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:topLeftRadius="44dp"
android:topRightRadius="44dp"
android:bottomLeftRadius="44dp" />
<padding
android:paddingLeft="22dp"
android:paddingRight="22dp" />
<solid android:color="@color/orange" />
</shape>
manifest
<activity
android:name="OrangeActivity"
android:label="@string/orange_title"
android:theme="@style/OrangeTheme" >
</activity>
<style name="OrangeTheme" parent="AppBaseTheme">
<item name="android:fastScrollThumbDrawable">@drawable/orange_fastscroll_thumb</item>
<item name="android:fastScrollOverlayPosition">atThumb</item>
<item name="android:fastScrollTextColor">@color/white</item>
<item name="android:fastScrollTrackDrawable">@drawable/fastscroll_thumb_pressed</item>
</style>
xml layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="@+id/fragmentorange">
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fastScrollEnabled="true"
android:scrollbarStyle="outsideInset">
</ListView>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="@string/no_results"
android:visibility="invisible"
android:gravity="center_horizontal"
android:id="@android:id/empty"
android:layout_marginTop="100dp"
android:textColor="@color/white"/>
</LinearLayout>
MainListAdapter
public class MainListAdapter extends BaseAdapter implements Filterable, SectionIndexer {
private List<Main> mData;
private List<Main> mFilteredData;
private LayoutInflater mInflater;
private ItemFilter mFilter;
private Object[] mSections;
private int[] mSectionsIndexedByPosition;
private int[] mPositionsIndexedBySection;
public MainListAdapter (List<Main> data, Context context) {
mData = data;
mFilteredData = new ArrayList(mData);
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
setupSections();
}
@Override
public int getCount() {
return mFilteredData.size();
}
@Override
public Main getItem(int position) {
return mFilteredData.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_item, parent, false);
holder = new ViewHolder();
holder.title = (TextView) convertView.findViewById(R.id.item);
holder.description = (TextView) convertView.findViewById(R.id.item_description);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
Main main = getItem(position);
holder.title.setText(main.getContinent());
holder.description.setText(main.getDescription());
if (main.isSelected()) {
convertView.setBackgroundColor(Color.parseColor("#1C3F96"));
holder.title.setTextColor(Color.parseColor("#FFFFFF"));
holder.description.setTextColor(Color.parseColor("#FFFFFF"));
} else {
convertView.setBackgroundColor(Color.TRANSPARENT);
holder.title.setTextColor(Color.parseColor("#FFFFFF"));
holder.description.setTextColor(Color.parseColor("#B5B5B5"));
}
holder.title.setText(mFilteredData.get(position).getContinent());
holder.description.setText(mFilteredData.get(position).getDescription());
return convertView;
}
@Override
public Filter getFilter() {
if (mFilter == null) {
mFilter = new ItemFilter();
}
return mFilter;
}
/**
* View holder
*/
static class ViewHolder {
private TextView title;
private TextView description;
}
/**
* Filter for filtering list items
*/
/**
* <p>An array filter constrains the content of the array adapter with
* a prefix. Each item that does not start with the supplied prefix
* is removed from the list.</p>
*/
private class ItemFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if (TextUtils.isEmpty(constraint)) {
results.count = mData.size();
results.values = new ArrayList(mData);
} else {
//Create a new list to filter on
List<Main> resultList = new ArrayList<Main>();
for (Main str : mData) {
if (str.getContinent().toLowerCase().contains(constraint.toString().toLowerCase())) {
resultList.add(str);
}
}
results.count = resultList.size();
results.values = resultList;
}
return results;
}
/**
* Runs on ui thread
* @param constraint the constraint used for the result
* @param results the results to display
*/
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if (results.count == 0) {
mFilteredData.clear();
notifyDataSetInvalidated();
} else {
mFilteredData = (ArrayList<Main>)results.values;
notifyDataSetChanged();
}
setupSections();
}
}
@Override
public int getPositionForSection(int section) {
return mPositionsIndexedBySection[section];
}
@Override
public int getSectionForPosition(int position) {
return mSectionsIndexedByPosition[position];
}
@Override
public Object[] getSections() {
return mSections;
}
private void setupSections() {
String initial = "\0";
List<String> sections = new ArrayList<String>();
mSectionsIndexedByPosition = new int[mFilteredData.size()];
mPositionsIndexedBySection = new int[mFilteredData.size()]; // yes it's bigger than necessary
int section = 0;
for (int pos = 0; pos < mFilteredData.size(); pos++) {
Main country = mFilteredData.get(pos);
if (initial.charAt(0) != country.getContinent().charAt(0)) {
initial = country.getContinent().substring(0, 1);
sections.add(initial);
mPositionsIndexedBySection[section] = pos;
mSectionsIndexedByPosition[pos] = section;
section++;
} else {
mSectionsIndexedByPosition[pos] = section;
}
}
mSections = sections.toArray();
mPositionsIndexedBySection = Arrays.copyOf(mPositionsIndexedBySection, section);
}
}
alphaIndexer
... – TwodimensionalgetSections()
should return String[] {"*", "A" ,... "Z"} ...getSectionForPosition
should return index to the letter based on item data (index of mFilteredData.get(position).getName()[0] in array returned by getSections() ... and getPositionForSection ... you should return index in mFilteredData where first country with letter appear – Twodimensionalimplements Filterable
in the adapter class so how am I supposed to includeimplements SectionIndexer
as well? – Danyelldanyelleimplements SectionIndexer
rather, SectionIndexer
but yes ... and then there will be the hardes part implementation ... but i gave you few hints in the prev comment ... and you be able to do it (looks like a basic programming excercise) – Twodimensional