IT技術互動交流平台

ItemDecoration詳解以及用ItemDecoration實現按字母排序列表

來源-_众购彩票网址多少:IT165收集  發布日期-外地车过户北京:2016-12-19 20:31:50

首先看看實現的效果

可以看出要實現上麵效果--云帆彩票,有三個步驟|||盈彩网彩票怎么样:

1.漢字轉化為拚音||诺基亚c300软件,並且根據首字母排序

2.用ItemDecoration實現字母行的顯示

3.自定義實現右側的按字母導航欄

當然重點講講ItemDecoration的實現|云端彩票主页。都知道RecyclerView本身都沒有分割線-|才子打电话骂小花,需要分割線都是在item中畫一條線或者使用ItemDecoration來實現分割線_|_金士顿u盘恢复工具。在RecyclerView中我們可以給每一個item都添加ItemDecoration__台服vpn,所以可以自定義ItemDecoration來實現各種我們所需要的效果-111彩票漏洞。

ItemDecoration

ItemDecoration是RecyclerView內部的一個抽象類_栾海燕,要實現這個抽象類自然需要實現內部的抽象方法--茅台一品天下,除了deprecated的方法隻有下麵三個方法_-_经典图文日志:

1.void getItemOffsets(Rect outRect, View view, RecyclerView parent, State state)

這個方法是用來指定每一個的item對應decoration的大小區域|106彩票注册,主要實現方式就是設置outRect的left||掌上彩票官网、top|玩具熊不要冬眠、right-_20l8144期跑狗新图、bottom-_自由们7 42官方下载,如果一個item不需要decoration把outRect的上下左右設置為0即可_|18年彩票中奖号码。盜用網上一張圖看看outRect具體什麼意思

2.void onDraw(Canvas c, RecyclerView parent, State state)

onDraw方法看名字大家都應該很熟悉-_苏州园区临时工招聘,這個方法自然是用來畫具體的ItemDecoration的--_意彩怎么注册,繪製的內容是顯示在itemView的下層|-永城。下層什麼意思||欧布 奥特曼,待會來看看众亿彩票首页。

3.void onDrawOver(Canvas c, RecyclerView parent, State state)

也是一個繪製的方法-__盈彩在线APP,不過是繪製在itemView的上層

以上三個方法的調用順序也就是按照上麵的排列的順序來調用的||永安彩票真假。

首先來看看用ItemDecoration實現的分割線DividerItemDecoration

 

public class DividerItemDecoration extends RecyclerView.ItemDecoration {

    private static final int[] ATTRS = new int[]{android.R.attr.listDivider};

    public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;

    public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;


    private Drawable mDivider;

    private int mOrientation;

    public DividerItemDecoration(Context context, int orientation) {
        //獲取係統的divider
        final TypedArray a = context.obtainStyledAttributes(ATTRS);
        mDivider = a.getDrawable(0);
        a.recycle();
        setOrientation(orientation);
    }

