52.android 简单的自定义View通讯录检索效果

导读:本篇文章讲解 52.android 简单的自定义View通讯录检索效果,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

//我写了两种方式,效果都差不多,不过第一个是通过网络接口串实现的,它里面有这个值,能知道当前的数据的拼音的第一个字母。第二个是我自己写的自定义数据,通过转成拼音,再通过截取拼音第一个字母,获取。

//第一个 没上传动图 凑合看一下,这个都是网络请求的数据:

52.android 简单的自定义View通讯录检索效果

 

//好了 第一步 先建立一个BaseView类继承View,自己来写自定义View

public class BaseView extends View {
    /*绘制的列表导航字母*/
    private String words[] = {"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 wordsPaint=new Paint();
    /*字母背景画笔*/
    private Paint bgPaint;
    /*每一个字母的宽度*/
    private int itemWidth;
    /*每一个字母的高度*/
    private int itemHeight;
    /*手指按下的字母索引*/
    private int touchIndex = 0;
    /*手指按下的字母改变接口*/
    private onWordsChangeListener listener;
    /*设置手指按下字母改变监听*/

    public void setOnWordsChangeListener(onWordsChangeListener listener) {
        this.listener = listener;
    }

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

    public BaseView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public BaseView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        itemWidth = getMeasuredWidth();
        //使得边距好看一些
        int height = getMeasuredHeight() - 10;
        itemHeight = height / 27;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        wordsPaint.setTextSize(40);
        for (int i = 0; i < words.length; i++) {
            //判断是不是我们按下的当前字母
            if (touchIndex == i) {
                //绘制文字圆形背景
//                canvas.drawCircle(itemWidth / 2, itemHeight / 2 + i * itemHeight, 23, bgPaint);
                wordsPaint.setColor(Color.RED);
            } else {
                wordsPaint.setColor(Color.BLACK);
            }
            //获取文字的宽高
            Rect rect = new Rect();
            wordsPaint.getTextBounds(words[i], 0, 1, rect);
            int wordWidth = rect.width();
            //绘制字母
            float wordX = itemWidth / 2 - wordWidth / 2;
            float wordY = itemWidth / 2 + i * itemHeight;
            canvas.drawText(words[i], wordX, wordY, wordsPaint);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_MOVE:
                float y = event.getY();
                //关键点===获得我们按下的是那个索引(字母)
                int index = (int) (y / itemHeight);
                if (index != touchIndex)
                    touchIndex = index;
                //防止数组越界
                if (listener != null && 0 <= touchIndex && touchIndex <= words.length - 1) {
                    //回调按下的字母
                    listener.wordsChange(words[touchIndex]);
                }
                //刷新
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                //手指抬起,不做任何操作
                break;
        }
        return true;
    }
    /*手指按下了哪个字母的回调接口*/
    public interface onWordsChangeListener {
        void wordsChange(String words);
    }
    /*设置当前按下的是那个字母*/
    public void setTouchIndex(String word) {
        for (int i = 0; i < words.length; i++) {
            if (words[i].equals(word)) {
                touchIndex = i;
                invalidate();
                return;
            }
        }
    }
}

//第二步 写布局

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.hasee.a817ceshi.MainActivity">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ListView
            android:layout_toLeftOf="@+id/mView"
            android:id="@+id/mDingWeiRe"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
        </ListView>

        <com.example.hasee.a817ceshi.BaseView
            android:layout_alignParentRight="true"
            android:id="@+id/mView"
            android:layout_width="40dp"
            android:layout_height="match_parent"
            />

        <TextView
            android:visibility="gone"
            android:id="@+id/mDingWeiXianShi"
            android:textSize="60sp"
            android:background="@color/colorAccent"
            android:gravity="center"
            android:layout_centerInParent="true"
            android:layout_width="100dp"
            android:layout_height="100dp" />
    </RelativeLayout>

   

</RelativeLayout>

// 第三步  Activity里开始具体使用,请求数据,适配,关联

//okhttp和gson解析的依赖

