城市選擇器

網(wǎng)上的城市選擇器很多蔼水,但還是親自動手實現(xiàn)一下,效果如下圖所示
Screenshot_2019-06-25-15-27-44.png

思路:使用RecyclerView的吸附式ItemDecoration(覆寫onDrawOver方法),將分好組的城市的拼音首字母繪制到上面蚤假。觸摸右側(cè)的字母指示器IndicatorView控制RecyclerView滾動到哪個位置栏饮。
所以我們要解決的問題有:
1.RecyclerView吸附式ItemDdecoration
2.獲取漢字拼音的首字母
3.根據(jù)觸摸到的字母,指定Recycler View滾動到對應(yīng)的位置
4.自定義View繪制“熱門磷仰、A抡爹、B······Z”,重寫繪制方法芒划、測量方法冬竟,和觸摸方法。

一:吸附式ItemDecoration民逼。

在滑動的時候會依次調(diào)用onDraw和onDrawOver泵殴,其中onDraw是在ItemView的下層繪制,onDrawOver是在ItemView的上層繪制拼苍⌒ψ纾可以在onDraw中給每一個ItemView繪制分割線,繪制區(qū)域是一個矩形疮鲫,即ItemView的底邊距頂部的高度吆你,以及底邊的offset。在DrawOver中繪制每一組的標(biāo)題俊犯,標(biāo)題的高度會在getItemOffsets中設(shè)置妇多,為rect.top。標(biāo)題位置分為三種情況燕侠,1.跟隨Group第一個View移動者祖。2.在頂部不動。3.頂部的標(biāo)題被下一組的標(biāo)題頂上去绢彤,即跟隨該組最后一個View的底部移動七问。具體情況具體分析。

public class StickyItemDecoration extends RecyclerView.ItemDecoration {
    private final Paint mPaint;
    private final Paint mDividerPaint;
    private OnDrawOverListener mSticky;
    private int mGroupTitleHeight;

    public StickyItemDecoration(Context context, OnDrawOverListener sticky) {
        mSticky = sticky;
        mPaint = new Paint();
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setColor(Color.BLUE);
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        mPaint.setTextSize(dp2px(context, 16));
        mGroupTitleHeight = dp2px(context, 20);
        mDividerPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
    }

    @Override
    public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
        super.onDraw(c, parent, state);
        int childCount=parent.getChildCount();
        RecyclerView.LayoutManager manager = parent.getLayoutManager();
        for (int i = 0; i < childCount; i++) {
            View child=parent.getChildAt(i);
            int left=parent.getPaddingLeft() + manager.getLeftDecorationWidth(child);
            int right=parent.getWidth()-parent.getPaddingRight() - manager.getRightDecorationWidth(child);
            int top=child.getTop()-1;
            int bottom=child.getTop();
            //Item分割線
            c.drawRect(left,top,right,bottom,mDividerPaint);
        }
    }

    @Override
    public void onDrawOver(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
        super.onDrawOver(c, parent, state);
        RecyclerView.LayoutManager manager = parent.getLayoutManager();
        int childCount = parent.getChildCount();
        String preGroupName;
        String groupName = "";
        for (int i = 0; i < childCount; i++) {
            View child = parent.getChildAt(i);
            int childAdapterPosition = parent.getChildAdapterPosition(child);
            preGroupName = groupName;
            groupName = mSticky.getGroupName(childAdapterPosition);
            //和上一個標(biāo)題做對比茫舶,不一樣就需要繪制
            if (preGroupName == groupName) {
                continue;
            }
            int startX = parent.getPaddingLeft() + (manager != null ? manager.getLeftDecorationWidth(child) : 0);
            Paint.FontMetricsInt fontMetrics = mPaint.getFontMetricsInt();
            //標(biāo)題跟隨整個Group滑動
            if (child.getTop() > mGroupTitleHeight) {
                int startY = child.getTop() - (mGroupTitleHeight + fontMetrics.descent + fontMetrics.ascent) / 2;
                c.drawText(groupName, startX, startY, mPaint);
            } else {
                //位于頂部的GroupTitle械巡,在頂部不用動,除非下邊的標(biāo)題頂上來了
                Log.e("TAG", "....." + childAdapterPosition);
                if (childAdapterPosition + 1 <= state.getItemCount()) {
                    //child后面的View的是下一組的第一個饶氏,并且這個child底部露出的高度已經(jīng)小于標(biāo)題高度了讥耗,這時候標(biāo)題會被頂上去
                    if (mSticky.isGroupFirst(childAdapterPosition + 1) && child.getBottom() < mGroupTitleHeight) {
                        int startY = (child.getBottom() - (mGroupTitleHeight + fontMetrics.descent + fontMetrics.ascent) / 2);
                        c.drawText(groupName, startX, startY, mPaint);
                    } else {
                        //在頂部不用動
                        int startY = (mGroupTitleHeight - fontMetrics.descent - fontMetrics.ascent) / 2;
                        c.drawText(groupName, startX, startY, mPaint);
                    }
                }
            }
        }
    }

    @Override
    public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
        Log.e("TAG", "getItemOffsets");
        int childAdapterPosition = parent.getChildAdapterPosition(view);
        if (mSticky.isGroupFirst(childAdapterPosition)) outRect.top = mGroupTitleHeight;
        outRect.bottom = 1;
    }

    public interface OnDrawOverListener {
        String getGroupName(int position);

        boolean isGroupFirst(int position);
    }

    public static int dp2px(Context context, int dp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics());
    }
}