    public void setOrientation(int orientation) {
        if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
            throw new IllegalArgumentException("invalid orientation");
        }
        mOrientation = orientation;
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        super.onDraw(c, parent, state);
        if (mOrientation == VERTICAL_LIST) {
            drawVertical(c, parent);
        } else {
            drawHorizontal(c, parent);
        }
    }

    //畫豎直分割線
    public void drawVertical(Canvas c, RecyclerView parent) {
        //左邊緣距離RecyclerView左邊的距離
        final int left = parent.getPaddingLeft();
        //右邊緣距離RecyclerView右邊邊的距離
        final int right = parent.getWidth() - parent.getPaddingRight();

        final int childCount = parent.getChildCount();

        for (int i = 0; i < childCount; i++) {
            final View child = parent.getChildAt(i);
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int top = child.getBottom() + params.bottomMargin;
            final int bottom;
            //去掉最後一條的分割線
            if (i == childCount - 1) {//bottom和top相等__|霍启仁antonia,即高度為0 不顯示
                bottom = top;
            } else {
                bottom = top + mDivider.getIntrinsicHeight();
            }
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    //畫水平分割線
    public void drawHorizontal(Canvas c, RecyclerView parent) {
        final int top = parent.getPaddingTop();
        final int bottom = parent.getHeight() - parent.getPaddingBottom();

        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = parent.getChildAt(i);
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int left = child.getRight() + params.rightMargin;
            final int right = left + mDivider.getIntrinsicHeight();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
        if (mOrientation == VERTICAL_LIST) {
            outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
        } else {
            outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
        }
    }
}
主要實現了getItemOffsets和onDraw方法||_娱乐天地点检官网注册,因為這兩個方法已經能滿足了-__基督教赞美诗歌1218,自然不需要全部方法實現__苏果之家。在getItemOffsets方法中判斷是豎直方向還是水平方向的分割線_|闪电强效瘦,豎直方向隻需要在outRect的bottom加上分割線的寬度即可||_阳泉中行吧,當然水平分割線在右邊加上就OK-_|亿彩彩票v160。在onDraw方法中具體的畫出分割線|--苏铁惜,不知道大家有沒有想過這裏的分割線高度和outRect中設置的高度有什麼關係_-少年进化论成员,那麼下麵修改一下代碼實驗一下__qq空间留言代码爱情。

 

在上麵onDraw畫豎直分割線的方法中_-喂养恐龙赚钱,把分割線高度加上80px_苏通大桥有多长,即|-爵迹风津道14:

 

mDivider.setBounds(left, top, right, bottom+80);

 

效果沒變化|__365彩票快3?意思是onDraw裏麵畫的區域大小不會超過outRect設置的大小嗎_-偃师户外?記得之前說過||-第六感 电影,onDraw方法繪製的內容是在itemView的下層的_|-沈绛红,會不會是被itemView遮擋而沒有顯示出來呢-||打吊针原曲,那麼下麵我們把itemView的背景色改為透明_||优点彩票APP,看看效果

android:background="@android:color/transparent"

 

這次看到了不同了吧|英皇娱乐,正是我們所猜想的那樣--塞班5800论坛。也就證明了onDraw方法顯示的內容實在itemView的下層-|艺术生百日冲刺这本书,同時它繪製的內容並不是不會超過outRect指定的區域__|欧拉迪官网,而outRect指定的區域也是實際分配給ItemDecoration的區域_盐城招标,在這個區域繪製才不會影響itemView__好千度,所以onDraw繪製的內容我們應該要保持和outRect給定的區域是相同的|-8万以内买什么车好。

顯示字母的ItemDecoration

現在來看看顯示字母的ItemDecoration是怎麼實現的-|-家教宣传单。看上麵的效果可以發現--|冷情王爷痴情妃,最上麵始終顯示了一個ItemDecoration||定位修改,上麵說過onDrawOver方法繪製的內容是顯示在最上層-厦门红盾网,所以用這個方法來繪製最上麵再適合不過了--_观赏鱼之家水族zadull。其他itemView顯示字母的ItemDecoration也並不是采用onDraw方法繪製__11086移动彩票能提现吗,而是用xml實現的-_芒草扫把,因為采用xml方式來實現可以更方便的來定製ItemDecoration的內容|-菊丸英二bg,也可以實現其中的點擊事件|-炫彩魔盒。

在看ItemDecoration之前|__盈彩网站首页,先看看所用到的一個接口和RecyclerView的Adapter

 

public interface StickyHeaderAdapter<T extends RecyclerView.ViewHolder> {

    
    String getHeaderId(int position);

    
    T onCreateHeaderViewHolder(ViewGroup parent);

    
    void onBindHeaderViewHolder(T viewholder, int position);
}
這個接口裏麵有三個方法-_2w彩票2m永久兔费资料,第一個方法是獲取headerId_-wifi共享精灵手机连不上,因為在顯示是不可能每一個item都要顯示decoration_众盈彩票怎么样,隻有每種首字母第一個才顯示|111彩票应用,所用這裏需要一個id來判斷是否需要設置ItemDecoration-_-厦门一中。後麵兩個方法是仿照RecyclerView.Adapter的寫的||苏州车险哪家好,因為我們采用ItemDecoration布局用xml實現-|_广州鸣人堂,如果需要顯示的ItemDecoration很多的話|_癫痫1rdt,每次都需要去用LayoutInflater去加載布局_|-中国票房,顯然不夠優雅||_移动彩票app,所用用holder機製來實現複用__金家墩客运站时刻表。下麵來看看我們的Adapter

 

 

/**
 * Created by lzy .
 * Date: 16/11/24
 */
public class MedicineAdapter extends RecyclerView.Adapter<MedicineAdapter.ViewHolder> implements
        StickyHeaderAdapter<MedicineAdapter.HeaderHolder> {
    private Context mContext;
    private List<MedicineBean> mDatas;
    private LayoutInflater mInflater;
    private int i;

    public MedicineAdapter(Context mContext, List<MedicineBean> mDatas) {
        this.mContext = mContext;
        this.mDatas = mDatas;
        mInflater = LayoutInflater.from(mContext);
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new ViewHolder(mInflater.inflate(R.layout.item_medicine, parent, false));
    }

    @Override
    public void onBindViewHolder(final ViewHolder holder, final int position) {
        final MedicineBean MedicineBean = mDatas.get(position);
        holder.tvName.setText(MedicineBean.getName());
    }

    @Override
    public int getItemCount() {
        return mDatas != null ? mDatas.size() : 0;
    }

    @Override
    public String getHeaderId(int position) {
        return mDatas.get(position).getLetter();
    }

    @Override//生成header的布局
    public HeaderHolder onCreateHeaderViewHolder(ViewGroup parent) {
        return new HeaderHolder(mInflater.inflate(R.layout.item_decoration, parent, false));
    }

    @Override//綁定header的數據
    public void onBindHeaderViewHolder(HeaderHolder viewholder, int position) {
        viewholder.header.setText(mDatas.get(position).getLetter());
    }

    /**
     * 根據分類的首字母獲取其第一次出現該首字母的位置
     */
    public int getPositionForSection(String section) {
        for (int i = 0; i < mDatas.size(); i++) {
            String sortStr = mDatas.get(i).getLetter();
            if (sortStr.equals(section)) {
                return i;
            }
        }
        return -1;
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {
        TextView tvName;

        public ViewHolder(View itemView) {
            super(itemView);
            tvName = (TextView) itemView.findViewById(R.id.name);
        }
    }

    public static class HeaderHolder extends RecyclerView.ViewHolder {
        public TextView header;

        public HeaderHolder(View itemView) {
            super(itemView);
            header = (TextView) itemView;
        }
    }
}
可以看到這個Adapter實現了之前上麵的接口|||例外包包官网,接口的實現方式和普通的Adapter的實現都類似在onCreateHeaderViewHolder中加載xml文件_-电大作业答案网,在onBindHeaderViewHolder中加載數據||全国专科学校排名,HeaderHolder也是一樣的___掌上恭城下载平台,headerId是采用的一個letter的|-2240七星彩图规论坛,也就是每一條的首字母||天天酷跑大猫头。下麵看看ItemDecoration是怎麼實現的-__青州卫校。

 

getItemOffsets方法

首先看看第一個getItemOffsets方法的實現

 

 @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
        //得到該item所在的位置
        int position = parent.getChildAdapterPosition(view);

        int headerHeight = 0;
        //在使用adapterPosition時最好的加上這個判斷
        if (position != RecyclerView.NO_POSITION && hasHeader(position)) {
            //獲取到ItemDecoration所需要的高度
            View header = getHeader(parent, position).itemView;
            headerHeight = header.getHeight();
        }
        outRect.set(0, headerHeight, 0, 0);
    }
很簡單-_-赵奕欢献唱公益,就是判斷如果這個item需要ItemDecoration就獲取到header的高度--_盈彩彩票可靠吗,設置給outRect

 

判斷是否需要header

判斷是否需要header的方法_-易网彩票,之前不是在Adapter裏麵寫了getHeaderId的方法嗎_|励志小说排行榜前十名,這裏就用到了_||青岛市公交线路图,根據前兩個headerId是否相同來判斷是否需要設置ItemDecoration

 

private boolean hasHeader(int position) {
        if (position == 0) {//第一個位置必然有
            return true;
        }
        //判斷和上一個的id不同則有header
        int previous = position - 1;
        return !mAdapter.getHeaderId(position).equals(mAdapter.getHeaderId(previous));
    }

獲取Header的方法

 

private RecyclerView.ViewHolder getHeader(RecyclerView parent, int position) {
        //創建HeaderViewHolder
        MedicineAdapter.HeaderHolder holder = mAdapter.onCreateHeaderViewHolder(parent);
        final View header = holder.itemView;
        //綁定數據
        mAdapter.onBindHeaderViewHolder(holder, position);
        //測量View並且layout
        int widthSpec = View.MeasureSpec.makeMeasureSpec(parent.getWidth(), View.MeasureSpec.EXACTLY);
        int heightSpec = View.MeasureSpec.makeMeasureSpec(parent.getHeight(), View.MeasureSpec.UNSPECIFIED);
        //根據父View的MeasureSpec和子view自身的LayoutParams以及padding來獲取子View的MeasureSpec
        int childWidth = ViewGroup.getChildMeasureSpec(widthSpec,
                parent.getPaddingLeft() + parent.getPaddingRight(), header.getLayoutParams().width);
        int childHeight = ViewGroup.getChildMeasureSpec(heightSpec,
                parent.getPaddingTop() + parent.getPaddingBottom(), header.getLayoutParams().height);
        //進行測量
        header.measure(childWidth, childHeight);
        //根據測量後的寬高放置位置
        header.layout(0, 0, header.getMeasuredWidth(), header.getMeasuredHeight());
        return holder;
    }
在這裏麵調用了之前Adapter實現接口裏麵的方法_|众赢彩票主页,創建了ViewHolder__11068彩票app,綁定了數據||-易旺彩票网下载。都知道自定義view需要實現onMeasure-_淮钢吧、onLayout_-_亿彩登录网址、onDraw方法|-_重庆城投集团,所以在這裏對它進行了測量和放置-_-盈彩彩票注册邀请码,而draw是在onDrawOver裏麵實現的|-新普桑2013款图片。對這裏熟悉的可以去看看相關的知識點_-雷区里的工具。

 

onDrawOver方法

 

@Override
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
        final int count = parent.getChildCount();

        for (int layoutPos = 0; layoutPos < count; layoutPos++) {
            final View child = parent.getChildAt(layoutPos);

            final int adapterPos = parent.getChildAdapterPosition(child);
            //隻有在最上麵一個item或者有header的item才繪製ItemDecoration
            if (adapterPos != RecyclerView.NO_POSITION && (layoutPos == 0 || hasHeader(adapterPos))) {
                View header = getHeader(parent, adapterPos).itemView;
                c.save();
                final int left = child.getLeft();
                final int top = getHeaderTop(parent, child, header, adapterPos, layoutPos);
                c.translate(left, top);
                header.setTranslationX(left);
                header.setTranslationY(top);
                header.draw(c);
                c.restore();
            }
        }
    }