//implementation 'com.google.code.gson:gson:2.8.1'
//implementation 'com.squareup.okhttp3:okhttp:3.8.1'
public class MainActivity extends AppCompatActivity implements BaseView.onWordsChangeListener {

    private ArrayList<DingWeiBean.ResultListBean.ListBean> arrayList;
    private ListView mDingWeiRe;
    private BaseView mView;
    private TextView mDingWeiXianShi;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initDatas();
    }


    private void initView() {
        mDingWeiRe = (ListView) findViewById(R.id.mDingWeiRe);
        mView = (BaseView) findViewById(R.id.mView);
        mDingWeiXianShi = (TextView) findViewById(R.id.mDingWeiXianShi);

//通过这个监听listView和自定义View互相关联上
        mView.setOnWordsChangeListener(this);

    }

    //网络请求数据 
    private void initDatas() {
        //get 异步
        //private String url = "http://v.juhe.cn/toutiao/index?type=top&key=097060266650f67b2cebd2a06aded587";
        OkHttpClient client = new OkHttpClient.Builder().build();
        Request request = new Request.Builder().url("https://api.dyhoa.com/dapi/v4/city/android").method("GET", null).build();
        Call call = client.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                //请求失败
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                //请求成功
                arrayList = new ArrayList<>();
                String string = response.body().string();
                Gson gson = new Gson();
                DingWeiBean dingWeiBean = gson.fromJson(string, DingWeiBean.class);
                List<DingWeiBean.ResultListBean.ListBean> list = dingWeiBean.getResultList().getList();
                for (int i = 0; i < list.size(); i++) {
                    DingWeiBean.ResultListBean.ListBean listBean = list.get(i);
                    arrayList.add(listBean);
                    Log.e("TAG1", arrayList.size() + "");
                }
                Log.e("TAG2", arrayList.size() + "");
                
                //listView适配数据
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Log.e("TAG3", arrayList.size() + "");
                        mDingWeiRe.setAdapter(new MyAdapter(arrayList, MainActivity.this));
                        mDingWeiRe.setOnScrollListener(new AbsListView.OnScrollListener() {
                            @Override
                            public void onScrollStateChanged(AbsListView view, int scrollState) {

                            }

                            @Override
                            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
                                //当滑动列表的时候,更新右侧字母列表的选中状态
                                mView.setTouchIndex(arrayList.get(firstVisibleItem).getFirst_letter());
                            }
                        });
                    }
                });
            }
        });
    }


    @Override
    public void wordsChange(String words) {
        updateWord(words);
        updateListView(words);
    }

    Handler handler = new Handler();

    private void updateWord(String words) {
        mDingWeiXianShi.setText(words);
        mDingWeiXianShi.setVisibility(View.VISIBLE);
        //清空之前的所有消息
        handler.removeCallbacksAndMessages(null);
        //500ms后让tv隐藏
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                mDingWeiXianShi.setVisibility(View.GONE);
            }
        }, 500);
    }

    private void updateListView(String words) {
        for (int i = 0; i < arrayList.size(); i++) {
            String headerWord = arrayList.get(i).getFirst_letter();
            //将手指按下的字母与列表中相同字母开头的项找出来
            if (words.equals(headerWord)) {
                //将列表选中哪一个
                mDingWeiRe.setSelection(i);
                //找到开头的一个即可
                return;
            }
        }
    }

}

//第四步 ListView适配器 适配数据:

public class MyAdapter extends BaseAdapter {
    private ArrayList<DingWeiBean.ResultListBean.ListBean> list;
    private Context context;

    public MyAdapter(ArrayList<DingWeiBean.ResultListBean.ListBean> list, Context context) {
        this.list = list;
        this.context = context;
    }

    @Override
    public int getCount() {
        return list.size();
    }