二:獲取漢字拼音的首字

https://www.cnblogs.com/pxblog/p/10604003.html


import java.io.UnsupportedEncodingException;

/**
 * 取得給定漢字串的首字母串,即聲母串
 * Title: ChineseCharToEn
 *
 * @date 注:只支持GB2312字符集中的漢字
 */
public final class ChineseCharToEn {
    private final static int[] li_SecPosValue = {1601, 1637, 1833, 2078, 2274,
            2302, 2433, 2594, 2787, 3106, 3212, 3472, 3635, 3722, 3730, 3858,
            4027, 4086, 4390, 4558, 4684, 4925, 5249, 5590};
    private final static String[] lc_FirstLetter = {"a", "b", "c", "d", "e",
            "f", "g", "h", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s",
            "t", "w", "x", "y", "z"};

    /**
     * 取得給定漢字串的首字母串,即聲母串
     *
     * @param str 給定漢字串
     * @return 聲母串
     */
    public static String getAllFirstLetter(String str) {
        if (str == null || str.trim().length() == 0) {
            return "";
        }

        String _str = "";
        for (int i = 0; i < str.length(); i++) {
            _str = _str + getFirstLetter(str.substring(i, i + 1));
        }

        return _str;
    }

    /**
     * 取得給定漢字的首字母,即聲母
     *
     * @param chinese 給定的漢字
     * @return 給定漢字的聲母
     */
    public static String getFirstLetter(String chinese) {
        if (chinese == null || chinese.trim().length() == 0) {
            return "";
        }
        chinese = conversionStr(chinese, "GB2312", "ISO8859-1");

        if (chinese.length() > 1) // 判斷是不是漢字
        {
            int li_SectorCode = (int) chinese.charAt(0); // 漢字區(qū)碼
            int li_PositionCode = (int) chinese.charAt(1); // 漢字位碼
            li_SectorCode = li_SectorCode - 160;
            li_PositionCode = li_PositionCode - 160;
            int li_SecPosCode = li_SectorCode * 100 + li_PositionCode; // 漢字區(qū)位碼
            if (li_SecPosCode > 1600 && li_SecPosCode < 5590) {
                for (int i = 0; i < 23; i++) {
                    if (li_SecPosCode >= li_SecPosValue[i]
                            && li_SecPosCode < li_SecPosValue[i + 1]) {
                        chinese = lc_FirstLetter[i];
                        break;
                    }
                }
            } else // 非漢字字符,如圖形符號或ASCII碼
            {
                chinese = conversionStr(chinese, "ISO8859-1", "GB2312");
                chinese = chinese.substring(0, 1);
            }
        }

        return chinese;
    }

    /**
     * 字符串編碼轉(zhuǎn)換
     *
     * @param str           要轉(zhuǎn)換編碼的字符串
     * @param charsetName   原來的編碼
     * @param toCharsetName 轉(zhuǎn)換后的編碼
     * @return 經(jīng)過編碼轉(zhuǎn)換后的字符串
     */
    private static String conversionStr(String str, String charsetName, String toCharsetName) {
        try {
            str = new String(str.getBytes(charsetName), toCharsetName);
        } catch (UnsupportedEncodingException ex) {
            System.out.println("字符串編碼轉(zhuǎn)換異常:" + ex.getMessage());
        }
        return str;
    }