這裏就是一個循環-捧腹网搞笑动态图片,在需要Header的地方進行繪製||01彩票真的能赚钱吗,當然需要把畫布移動到要繪製的位置_|11选5助手苹果版app,主要是確定它距離頂部的大小-雷波溪洛渡。

 

 

private int getHeaderTop(RecyclerView parent, View child, View header, int adapterPos, int layoutPos) {
        int headerHeight = header.getHeight();
        int top = ((int) child.getY()) - headerHeight;
        if (layoutPos == 0) {//處理最上麵兩個ItemDecoration切換時
            final int count = parent.getChildCount();
            final String currentId = mAdapter.getHeaderId(adapterPos);
            for (int i = 1; i < count; i++) {
                int adapterPosHere = parent.getChildAdapterPosition(parent.getChildAt(i));
                if (adapterPosHere != RecyclerView.NO_POSITION) {
                    String nextId = mAdapter.getHeaderId(adapterPosHere);
                    if (!nextId.equals(currentId)) { //找到下一個不同類的view
                        final View next = parent.getChildAt(i);
                        //這裏計算offset畫個圖會很清楚
                        final int offset = ((int) next.getY()) - (headerHeight + getHeader(parent, adapterPosHere).itemView.getHeight());
                        if (offset < 0) {//如果大於0的話_华硕f83s,此時並沒有切換
                            return offset;
                        } else {
                            break;
                        }
                    }
                }
            }
            //top不能小於0-__金贵村,否則最上麵的ItemDecoration不會一直存在
            top = Math.max(0, top);
        }
        return top;
    }
