快速索引

来源:互联网 发布:淘宝悬浮框生成器 编辑:程序博客网 时间:2024/06/14 20:06

自定义控件的绘制:

package com.it.quickindex.ui;import com.it.quickindex.util.Cheeses;import com.it.quickindex.util.Utils;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Rect;import android.graphics.Typeface;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;/** * 快速索引条 * @author poplar * */public class QuickIndexBar extends View {    public static final String[] LETTERS = 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"};    private Paint paint;    private float cellHeight; // 单元格高度    private int cellWidth; // 单元格宽度    private OnLetterChangeListener mOnLetterChangeListener;    /**     * 字母更新监听     * @author poplar     *     */    public interface OnLetterChangeListener{        void onLetterChange(String letter);    }    /**     * 设置监听器     * @param mOnLetterChangeListener     */    public void setOnLetterChangeListener(OnLetterChangeListener mOnLetterChangeListener){        this.mOnLetterChangeListener = mOnLetterChangeListener;    }    /**     * 构造方法     * @param context     */    public QuickIndexBar(Context context) {        this(context, null);    }    public QuickIndexBar(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public QuickIndexBar(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);        //抗锯齿        paint = new Paint(Paint.ANTI_ALIAS_FLAG);        paint.setColor(Color.WHITE);        paint.setTextSize(25);        //加粗        paint.setTypeface(Typeface.DEFAULT_BOLD);    }    /**     * 绘制索引字母表     */    @Override    protected void onDraw(Canvas canvas) {        // 把所有字母画到画板上        for (int i = 0; i < LETTERS.length; i++) {            String letter = LETTERS[i];            // 计算水平坐标(字母控件左侧坐标)            int x = (int) (cellWidth * 0.5f - paint.measureText(letter) * 0.5f);            // 计算垂直坐标(左下角为textView的坐标)            // 将一个文本的指定区域放置到 bounds的矩形对象中,并将值封装给bound            Rect bounds = new Rect();            paint.getTextBounds(letter, 0, letter.length(), bounds);            int y = (int) (cellHeight * 0.5f + bounds.height() * 0.5f + cellHeight * i);            // 设置画笔颜色, 如果是被触摸的, 设置灰色            paint.setColor(i == currentIndex ? Color.GRAY : Color.WHITE);            // 绘制文本            canvas.drawText(letter, x, y, paint);        }    }    int currentIndex = -1;    @Override    public boolean onTouchEvent(MotionEvent event) {        int index;        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                // 根据当前的y值, 计算得到字母的索引                index = (int) (event.getY() / cellHeight);                if(index != currentIndex){                    // 如果发生了变化, 才走到这里边                    if(index >= 0 && index < LETTERS.length){                        // 获取到手指按下的字母                        System.out.println(LETTERS[index]);                        if(mOnLetterChangeListener != null){                            mOnLetterChangeListener.onLetterChange(LETTERS[index]);                        }                    }                    currentIndex = index;                }                break;            case MotionEvent.ACTION_MOVE:                index = (int) (event.getY() / cellHeight);                if(index != currentIndex) {                    // 如果发生了变化, 才走到这里边                    if(index >= 0 && index < LETTERS.length){                        // 获取到手指按下的字母                        System.out.println(LETTERS[index]);                        if(mOnLetterChangeListener != null){                            mOnLetterChangeListener.onLetterChange(LETTERS[index]);                        }                    }                    currentIndex = index;                }                break;            case MotionEvent.ACTION_UP:                currentIndex = -1;                break;            default:                break;        }        // 重绘界面        invalidate();        // 由本控件消费事件        return true;    }    /**     * 测量控件的尺寸     */    @Override    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(w, h, oldw, oldh);        cellWidth = getMeasuredWidth();        int mHeight = getMeasuredHeight();        cellHeight = mHeight * 1.0f / LETTERS.length;    }}

主页布局文件:

<RelativeLayout 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"    tools:context=".MainActivity" >    <ListView        android:id="@+id/lv_haohan"        android:layout_width="match_parent"        android:layout_height="match_parent" >    </ListView>    <com.itheima57.quickindex.ui.QuickIndexBar        android:id="@+id/quickIndexBar"        android:layout_width="30dp"        android:layout_height="match_parent"        android:layout_alignParentRight="true"        android:background="#FF0000" />    <TextView        android:id="@+id/tv_center"        android:visibility="gone"        android:layout_width="140dp"        android:layout_height="80dp"        android:layout_centerInParent="true"        android:background="@drawable/shape_bg_index"        android:gravity="center"        android:text="A"        android:textColor="#FFFFFF"        android:textSize="28sp" /></RelativeLayout>

MainActivity:

package com.it.quickindex;import java.util.ArrayList;import java.util.Collections;import java.util.List;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.text.TextUtils;import android.view.View;import android.view.Window;import android.widget.ListView;import android.widget.TextView;import com.itheima57.quickindex.adapter.HaoHanAdapter;import com.itheima57.quickindex.domain.HaoHan;import com.itheima57.quickindex.ui.QuickIndexBar;import com.itheima57.quickindex.ui.QuickIndexBar.OnLetterChangeListener;import com.itheima57.quickindex.util.Cheeses;public class MainActivity extends Activity {    private TextView tv_center;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        requestWindowFeature(Window.FEATURE_NO_TITLE);        setContentView(R.layout.activity_main);        //获取索引弹窗控件        tv_center = (TextView) findViewById(R.id.tv_center);        //获取联系人列表ListView控件        final ListView lv_haohan = (ListView) findViewById(R.id.lv_haohan);        final List<HaoHan> persons = new ArrayList<HaoHan>();        // 填充并排序        fillAndSortData(persons);        lv_haohan.setAdapter(new HaoHanAdapter(this, persons));        QuickIndexBar quickIndexBar = (QuickIndexBar) findViewById(R.id.quickIndexBar);        // 给自定义索引设置监听(选择右侧索引,左侧listView跳转到相应的位置)        quickIndexBar.setOnLetterChangeListener(new OnLetterChangeListener() {            @Override            public void onLetterChange(String letter) {//              Utils.showToast(getApplicationContext(), "letter: " + letter);                showCenterLetter(letter);                // 将ListView调到 , 首次出现 letter 的条目                for (int i = 0; i < persons.size(); i++) {                    String l = persons.get(i).getPinyin().charAt(0) + "";                    if(TextUtils.equals(l, letter)){                        // 找到了, 跳转到指定位置                        lv_haohan.setSelection(i);                        break;                    }                }            }        });    }    private Handler mHandler = new Handler();    protected void showCenterLetter(String letter) {        tv_center.setText(letter);        tv_center.setVisibility(View.VISIBLE);        // 移除刚刚所有发出的消息(防止之前的消息还没显示结束再显示新消息出现闪屏)        mHandler.removeCallbacksAndMessages(null);        mHandler.postDelayed(new Runnable() {            @Override            public void run() {                tv_center.setVisibility(View.GONE);            }        }, 1500);    }    /**     * 将数据封装进集合并且排序     * @param persons     */    private void fillAndSortData(List<HaoHan> persons) {        HaoHan haoHan;        for (int i = 0; i < Cheeses.NAMES.length; i++) {            String name = Cheeses.NAMES[i];            haoHan = new HaoHan(name);            persons.add(haoHan);        }        // 排序        Collections.sort(persons);    }}

haohanAdapter:
实现相同索引字母的时候只显示一个标题头。

package com.itheima57.quickindex.adapter;import java.util.List;import android.content.Context;import android.text.TextUtils;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.TextView;import com.itheima57.quickindex.R;import com.itheima57.quickindex.domain.HaoHan;public class HaoHanAdapter extends BaseAdapter {    private final List<HaoHan> persons;    private final Context context;    public HaoHanAdapter(Context context, List<HaoHan> persons) {        this.context = context;        this.persons = persons;    }    @Override    public int getCount() {        return persons.size();    }    @Override    public Object getItem(int position) {        return null;    }    @Override    public long getItemId(int position) {        return 0;    }    @Override    public View getView(int position, View convertView, ViewGroup parent) {        View view;        if(convertView == null){            view = View.inflate(context, R.layout.item_list_haohan, null);        }else {            view = convertView;        }        // 索引字母        TextView tv_index = (TextView) view.findViewById(R.id.tv_index);        // 名称        TextView tv_name = (TextView) view.findViewById(R.id.tv_name);        HaoHan haoHan = persons.get(position);        String currentLetter = haoHan.getPinyin().charAt(0) + "";        // 分组, 只显示首次出现新的字母的条目索引        String indexStr = null;        if(position == 0){            // 当前是第一个条目, 直接显示            indexStr = currentLetter;        }else {            // 不是第一个条目, 跟前一个比较            // 前一个拼音首字母            String previousLetter = persons.get(position - 1).getPinyin().charAt(0) + "";            if(!TextUtils.equals(previousLetter, currentLetter)){                // 不相同时, 显示当前的索引栏                indexStr = currentLetter;            }        }        tv_index.setVisibility(indexStr == null ? View.GONE : View.VISIBLE);        tv_index.setText(currentLetter);        tv_name.setText(haoHan.getName());        return view;    }}
0 0