    @Override
    public Object getItem(int position) {
        return list.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) {
            holder = new ViewHolder();
            convertView = LayoutInflater.from(context).inflate(R.layout.dingweilayout, null);
            holder.mDingWeiText1 = (TextView) convertView.findViewById(R.id.mDingWeiText1);
            holder.mDingWeiText2 = (TextView) convertView.findViewById(R.id.mDingWeiText2);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        String first_letter = list.get(position).getFirst_letter();
        holder.mDingWeiText1.setText(first_letter);
        holder.mDingWeiText2.setText(list.get(position).getCity_name());
        //将相同字母开头的合并在一起
        if (position == 0) {
            //第一个是一定显示的
            holder.mDingWeiText1.setVisibility(View.VISIBLE);
        } else {
            //后一个与前一个对比,判断首字母是否相同,相同则隐藏
            String first_letter1 = list.get(position - 1).getFirst_letter();
            if (first_letter.equals(first_letter1)) {
                holder.mDingWeiText1.setVisibility(View.GONE);
            } else {
                holder.mDingWeiText1.setVisibility(View.VISIBLE);
            }
        }
        return convertView;
    }

    private class ViewHolder {
        private TextView mDingWeiText1;
        private TextView mDingWeiText2;
    }
}

// 第五步 还有这个Bean类

public class DingWeiBean {