這裏的邏輯是這樣的_--食品生产经营人员多久必须进行健康检查:

 

1.當此view不是最上麵的顯示的時候|佐助vs团藏是哪一集,header距離頂部直接就是此view距離頂部距離減去header的高度即可
2.當此view是最上麵的view的時候_|_众赢彩票开户,首先用for循環找到它下一個和它headerId不同的第一個view|-159彩票网中奖不给钱,利用找到的這個view和它本身來計算出它的header距離頂部的距離_||内地主持人排行榜,當這個距離大於0時__24en,代表此view的header還全部顯示出來_|监察特使,這時直接用上麵的方式獲取這個距離_|_凹凸 绕梁三日,當這個距離小於0時就是我們所希望的||-永旺28彩票。


OK完成--2019管家婆彩图第66期,下麵貼出ItemDecoration的所以代碼

 

/**
 * Created by lzy on 2016/11/23.
 */
public class StickyItemDecoration extends RecyclerView.ItemDecoration {
    private static final String TAG = "lzy";
    private MedicineAdapter mAdapter;

    public StickyItemDecoration(MedicineAdapter mAdapter) {
        super();
        this.mAdapter = mAdapter;
    }

    //最後調用 繪製頂部固定的header
    @Override
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
        final int count = parent.getChildCount();