    public static void main(String[] args) {
        System.out.println("獲取拼音首字母:" + getAllFirstLetter("大中國南昌中大china"));
    }
}

三:RecyclerView滾動到指定位置pos

http://www.reibang.com/p/6d5ecfdbb615

四:自定義字母指示器IndicatorView

1.繪制data中的字符串:熱門、A嚷往、B葛账、C······Z
2.測量大小onMeasure
3.重寫onTouch方法,通過觸摸的位置的坐標(biāo)皮仁,計算出觸摸的是哪個字母,并傳入回調(diào)接口中

package com.app.cityselector.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;

import java.util.List;

public class IndicatorView extends View {

    private Context context;
    private List<String> data;
    private Paint paint;
    private float ascent;
    private float descent;
    private float textHeight;
    private float textGap;
    private float charWidth;
    private int paddingLeft;
    private int paddingRight;

    public IndicatorView(Context context) {
        this(context, null);
    }

    public IndicatorView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public IndicatorView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context = context;
        initView();
    }

    private void initView() {
        paint = new Paint();
        DisplayMetrics metrics = context.getResources().getDisplayMetrics();
        paint.setTextSize(9 * metrics.density);
        ascent = paint.getFontMetrics().ascent;
        descent = paint.getFontMetrics().descent;
        textHeight = Math.abs(ascent - descent);
        charWidth = paint.measureText("A");
    }

    public void setData(List<String> data) {
        this.data = data;
        invalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        float y = 0;
        y = -ascent + textGap / 2;
        float x = (getWidth() - paddingLeft - paddingRight - charWidth) / 2;
        for (int i = 0; i < data.size(); i++) {
            canvas.drawText(data.get(i), i == 0 ? 0 : x, y, paint);
            y += textHeight + textGap;
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);

        int width = widthSize;
        int height = heightSize;
        paddingLeft = getPaddingLeft();
        paddingRight = getPaddingRight();
        //wrap_content:計算得出最小的寬高,
        //match_content或具體值:撐滿父容器贷祈,空出來的地方作為item間隔平均分布到item之間
        if (widthMode == MeasureSpec.EXACTLY) {
            width = widthSize;
        } else {
            width = (int) paint.measureText("熱門") + paddingLeft + paddingRight;
        }
        if (heightMode == MeasureSpec.EXACTLY) {
            height = heightSize;
            textGap = (height - textHeight * data.size()) / data.size();
        } else {
            height = (int) (Math.abs(paint.getFontMetrics().ascent - paint.getFontMetrics().descent) * data.size());
        }
        setMeasuredDimension(width, height);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float y = event.getY();
        int index = (int) (y / (textGap + textHeight));
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_MOVE:
                if (onItemTouched != null) {
                    onItemTouched.onTouched(data.get(index), index);
                }
                break;
            case MotionEvent.ACTION_UP:
                if (onItemTouched != null) {
                    onItemTouched.onTouchedUp(data.get(index), index);
                }
                break;
        }
        return true;
    }

    OnItemTouched onItemTouched;

    public void setOnItemTouched(OnItemTouched onItemTouched) {
        this.onItemTouched = onItemTouched;
    }

    public interface OnItemTouched {
        void onTouched(String s, int pos);

        void onTouchedUp(String s, int pos);
    }

}

以上三步做好后趋急,就完成了準(zhǔn)備工作。
CitySelectorView中使用RecyclerView展示數(shù)據(jù)势誊,根據(jù)右側(cè)的字母指示器指定RecyclerView滾動到指定pos呜达。
實體類:

public class CityBean {
    private int id;
    private String code;
    private String name;
    //getter and setter
    ......
}

CityAdapter:展示的數(shù)據(jù)有熱門城市和普通城市Item,所以要區(qū)分兩類itemType

package com.app.cityselector.view.adapter;

import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.app.cityselector.R;
import com.app.cityselector.bean.CityBean;

import java.util.List;