    /**
     * result :
     * total : 2
     * code : 200
     * message : ok
     * resultList : {"hot":[{"city_name":"北京市","province_id":110000,"first_letter":"B","is_hot":1,"latitude":"39.90469","base_results":0,"id":1,"displayorder":0,"city_id":110000,"status":1,"longitude":"116.40717"},{"city_name":"石家庄市","province_id":130000,"first_letter":"S","is_hot":1,"latitude":"38.04223","base_results":3000,"id":5,"displayorder":0,"city_id":130100,"status":1,"longitude":"114.51479"},{"city_name":"廊坊市","province_id":130000,"first_letter":"L","is_hot":1,"latitude":"39.52393","base_results":2900,"id":14,"displayorder":100,"city_id":131000,"status":1,"longitude":"116.70444"},{"city_name":"呼和浩特市","province_id":150000,"first_letter":"H","is_hot":1,"latitude":"40.842723","base_results":0,"id":27,"displayorder":0,"city_id":150100,"status":1,"longitude":"111.748426"},{"city_name":"南京市","province_id":320000,"first_letter":"N","is_hot":1,"latitude":"32.05935","base_results":0,"id":77,"displayorder":0,"city_id":320100,"status":1,"longitude":"118.79662"},{"city_name":"武汉市","province_id":420000,"first_letter":"W","is_hot":1,"latitude":"31.01269","base_results":2500,"id":172,"displayorder":0,"city_id":420100,"status":1,"longitude":"114.33996"},{"city_name":"昆明市","province_id":530000,"first_letter":"K","is_hot":1,"latitude":"24.87966","base_results":0,"id":271,"displayorder":0,"city_id":530100,"status":1,"longitude":"102.83322"},{"city_name":"西安市","province_id":610000,"first_letter":"X","is_hot":1,"latitude":"34.34749","base_results":0,"id":294,"displayorder":0,"city_id":610100,"status":1,"longitude":"108.94627"}],"list":[{"city_name":"北京市","province_id":110000,"first_letter":"B","is_hot":1,"latitude":"39.90469","base_results":0,"id":1,"displayorder":0,"city_id":110000,"status":1,"longitude":"116.40717"},{"city_name":"宝鸡市","province_id":610000,"first_letter":"B","is_hot":0,"latitude":"0.000000","base_results":0,"id":296,"displayorder":0,"city_id":610300,"status":1,"longitude":"0.000000"},{"city_name":"保定市","province_id":130000,"first_letter":"B","is_hot":0,"latitude":"38.86766","base_results":0,"id":10,"displayorder":0,"city_id":130600,"status":1,"longitude":"115.48233"},{"city_name":"沧州市","province_id":130000,"first_letter":"C","is_hot":0,"latitude":"38.31058","base_results":0,"id":13,"displayorder":0,"city_id":130900,"status":1,"longitude":"116.85746"},{"city_name":"邯郸市","province_id":130000,"first_letter":"H","is_hot":0,"latitude":"36.61227","base_results":0,"id":8,"displayorder":0,"city_id":130400,"status":1,"longitude":"114.49068"},{"city_name":"呼和浩特市","province_id":150000,"first_letter":"H","is_hot":1,"latitude":"40.842723","base_results":0,"id":27,"displayorder":0,"city_id":150100,"status":1,"longitude":"111.748426"},{"city_name":"衡水市","province_id":130000,"first_letter":"H","is_hot":0,"latitude":"37.7351","base_results":0,"id":15,"displayorder":0,"city_id":131100,"status":1,"longitude":"115.66599"},{"city_name":"济南市","province_id":370000,"first_letter":"J","is_hot":0,"latitude":"36.6512","base_results":0,"id":138,"displayorder":0,"city_id":370100,"status":1,"longitude":"117.1201"},{"city_name":"晋中市","province_id":140000,"first_letter":"J","is_hot":0,"latitude":"37.696495","base_results":0,"id":22,"displayorder":0,"city_id":140700,"status":1,"longitude":"112.736465"},{"city_name":"昆明市","province_id":530000,"first_letter":"K","is_hot":1,"latitude":"24.87966","base_results":0,"id":271,"displayorder":0,"city_id":530100,"status":1,"longitude":"102.83322"},{"city_name":"廊坊市","province_id":130000,"first_letter":"L","is_hot":1,"latitude":"39.52393","base_results":2900,"id":14,"displayorder":100,"city_id":131000,"status":1,"longitude":"116.70444"},{"city_name":"南京市","province_id":320000,"first_letter":"N","is_hot":1,"latitude":"32.05935","base_results":0,"id":77,"displayorder":0,"city_id":320100,"status":1,"longitude":"118.79662"},{"city_name":"秦皇岛市","province_id":130000,"first_letter":"Q","is_hot":0,"latitude":"39.942531","base_results":0,"id":7,"displayorder":0,"city_id":130300,"status":1,"longitude":"119.586579"},{"city_name":"石家庄市","province_id":130000,"first_letter":"S","is_hot":1,"latitude":"38.04223","base_results":3000,"id":5,"displayorder":0,"city_id":130100,"status":1,"longitude":"114.51479"},{"city_name":"上饶市","province_id":360000,"first_letter":"S","is_hot":0,"latitude":"28.44442","base_results":0,"id":137,"displayorder":0,"city_id":361100,"status":1,"longitude":"117.971185"},{"city_name":"太原市","province_id":140000,"first_letter":"T","is_hot":0,"latitude":"37.87046","base_results":0,"id":16,"displayorder":0,"city_id":140100,"status":1,"longitude":"112.549717"},{"city_name":"唐山市","province_id":130000,"first_letter":"T","is_hot":0,"latitude":"39.635113","base_results":0,"id":6,"displayorder":0,"city_id":130200,"status":1,"longitude":"118.175393"},{"city_name":"武汉市","province_id":420000,"first_letter":"W","is_hot":1,"latitude":"31.01269","base_results":2500,"id":172,"displayorder":0,"city_id":420100,"status":1,"longitude":"114.33996"},{"city_name":"武威市","province_id":620000,"first_letter":"w","is_hot":0,"latitude":"37.929996","base_results":0,"id":309,"displayorder":0,"city_id":620600,"status":1,"longitude":"102.634697"},{"city_name":"邢台市","province_id":130000,"first_letter":"X","is_hot":0,"latitude":"37.0682","base_results":0,"id":9,"displayorder":0,"city_id":130500,"status":1,"longitude":"114.50885"},{"city_name":"西安市","province_id":610000,"first_letter":"X","is_hot":1,"latitude":"34.34749","base_results":0,"id":294,"displayorder":0,"city_id":610100,"status":1,"longitude":"108.94627"}]}
     */

    private String result;
    private int total;
    private int code;
    private String message;
    private ResultListBean resultList;

    public String getResult() {
        return result;
    }