        for (int layoutPos = 0; layoutPos < count; layoutPos++) {
            final View child = parent.getChildAt(layoutPos);

            final int adapterPos = parent.getChildAdapterPosition(child);
            //隻有在最上麵一個item或者有header的item才繪製ItemDecoration
            if (adapterPos != RecyclerView.NO_POSITION && (layoutPos == 0 || hasHeader(adapterPos))) {
                View header = getHeader(parent, adapterPos).itemView;
                c.save();
                final int left = child.getLeft();
                final int top = getHeaderTop(parent, child, header, adapterPos, layoutPos);
                c.translate(left, top);
                header.setTranslationX(left);
                header.setTranslationY(top);
                header.draw(c);
                c.restore();
            }
        }
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
        //得到該item所在的位置
        int position = parent.getChildAdapterPosition(view);

        int headerHeight = 0;
        //在使用adapterPosition時最好的加上這個判斷
        if (position != RecyclerView.NO_POSITION && hasHeader(position)) {
            //獲取到ItemDecoration所需要的高度
            View header = getHeader(parent, position).itemView;
            headerHeight = header.getHeight();
        }
        outRect.set(0, headerHeight, 0, 0);
    }

    /**
     * 判斷是否有header
     *
     * @param position
     * @return
     */
    private boolean hasHeader(int position) {
        if (position == 0) {//第一個位置必然有
            return true;
        }
        //判斷和上一個的id不同則有header
        int previous = position - 1;
        return !mAdapter.getHeaderId(position).equals(mAdapter.getHeaderId(previous));
    }

    /**
     * 獲得自定義的Header
     *
     * @param parent
     * @param position
     * @return
     */
    private RecyclerView.ViewHolder getHeader(RecyclerView parent, int position) {
        //創建HeaderViewHolder
        MedicineAdapter.HeaderHolder holder = mAdapter.onCreateHeaderViewHolder(parent);
        final View header = holder.itemView;
        //綁定數據
        mAdapter.onBindHeaderViewHolder(holder, position);
        //測量View並且layout
        int widthSpec = View.MeasureSpec.makeMeasureSpec(parent.getWidth(), View.MeasureSpec.EXACTLY);
        int heightSpec = View.MeasureSpec.makeMeasureSpec(parent.getHeight(), View.MeasureSpec.UNSPECIFIED);
        //根據父View的MeasureSpec和子view自身的LayoutParams以及padding來獲取子View的MeasureSpec
        int childWidth = ViewGroup.getChildMeasureSpec(widthSpec,
                parent.getPaddingLeft() + parent.getPaddingRight(), header.getLayoutParams().width);
        int childHeight = ViewGroup.getChildMeasureSpec(heightSpec,
                parent.getPaddingTop() + parent.getPaddingBottom(), header.getLayoutParams().height);
        //進行測量
        header.measure(childWidth, childHeight);
        //根據測量後的寬高放置位置
        header.layout(0, 0, header.getMeasuredWidth(), header.getMeasuredHeight());
        return holder;
    }

    /**
     * 計算距離頂部的高度
     *
     * @param parent
     * @param child
     * @param header
     * @param adapterPos
     * @param layoutPos
     * @return
     */
    private int getHeaderTop(RecyclerView parent, View child, View header, int adapterPos, int layoutPos) {
        int headerHeight = header.getHeight();
       int top = ((int) child.getY()) - headerHeight;
        if (layoutPos == 0) {//處理最上麵兩個ItemDecoration切換時
            final int count = parent.getChildCount();
            final String currentId = mAdapter.getHeaderId(adapterPos);
            for (int i = 1; i < count; i++) {
                int adapterPosHere = parent.getChildAdapterPosition(parent.getChildAt(i));
                if (adapterPosHere != RecyclerView.NO_POSITION) {
                    String nextId = mAdapter.getHeaderId(adapterPosHere);
                    //找到下一個不同類的view
                    if (!nextId.equals(currentId)) {
                        final View next = parent.getChildAt(i);
                        //這裏計算offset畫個圖會很清楚
                        final int offset = ((int) next.getY()) - (headerHeight + getHeader(parent, adapterPosHere).itemView.getHeight());
                        if (offset < 0) {//如果大於0的話||-三星铃声下载,此時並沒有切換
                            return offset;
                        } else {
                            break;
                        }
                    }
                }
            }
            //top不能小於0-_冰心原名是什么,否則最上麵的ItemDecoration不會一直存在
            top = Math.max(0, top);
        }
        return top;
    }
}