public class CityAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    public static final int TYPE_HOT_CITY = 1;
    public static final int TYPE_CITY_ITEM = 2;
    private final LayoutInflater inflater;

    Context context;
    //熱門城市
    List<CityBean> hotCitys;
    //全部城市
    List<CityBean> allCitys;

    public CityAdapter(Context context) {
        this.context = context;
        inflater = LayoutInflater.from(context);
    }

    public void setHotCitys(List<CityBean> hotCitys) {
        this.hotCitys = hotCitys;
    }

    public void setAllCitys(List<CityBean> allCitys) {
        this.allCitys = allCitys;
    }

    @Override
    public int getItemViewType(int position) {
        if (hotCitys != null && position == 0) {
            return TYPE_HOT_CITY;
        } else {
            return TYPE_CITY_ITEM;
        }
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int type) {
        if (type == TYPE_HOT_CITY) {
            return new HotCityViewHolder(inflater.inflate(R.layout.item_hot_city, viewGroup, false));
        } else if (type == TYPE_CITY_ITEM) {
            return new CityItemViewHolder(inflater.inflate(R.layout.item_city, viewGroup, false));
        }
        return null;
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
        if (viewHolder instanceof HotCityViewHolder) {
            HotCityViewHolder hotCityViewHolder = (HotCityViewHolder) viewHolder;
            hotCityViewHolder.bindData(hotCitys);
        } else if (viewHolder instanceof CityItemViewHolder) {
            CityItemViewHolder cityItemViewHolder = (CityItemViewHolder) viewHolder;
            CityBean cityBean = allCitys.get(hotCitys != null ? i - 1 : i);
            cityItemViewHolder.bindData(cityBean);
        }
    }

    @Override
    public int getItemCount() {
        int count = 0;
        if (hotCitys != null) {
            count++;
        }
        if (allCitys != null) {
            count += allCitys.size();
        }
        return count;
    }

    static class CityItemViewHolder extends RecyclerView.ViewHolder {

        private TextView tvCityName;

        public CityItemViewHolder(@NonNull View itemView) {
            super(itemView);
            tvCityName = itemView.findViewById(R.id.tv_city_name);
        }

        public void bindData(CityBean cityBean) {
            tvCityName.setText(cityBean.getName());
        }
    }

    static class HotCityViewHolder extends RecyclerView.ViewHolder {

        private LinearLayout llHotCityContainer;
        //熱門城市的列數(shù)
        int hotColumn = 3;

        public void setHotColumn(int hotColumn) {
            this.hotColumn = hotColumn;
        }

        public HotCityViewHolder(@NonNull View itemView) {
            super(itemView);
            llHotCityContainer = itemView.findViewById(R.id.gl_hot_city_container);
        }
        //展示熱門城市
        public void bindData(List<CityBean> cityBeans) {
            llHotCityContainer.removeAllViews();
            Context context = itemView.getContext();
            int halfMargin = context.getResources().getDimensionPixelSize(R.dimen.base_margin_half);
            int paddingVertical = context.getResources().getDimensionPixelSize(R.dimen.padding_vertical);
            int row = cityBeans.size() / hotColumn;
            for (int i = 0; i < row + 1; i++) {
                LinearLayout llRow = new LinearLayout(context);
                llRow.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
                llRow.setPadding(halfMargin, halfMargin, halfMargin, halfMargin);
                for (int j = 0; j < hotColumn; j++) {
                    int index = row * i + j;
                    if (index < cityBeans.size()) {
                        CityBean cityBean = cityBeans.get(index);
                        TextView textView = new TextView(context);
                        textView.setText(cityBean.getName());
                        textView.setBackgroundResource(R.drawable.bg_hot_city);
                        textView.setClickable(true);
                        textView.setPadding(0, paddingVertical, 0, paddingVertical);
                        textView.setGravity(Gravity.CENTER);
                        textView.setTextColor(context.getResources().getColor(R.color.colorText));
                        textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
                        //setLayoutParams
                        LinearLayout.LayoutParams textLayoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
                        textLayoutParams.weight = 1;
                        textLayoutParams.leftMargin = halfMargin;
                        textLayoutParams.rightMargin = halfMargin;
                        textView.setLayoutParams(textLayoutParams);
                        llRow.addView(textView);
                    }
                }
                llHotCityContainer.addView(llRow);
            }
        }
    }
}