    public void setResult(String result) {
        this.result = result;
    }

    public int getTotal() {
        return total;
    }

    public void setTotal(int total) {
        this.total = total;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public ResultListBean getResultList() {
        return resultList;
    }

    public void setResultList(ResultListBean resultList) {
        this.resultList = resultList;
    }

    public static class ResultListBean {
        private List<HotBean> hot;
        private List<ListBean> list;

        public List<HotBean> getHot() {
            return hot;
        }

        public void setHot(List<HotBean> hot) {
            this.hot = hot;
        }

        public List<ListBean> getList() {
            return list;
        }

        public void setList(List<ListBean> list) {
            this.list = list;
        }

        public static class HotBean {
            /**
             * city_name : 北京市
             * province_id : 110000
             * first_letter : B
             * is_hot : 1
             * latitude : 39.90469
             * base_results : 0.0
             * id : 1
             * displayorder : 0
             * city_id : 110000
             * status : 1
             * longitude : 116.40717
             */

            private String city_name;
            private int province_id;
            private String first_letter;
            private int is_hot;
            private String latitude;
            private double base_results;
            private int id;
            private int displayorder;
            private int city_id;
            private int status;
            private String longitude;

            public String getCity_name() {
                return city_name;
            }

            public void setCity_name(String city_name) {
                this.city_name = city_name;
            }

            public int getProvince_id() {
                return province_id;
            }

            public void setProvince_id(int province_id) {
                this.province_id = province_id;
            }

            public String getFirst_letter() {
                return first_letter;
            }

            public void setFirst_letter(String first_letter) {
                this.first_letter = first_letter;
            }

            public int getIs_hot() {
                return is_hot;
            }

            public void setIs_hot(int is_hot) {
                this.is_hot = is_hot;
            }

            public String getLatitude() {
                return latitude;
            }

            public void setLatitude(String latitude) {
                this.latitude = latitude;
            }

            public double getBase_results() {
                return base_results;
            }

            public void setBase_results(double base_results) {
                this.base_results = base_results;
            }

            public int getId() {
                return id;
            }

            public void setId(int id) {
                this.id = id;
            }

            public int getDisplayorder() {
                return displayorder;
            }

            public void setDisplayorder(int displayorder) {
                this.displayorder = displayorder;
            }

            public int getCity_id() {
                return city_id;
            }

            public void setCity_id(int city_id) {
                this.city_id = city_id;
            }

            public int getStatus() {
                return status;
            }

            public void setStatus(int status) {
                this.status = status;
            }

            public String getLongitude() {
                return longitude;
            }

            public void setLongitude(String longitude) {
                this.longitude = longitude;
            }
        }

        public static class ListBean {
            /**
             * city_name : 北京市
             * province_id : 110000
             * first_letter : B
             * is_hot : 1
             * latitude : 39.90469
             * base_results : 0.0
             * id : 1
             * displayorder : 0
             * city_id : 110000
             * status : 1
             * longitude : 116.40717
             */

            private String city_name;
            private int province_id;
            private String first_letter;
            private int is_hot;
            private String latitude;
            private double base_results;
            private int id;
            private int displayorder;
            private int city_id;
            private int status;
            private String longitude;

            public String getCity_name() {
                return city_name;
            }

            public void setCity_name(String city_name) {
                this.city_name = city_name;
            }

            public int getProvince_id() {
                return province_id;
            }

            public void setProvince_id(int province_id) {
                this.province_id = province_id;
            }

            public String getFirst_letter() {
                return first_letter;
            }

            public void setFirst_letter(String first_letter) {
                this.first_letter = first_letter;
            }

            public int getIs_hot() {
                return is_hot;
            }

            public void setIs_hot(int is_hot) {
                this.is_hot = is_hot;
            }

            public String getLatitude() {
                return latitude;
            }

            public void setLatitude(String latitude) {
                this.latitude = latitude;
            }

            public double getBase_results() {
                return base_results;
            }

            public void setBase_results(double base_results) {
                this.base_results = base_results;
            }

            public int getId() {
                return id;
            }

            public void setId(int id) {
                this.id = id;
            }

            public int getDisplayorder() {
                return displayorder;
            }

            public void setDisplayorder(int displayorder) {
                this.displayorder = displayorder;
            }

            public int getCity_id() {
                return city_id;
            }

            public void setCity_id(int city_id) {
                this.city_id = city_id;
            }

            public int getStatus() {
                return status;
            }

            public void setStatus(int status) {
                this.status = status;
            }

            public String getLongitude() {
                return longitude;
            }

            public void setLongitude(String longitude) {
                this.longitude = longitude;
            }
        }
    }
}

//———————————–第一种 完 —————————————–

 

 

//——————第二种  自定义的数据,不是网络请求的—————-

52.android 简单的自定义View通讯录检索效果

 

 

//第一步  还是一样 写个BaseView类继承View

public class BaseView extends View {
    /*绘制的列表导航字母*/
    private String words[] = {"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 wordsPaint=new Paint();
    /*字母背景画笔*/
    private Paint bgPaint;
    /*每一个字母的宽度*/
    private int itemWidth;
    /*每一个字母的高度*/
    private int itemHeight;
    /*手指按下的字母索引*/
    private int touchIndex = 0;
    /*手指按下的字母改变接口*/
    private onWordsChangeListener listener;
    /*设置手指按下字母改变监听*/

    public void setOnWordsChangeListener(onWordsChangeListener listener) {
        this.listener = listener;
    }

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

    public BaseView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public BaseView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        itemWidth = getMeasuredWidth();
        //使得边距好看一些
        int height = getMeasuredHeight() - 10;
        itemHeight = height / 27;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        wordsPaint.setTextSize(40);
        for (int i = 0; i < words.length; i++) {
            //判断是不是我们按下的当前字母
            if (touchIndex == i) {
                //绘制文字圆形背景
//                canvas.drawCircle(itemWidth / 2, itemHeight / 2 + i * itemHeight, 23, bgPaint);
                wordsPaint.setColor(Color.RED);
            } else {
                wordsPaint.setColor(Color.BLACK);
            }
            //获取文字的宽高
            Rect rect = new Rect();
            wordsPaint.getTextBounds(words[i], 0, 1, rect);
            int wordWidth = rect.width();
            //绘制字母
            float wordX = itemWidth / 2 - wordWidth / 2;
            float wordY = itemWidth / 2 + i * itemHeight;
            canvas.drawText(words[i], wordX, wordY, wordsPaint);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_MOVE:
                float y = event.getY();
                //关键点===获得我们按下的是那个索引(字母)
                int index = (int) (y / itemHeight);
                if (index != touchIndex)
                    touchIndex = index;
                //防止数组越界
                if (listener != null && 0 <= touchIndex && touchIndex <= words.length - 1) {
                    //回调按下的字母
                    listener.wordsChange(words[touchIndex]);
                }
                //刷新
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                //手指抬起,不做任何操作
                break;
        }
        return true;
    }
    /*手指按下了哪个字母的回调接口*/
    public interface onWordsChangeListener {
        void wordsChange(String words);
    }
    /*设置当前按下的是那个字母*/
    public void setTouchIndex(String word) {
        for (int i = 0; i < words.length; i++) {
            if (words[i].equals(word)) {
                touchIndex = i;
                invalidate();
                return;
            }
        }
    }
}

 

//第二步 布局

<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.hasee.a817ceshi.Main2Activity">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ListView
            android:layout_toLeftOf="@+id/mView"
            android:id="@+id/mRe"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
        </ListView>