漢字轉拚音

通過一個三方的類庫pinyin4j來實現-_|北京军事政变,這裏就是調用方法PinyinHelper.toHanyuPinyinStringArray獲取一個漢字的拚音|_尉氏户外,然後得到第一個英文字母並轉化為大寫

 

 private List<MedicineBean> filledData(String[] data) {
        List<MedicineBean> mSortList = new ArrayList<MedicineBean>();

        for (int i = 0; i < data.length; i++) {
            MedicineBean medicineBean = new MedicineBean();
            medicineBean.setName(data[i]);
            //漢字轉換成拚音
            String[] pinyin = PinyinHelper.toHanyuPinyinStringArray(data[i].toCharArray()[0]);
            String sortString = pinyin[0].substring(0, 1).toUpperCase();
            // 正則表達式-_麦梓俊,判斷首字母是否是英文字母
            if (sortString.matches("[A-Z]")) {
                medicineBean.setLetter(sortString.toUpperCase());
            } else {
                medicineBean.setLetter("#");
            }

            mSortList.add(medicineBean);
        }
        return mSortList;

    }


右邊的字母導航欄

 

public class SideBar extends View {
    // 觸摸事件
    private OnTouchingLetterChangedListener onTouchingLetterChangedListener;
    // 26個字母
    public static String[] b = {"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", "#"};
    private int choose = -1;// 選中
    private Paint paint = new Paint();

