快速滚动大字母缩略图预览未出现

Fast scroll large letter thumb preview not appearing

当我在列表中使用快速滚动功能时(如下图所示),我试图让包含大字母的快速滚动弹出窗口出现,但由于某种原因它不会出现。我已经查阅了各种教程,但它似乎仍然不起作用 + 我不确定代码是否丢失或某些代码在错误的位置。我们将不胜感激。

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 &amp; 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>

清单

<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布局

<?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 = "[=17=]";
        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);
    }
}

MainListAdapter 中的 setupSections() 替换为以下代码:

    private void setupSections() {

        String initial = "[=10=]";
        List<String> sections = new ArrayList<String>();
        mSectionsIndexedByPosition = new int[mFilteredData.size()];
        mPositionsIndexedBySection = new int[mFilteredData.size()];

        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);
                section = sections.size();
                sections.add(initial);
                mPositionsIndexedBySection[section] = pos;
                mSectionsIndexedByPosition[pos] = section;
            } else {
                mSectionsIndexedByPosition[pos] = section;
            }
        }
        mSections = sections.toArray();
        mPositionsIndexedBySection = Arrays.copyOf(mPositionsIndexedBySection, mSections.length);

    }

关于索引字母的背景,您将 预览背景 缩略图 混淆了。拇指是沿着轨道移动的元素。您称为 orange_fastscroll_thumb.xml 的文件实际上是预览背景,而不是缩略图。如果将名称更改为 orange_fastscroll_preview_bg,则可以这样设置:

<style name="OrangeTheme" parent="AppTheme">
    <item name="android:fastScrollPreviewBackgroundRight">@drawable/orange_fastscroll_preview_bg</item>
    <item name="android:fastScrollOverlayPosition">atThumb</item>
</style>

显然,Google 编写快速滚动代码的方式无法直接设置缩略图和轨道的样式。您可以尝试 this question.

中的一些建议