        <com.example.hasee.a817ceshi.BaseView
            android:layout_alignParentRight="true"
            android:id="@+id/mView"
            android:layout_width="40dp"
            android:layout_height="match_parent"
            />

        <TextView
            android:visibility="gone"
            android:id="@+id/mText"
            android:textSize="60sp"
            android:background="@color/colorAccent"
            android:gravity="center"
            android:layout_centerInParent="true"
            android:layout_width="100dp"
            android:layout_height="100dp" />
    </RelativeLayout>


</android.support.constraint.ConstraintLayout>

 

//第三步 写了一个拼音工具类,这个需要导入jar包,我导入的是pinyin4j-2.5.0.jar这个,大家可以网上下载一下。导入并add添加,就可以了。

下载地址:

http://www.java2s.com/Code/Jar/p/Downloadpinyin4j250jar.htm

public class PinyinUtil {
    /**
     * 将hanzi转成拼音
     *
     * @param hanzi 汉字或字母
     * @return 拼音
     */
    public static String getPinyin(String hanzi) {
        StringBuilder sb = new StringBuilder();
        HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
        format.setCaseType(HanyuPinyinCaseType.UPPERCASE);
        format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
        //由于不能直接对多个汉子转换,只能对单个汉子转换
        char[] arr = hanzi.toCharArray();
        for (int i = 0; i < arr.length; i++) {
            if (Character.isWhitespace(arr[i])) {
                continue;
            }
            try {
                String[] pinyinArr = PinyinHelper.toHanyuPinyinStringArray(arr[i], format);
                if (pinyinArr != null) {
                    sb.append(pinyinArr[0]);
                } else {
                    sb.append(arr[i]);
                }
            } catch (Exception e) {
                e.printStackTrace();
                //不是正确的汉字
                sb.append(arr[i]);
            }
        }
        //取字符串的前1个字符,只要第一个字母
        String substring = sb.substring(0, 1);
        return substring;
    }
}

//第四步 Activity里的使用:

public class Main2Activity extends AppCompatActivity implements BaseView.onWordsChangeListener {