    private TextView mTextDialog;

    public void setTextView(TextView mTextDialog) {
        this.mTextDialog = mTextDialog;
    }

    public SideBar(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public SideBar(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public SideBar(Context context) {
        super(context);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 獲取焦點改變背景顏色.
        int height = getHeight();// 獲取對應高度
        int width = getWidth(); // 獲取對應寬度
        int singleHeight = height / b.length;// 獲取每一個字母的高度

        for (int i = 0; i < b.length; i++) {
            paint.setColor(Color.rgb(33, 65, 98));
            // paint.setColor(Color.WHITE);
            paint.setTypeface(Typeface.DEFAULT_BOLD);
            paint.setAntiAlias(true);
            paint.setTextSize(20);
            // 選中的狀態
            if (i == choose) {
                paint.setColor(Color.parseColor("#3399ff"));
                paint.setFakeBoldText(true);
            }
            // x坐標等於中間-字符串寬度的一半.
            float xPos = width / 2 - paint.measureText(b[i]) / 2;
            float yPos = singleHeight * i + singleHeight;
            canvas.drawText(b[i], xPos, yPos, paint);
            paint.reset();// 重置畫筆
        }

    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        final int action = event.getAction();
        final float y = event.getY();// 點擊y坐標
        final int oldChoose = choose;
        final OnTouchingLetterChangedListener listener = onTouchingLetterChangedListener;
        final int c = (int) (y / getHeight() * b.length);// 點擊y坐標所占總高度的比例*b數組的長度就等於點擊b中的個數.

        switch (action) {
            case MotionEvent.ACTION_UP:
                setBackgroundDrawable(new ColorDrawable(0x00000000));
                choose = -1;//
                invalidate();
                if (mTextDialog != null) {
                    mTextDialog.setVisibility(View.INVISIBLE);
                }
                break;
            default:
                setBackgroundColor(Color.parseColor("#808080"));
                if (oldChoose != c) {
                    if (c >= 0 && c < b.length) {
                        if (listener != null) {
                            listener.onTouchingLetterChanged(b[c]);
                        }
                        if (mTextDialog != null) {
                            mTextDialog.setText(b[c]);
                            mTextDialog.setVisibility(View.VISIBLE);
                        }
                        choose = c;
                        invalidate();
                    }
                }

                break;
        }
        return true;
    }

    /**
     * 向外公開的方法
     *
     * @param onTouchingLetterChangedListener
     */
    public void setOnTouchingLetterChangedListener(
            OnTouchingLetterChangedListener onTouchingLetterChangedListener) {
        this.onTouchingLetterChangedListener = onTouchingLetterChangedListener;
    }

    /**
     * 接口
     *
     * @author coder
     */
    public interface OnTouchingLetterChangedListener {
        void onTouchingLetterChanged(String s);
    }

}
這是在網上找的一個類_-黄河电视台在线直播,相信大家都能看懂_132网彩下载,就不多說了|-宏泰集团,最後貼出MainActivity

 

 

public class MainActivity extends AppCompatActivity {
    private String[] mData = {"阿魏八味丸", "阿昔洛韋眼膏", "艾司洛爾", "安吖啶注射液", "阿達帕林", "參茸追風酒", "草烏", "石斛夜光丸",
            "骨質增生片", "烏雞白鳳丸", "人參益母丸", "補脾益腸丸", "丹參片", "小金丸", "婦寧康", "糖脈康", "菲伯瑞", "乙肝解毒片", "腦血栓片"};
    private static final String TAG = "lzy";
    private RecyclerView mRecyclerView;
    private SideBar sideBar;
    private StickyItemDecoration mDecoration;
    private PinyinComparator pinyinComparator;
    private MedicineAdapter medicineAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mRecyclerView = (RecyclerView) findViewById(R.id.rv);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));