重點來了粟耻,當(dāng)觸摸右邊的字母指示器時查近,根據(jù)字母獲取RecyclerView中的城市名稱的拼音的出現(xiàn)該字母的第一個位置,如果找不到挤忙,就定位到上一個字母出現(xiàn)的位置霜威。



    /**
     * 根據(jù)ABC...Z獲取第一次出現(xiàn)的pos
     *
     * @param s
     * @return
     */
    private int getFirstPos(String s) {
        if ("熱門".equals(s)) {
            return 0;
        }
        int pos = 0;
        if (hotCity != null) {
            pos++;
        }
        int firstPos = 0;
        for (int i = 0; i < allCity.size(); i++) {
            //相等
            String firstLetter = ChinessToEn.getFirstLetter(allCity.get(i).getName()).toUpperCase();
            int compare = firstLetter.compareToIgnoreCase(s);
            if (compare == 0) {
                firstPos = i;
                break;
            } else if (compare < 0) {
                if (i > 1 && !allCity.get(i).getName().equals(allCity.get(i - 1).getName())) {
                    firstPos = i;
                }
            } else {
                break;
            }
        }
        pos += firstPos;
        return pos;
    }

獲取到位置后,就可以混動RecyclerView了

 public static void moveToPosition(LinearLayoutManager manager, RecyclerView mRecyclerView, int n) {
        int firstItem = manager.findFirstVisibleItemPosition();
        int lastItem = manager.findLastVisibleItemPosition();
        if (n <= firstItem) {
            mRecyclerView.scrollToPosition(n);
        } else if (n <= lastItem) {
            int top = mRecyclerView.getChildAt(n - firstItem).getTop();
            mRecyclerView.scrollBy(0, top);
        } else {
            mRecyclerView.scrollToPosition(n);
        }
    }

CitySelectorView完成代碼:


public class CitySelectorView extends FrameLayout implements View.OnClickListener {

    private Context context;
    private RecyclerView recyclerView;
    private IndicatorView indicatorView;
    private TextView tvCenter;