    private ListView mRe;
    private BaseView mView;
    private TextView mText;
    private List<Bean> mList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        initView();
    }

    private void initView() {
        mRe = (ListView) findViewById(R.id.mRe);
        mView = (BaseView) findViewById(R.id.mView);
        mText = (TextView) findViewById(R.id.mText);
        mView.setOnWordsChangeListener(this);

        mList = new ArrayList<>();
//我写的这个数据也是没谁了,写代码写的有点短路
//这个第一个参数传递的是Bean类里的String类型的数据,通过这个拼音工具类转换与截取,把数据转换成第一个字母。
        mList.add(new Bean(PinyinUtil.getPinyin("阿超"),"阿超"));
        mList.add(new Bean(PinyinUtil.getPinyin("阿宽"),"阿宽"));
        mList.add(new Bean(PinyinUtil.getPinyin("阿牛"),"阿牛"));
        mList.add(new Bean(PinyinUtil.getPinyin("阿剑"),"阿剑"));

        mList.add(new Bean(PinyinUtil.getPinyin("白小白"),"白小白"));
        mList.add(new Bean(PinyinUtil.getPinyin("白百合"),"白百合"));

        mList.add(new Bean(PinyinUtil.getPinyin("曹操"),"曹操"));
        mList.add(new Bean(PinyinUtil.getPinyin("曹丕"),"曹丕"));

        mList.add(new Bean(PinyinUtil.getPinyin("大龙"),"大龙"));
        mList.add(new Bean(PinyinUtil.getPinyin("大飞"),"大飞"));

        mList.add(new Bean(PinyinUtil.getPinyin("易中天"),"易中天"));
        mList.add(new Bean(PinyinUtil.getPinyin("易大师"),"易大师"));
        mList.add(new Bean(PinyinUtil.getPinyin("医生"),"医生"));
        mList.add(new Bean(PinyinUtil.getPinyin("蚁人"),"蚁人"));

        mList.add(new Bean(PinyinUtil.getPinyin("发哥"),"发哥"));
        mList.add(new Bean(PinyinUtil.getPinyin("肥龙"),"肥龙"));

        mList.add(new Bean(PinyinUtil.getPinyin("哥白尼"),"哥白尼"));
        mList.add(new Bean(PinyinUtil.getPinyin("革命军"),"革命军"));

        mList.add(new Bean(PinyinUtil.getPinyin("哈哈"),"哈哈"));
        mList.add(new Bean(PinyinUtil.getPinyin("海哥"),"海哥"));

        mList.add(new Bean(PinyinUtil.getPinyin("嘉禾"),"嘉禾"));
        mList.add(new Bean(PinyinUtil.getPinyin("姬发"),"姬发"));

        mList.add(new Bean(PinyinUtil.getPinyin("开牛"),"开牛"));
        mList.add(new Bean(PinyinUtil.getPinyin("铠甲勇士"),"铠甲勇士"));


//ListView适配,把这个集合传到适配器,开始适配,适配器里还得判断。
        mRe.setAdapter(new MyAdapters(mList, Main2Activity.this));
        mRe.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {

            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
                //当滑动列表的时候,更新右侧字母列表的选中状态
                mView.setTouchIndex(mList.get(firstVisibleItem).getPing());
            }
        });
    }

    @Override
    public void wordsChange(String words) {
        updateWord(words);
        updateListView(words);
    }

    Handler handler = new Handler();

    private void updateWord(String words) {
        mText.setText(words);
        mText.setVisibility(View.VISIBLE);
        //清空之前的所有消息
        handler.removeCallbacksAndMessages(null);
        //500ms后让tv隐藏
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                mText.setVisibility(View.GONE);
            }
        }, 500);
    }

    private void updateListView(String words) {
        for (int i = 0; i < mList.size(); i++) {
            String headerWord = mList.get(i).getPing();
            //将手指按下的字母与列表中相同字母开头的项找出来
            if (words.equals(headerWord)) {
                //将列表选中哪一个
                mRe.setSelection(i);
                //找到开头的一个即可
                return;
            }
        }
    }
}

 