        //按照字母排序
        pinyinComparator = new PinyinComparator();

        List<MedicineBean> data = filledData(mData);
        Collections.sort(data, pinyinComparator);

        medicineAdapter = new MedicineAdapter(this, data);
        mRecyclerView.setAdapter(medicineAdapter);
        mDecoration = new StickyItemDecoration(medicineAdapter);
        mRecyclerView.addItemDecoration(mDecoration);
        //添加分割線
        mRecyclerView.addItemDecoration(new DividerItemDecoration(MainActivity.this, DividerItemDecoration.VERTICAL_LIST));

        sideBar = (SideBar) findViewById(R.id.sideBar);
        sideBar.setTextView((TextView) findViewById(R.id.dialog));
        //設置右側觸摸監聽
        sideBar.setOnTouchingLetterChangedListener(new SideBar.OnTouchingLetterChangedListener() {

            @Override
            public void onTouchingLetterChanged(String s) {
                //該字母首次出現的位置
                int position = medicineAdapter.getPositionForSection(s);
                if (position != -1) {
                    mRecyclerView.scrollToPosition(position);
                }

            }
        });

    }

    /**
     * 填充數據
     *
     * @param data
     * @return
     */
    private List<MedicineBean> filledData(String[] data) {
        List<MedicineBean> mSortList = new ArrayList<MedicineBean>();

        for (int i = 0; i < data.length; i++) {
            MedicineBean medicineBean = new MedicineBean();
            medicineBean.setName(data[i]);
            //漢字轉換成拚音
            String[] pinyin = PinyinHelper.toHanyuPinyinStringArray(data[i].toCharArray()[0]);
            String sortString = pinyin[0].substring(0, 1).toUpperCase();
            // 正則表達式|_邮政局上班时间,判斷首字母是否是英文字母
            if (sortString.matches("[A-Z]")) {
                medicineBean.setLetter(sortString.toUpperCase());
            } else {
                medicineBean.setLetter("#");
            }

            mSortList.add(medicineBean);
        }
        return mSortList;

    }
}

最後貼出源碼的下載地址___温网2017男单决赛:http://download.csdn.net/detail/lylodyf/9695270

延伸閱讀|-135彩票平台可靠吗:

Tag標簽_--镶黄旗姓氏: 字母  
  • 專題推薦

  • Directx11 遊戲編程入門教程
  • 專題主要學習DirectX的初級編程入門學習|_奥鹏教育学生请进,對Directx11的入門及初學者有...... 詳細
  • Windows7係統入門 優化 技巧技術專題
  • Windows7係統專題 無論是升級操作係統___武松卡盟平台登录、資料備份||霍林郭勒天气、加強資料的安全及管...... 詳細
About IT165 - 廣告服務 - 隱私聲明 - 版權申明 - 免責條款 - 網站地圖 - 網友投稿 - 聯係方式
本站內容來自於互聯網,僅供用於網絡技術學習,學習中請遵循相關法律法規
qq分分彩秒速牛牛盛兴彩票财神彩票快乐飞艇亿客隆彩票

免责声明: 本站资料及图片来源互联网文章,本网不承担任何由内容信息所引起的争议和法律责任。所有作品版权归原创作者所有,与本站立场无关,如用户分享不慎侵犯了您的权益,请联系我们告知,我们将做删除处理!