    private LinearLayoutManager layoutManager;
    private CityAdapter adapter;
    private List<CityBean> hotCity;
    private List<CityBean> allCity;
    private String[] indecatorData = new String[]{"熱門", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"};

    public void setHotCity(List<CityBean> hotCity) {
        this.hotCity = hotCity;
    }

    public void setAllCity(List<CityBean> allCity) {
        this.allCity = allCity;
    }

    public void notifyDataSetChanged() {
        adapter.setHotCitys(hotCity);
        adapter.setAllCitys(allCity);
        adapter.notifyDataSetChanged();
    }

    public CitySelectorView(@NonNull Context context) {
        this(context, null);
    }

    public CitySelectorView(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CitySelectorView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        this.context = context;
        init();
    }

    private void init() {
        LayoutInflater.from(context).inflate(R.layout.view_city_selector, this, true);

        recyclerView = findViewById(R.id.recycler_city);
        tvCenter = findViewById(R.id.tv_center);
        indicatorView = findViewById(R.id.indicator);
        //set RecyclerView
        layoutManager = new LinearLayoutManager(context);
        recyclerView.setLayoutManager(layoutManager);
        //吸附式
        recyclerView.addItemDecoration(new StickyItemDecoration(context, new ISticky() {
            @Override
            public boolean isGroupFirst(int pos) {
                if (hotCity != null) {
                    if (pos == 0) return true;
                    if (allCity != null && allCity.size() != 0) {
                        if (pos == 1) {
                            return true;
                        } else {
                            return !ChinessToEn.getFirstLetter(allCity.get(pos - 1).getName()).equals(ChinessToEn.getFirstLetter(allCity.get(pos - 2).getName()));
                        }
                    }
                    return false;
                } else {
                    if (pos == 0) return true;
                    if (allCity != null && allCity.size() != 0) {
                        return !ChinessToEn.getFirstLetter(allCity.get(pos).getName()).equals(ChinessToEn.getFirstLetter(allCity.get(pos - 1).getName()));
                    }
                    return false;
                }
            }

            @Override
            public String getGroupTitle(int pos) {
                if (hotCity != null) {
                    if (pos == 0) return "熱門";
                    if (allCity != null && allCity.size() != 0) {
                        return ChinessToEn.getFirstLetter(allCity.get(pos - 1).getName()).toUpperCase();
                    }
                } else {
                    if (allCity != null && allCity.size() != 0) {
                        return ChinessToEn.getFirstLetter(allCity.get(pos).getName()).toUpperCase();
                    }
                }
                return null;
            }
        }));
        adapter = new CityAdapter(context);
        recyclerView.setAdapter(adapter);

        indicatorView.setData(Arrays.asList(indecatorData));
        indicatorView.setOnItemTouched(new IndicatorView.OnItemTouched() {
            @Override
            public void onTouched(String s, int pos) {
                tvCenter.setVisibility(VISIBLE);
                tvCenter.setText(s);
                int firstPos = getFirstPos(s);
                L.e(firstPos);
                moveToPosition(layoutManager, recyclerView, firstPos);
            }

            @Override
            public void onTouchedUp(String s, int pos) {
                tvCenter.setVisibility(INVISIBLE);
            }
        });
    }

    @Override
    public void onClick(View v) {

    }

    /**
     * 根據(jù)ABC...Z獲取第一次出現(xiàn)的pos
     *
     * @param s
     * @return
     */
    private int getFirstPos(String s) {
        if ("熱門".equals(s)) {
            return 0;
        }
        int pos = 0;
        if (hotCity != null) {
            pos++;
        }
        int firstPos = 0;
        for (int i = 0; i < allCity.size(); i++) {
            //相等
            String firstLetter = ChinessToEn.getFirstLetter(allCity.get(i).getName()).toUpperCase();
            int compare = firstLetter.compareToIgnoreCase(s);
            if (compare == 0) {
                firstPos = i;
                break;
            } else if (compare < 0) {
                if (i > 1 && !allCity.get(i).getName().equals(allCity.get(i - 1).getName())) {
                    firstPos = i;
                }
            } else {
                break;
            }
        }
        pos += firstPos;
        return pos;
    }

    /**
     * RecyclerView 移動到當(dāng)前位置册烈,
     *
     * @param manager       設(shè)置RecyclerView對應(yīng)的manager
     * @param mRecyclerView 當(dāng)前的RecyclerView
     * @param n             要跳轉(zhuǎn)的位置
     */
    public static void moveToPosition(LinearLayoutManager manager, RecyclerView mRecyclerView, int n) {
        int firstItem = manager.findFirstVisibleItemPosition();
        int lastItem = manager.findLastVisibleItemPosition();
        if (n <= firstItem) {
            mRecyclerView.scrollToPosition(n);
        } else if (n <= lastItem) {
            int top = mRecyclerView.getChildAt(n - firstItem).getTop();
            mRecyclerView.scrollBy(0, top);
        } else {
            mRecyclerView.scrollToPosition(n);
        }
    }
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末戈泼,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子赏僧,更是在濱河造成了極大的恐慌大猛,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件淀零,死亡現(xiàn)場離奇詭異挽绩,居然都是意外死亡,警方通過查閱死者的電腦和手機驾中,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進店門琼牧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人哀卫,你說我怎么就攤上這事巨坊。” “怎么了此改?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵趾撵,是天一觀的道長。 經(jīng)常有香客問我共啃,道長占调,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任移剪,我火速辦了婚禮究珊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘纵苛。我一直安慰自己剿涮,他們只是感情好言津,可當(dāng)我...
    茶點故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著取试,像睡著了一般悬槽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上瞬浓,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天初婆,我揣著相機與錄音,去河邊找鬼猿棉。 笑死磅叛,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的萨赁。 我是一名探鬼主播弊琴,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼位迂!你這毒婦竟也來了访雪?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤掂林,失蹤者是張志新(化名)和其女友劉穎臣缀,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體泻帮,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡精置,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了锣杂。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片脂倦。...
    茶點故事閱讀 40,013評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖元莫,靈堂內(nèi)的尸體忽然破棺而出赖阻,到底是詐尸還是另有隱情,我是刑警寧澤踱蠢,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布火欧,位于F島的核電站,受9級特大地震影響茎截,放射性物質(zhì)發(fā)生泄漏苇侵。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一企锌、第九天 我趴在偏房一處隱蔽的房頂上張望榆浓。 院中可真熱鬧,春花似錦撕攒、人聲如沸陡鹃。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽杉适。三九已至谎倔,卻和暖如春柳击,著一層夾襖步出監(jiān)牢的瞬間猿推,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工捌肴, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蹬叭,地道東北人。 一個月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓状知,卻偏偏與公主長得像秽五,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子饥悴,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,960評論 2 355

推薦閱讀更多精彩內(nèi)容