//第五步 ListView适配器 适配数据:

public class MyAdapters extends BaseAdapter {
    private List<Bean> list;
    private Context context;

    public MyAdapters(List<Bean> list, Context context) {
        this.list = list;
        this.context = context;
    }

    @Override
    public int getCount() {
        return list.size();
    }

    @Override
    public Object getItem(int i) {
        return list.get(i);
    }

    @Override
    public long getItemId(int i) {
        return i;
    }

    @Override
    public View getView(int i, View convertView, ViewGroup viewGroup) {
        MyAdapters.ViewHolder holder;
        if (convertView == null) {
            holder = new MyAdapters.ViewHolder();
            convertView = LayoutInflater.from(context).inflate(R.layout.item, null);
            holder.mDingT1 = (TextView) convertView.findViewById(R.id.mDingT1);
            holder.mDingT2 = (TextView) convertView.findViewById(R.id.mDingT2);
            convertView.setTag(holder);
        } else {
            holder = (MyAdapters.ViewHolder) convertView.getTag();
        }
        String first_letter = list.get(i).getPing();
        holder.mDingT1.setText(first_letter);
        holder.mDingT2.setText(list.get(i).getName());
        //将相同字母开头的合并在一起
        if (i == 0) {
            //第一个是一定显示的
            holder.mDingT1.setVisibility(View.VISIBLE);
        } else {
            //后一个与前一个对比,判断首字母是否相同,相同则隐藏
            String first_letter1 = list.get(i - 1).getPing();
            if (first_letter.equals(first_letter1)) {
                holder.mDingT1.setVisibility(View.GONE);
            } else {
                holder.mDingT1.setVisibility(View.VISIBLE);
            }
        }
        return convertView;
    }

    private class ViewHolder {
        private TextView mDingT1;
        private TextView mDingT2;
    }
}

//第六步  Bean类:

public class Bean {
    private String Ping;
    private String name;

    public Bean() {
    }

    public Bean(String ping, String name) {
        Ping = ping;
        this.name = name;
    }

    public String getPing() {
        return Ping;
    }

    public void setPing(String ping) {
        Ping = ping;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

//—————————————————————————完—————————————————————————-

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/118342.html

(0)
seven_的头像seven_bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!