美文网首页
Android 自定义View 仿微信好友,字母排序

Android 自定义View 仿微信好友,字母排序

作者: snrtyunfeng | 来源:发表于2018-07-27 10:56 被阅读0次
    效果图

    一 :具体说下思路

    1 :整体用到的控件,list view(recyclerView原理一样),自定义view,汉字转拼音的utils工具类.

    2:MainActivity的xml简单就不说了,下面看代码,说下自定义View,首先自定义类继承View重写三个构造方法,重写

    onMeasure()的方法用于测量View的宽高,onSizeChanged()方法改变当前控件大小的时候调用,onDarw()方法绘制View,

    onTouchEvent()方法用于手势监听,自定义接口用于保存点击了那个字母的值。

    3:数据实体类必须 实现Comparable<泛型为当前类名> 接口,用于获取汉字的首字母和字母排序。

    4在list的Adaptes里面根据position的首字母来作为目录catalog。通过getPositionForSection(此方法为自定义的)方法,来获取catalog的首次出现的位置。如果当前位置(position)等于该分类首字母的Char的位置 ,则认为是第一次出现,则首字母显示,否则隐藏,此判断是为了避免出现相同的字母。

    5:在接口回调的方法里面,遍历list集合(为数据集合).getFirstLetter()方法获取到集合的每条数据的首字母,和接口回传的字母通过equalsIgnoreCase(此方法用于和回传的字母匹配)方法匹配。成功list就掉用setSelection(i)定位到首字母出现的位置。

    思路完毕,下面就贴代码:

    二   代码实现:

    1  MainActivity 的xml

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    ">

    android:id="@+id/mListView"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:layout_toLeftOf="@+id/mYunFengView"

    android:scrollbars="none">

    android:id="@+id/mYunFengView"

    android:layout_width="40dp"

    android:layout_height="match_parent"

    android:layout_alignParentRight="true" />

    android:visibility="gone"

    android:id="@+id/mDaZiMu2"

    android:layout_width="60dp"

    android:layout_height="60dp"

    android:layout_centerInParent="true"

    android:background="@drawable/dzm"

    android:gravity="center"

    android:text="A"

    android:textSize="30dp" />

    2  自定义VIew

    package com.example.yangai00.yy_2018_6_29.mudel.home.chengshi;

    import android.content.Context;

    import android.graphics.Canvas;

    import android.graphics.Color;

    import android.graphics.Paint;

    import android.graphics.Rect;

    import android.support.annotation.Nullable;

    import android.util.AttributeSet;

    import android.util.Log;

    import android.view.MotionEvent;

    import android.view.View;

    /**

    * Created by yangai00 on 2018/7/10.

    */

    public class YunfengView extends View {

    private String[] yuns = {"↑", "💗", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P"

    , "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"};

    private Paint paint;

    //初始化对象的时候调用

    public YunfengView(Context context) {

    super(context, null);

    }

    //在布局里面声明控件的时候调用

    public YunfengView(Context context, @Nullable AttributeSet attrs) {

    super(context, attrs, 0);

    init();

    }

    //在布局里面声明控件并用到styel的时候调用

    public YunfengView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {

    super(context, attrs, defStyleAttr);

        }

    //初始化

    private void init() {

    paint = new Paint();

    paint.setColor(Color.BLACK);

    paint.setTextSize(30);

    }

    //布局控件加载完成调用此方法

    @Override

    protected void onFinishInflate() {

    super.onFinishInflate();

    }

    //测量View的宽高

    @Override

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    }

    private float mWeight;

    private float mHeight;

    //改变当前控件大小的时候调用

    @Override

    protected void onSizeChanged(int w, int h, int oldw, int oldh) {

    //获取View的宽高

    mWeight = getMeasuredWidth();

    mHeight = getMeasuredHeight() / yuns.length;

    super.onSizeChanged(w, h, oldw, oldh);

    }

    //View 的绘制

    @Override

    protected void onDraw(Canvas canvas) {

    //循环绘制

    for (int i = 0; i < yuns.length; i++) {

    //字母的宽高

    float x = mWeight / 2;

    float y = (mHeight / 2) + DanQianKuan(yuns[i]) / 2 + i * mHeight;

    paint.setColor(i == mId ? Color.BLUE : Color.BLACK);

    canvas.drawText(yuns[i], x, y, paint);

    }

    //刷新View

    invalidate();

    super.onDraw(canvas);

    }

    private int mId = -1;

    //手势监听

    @Override

    public boolean onTouchEvent(MotionEvent event) {

    switch (event.getAction()) {

    //滑动和点击

    case MotionEvent.ACTION_DOWN:

    case MotionEvent.ACTION_MOVE:

    float Y = event.getY();

    int id = (int) (Y / mHeight);

    if (mId != id) {

    String dqzf = yuns[id];

    Log.e("点击", dqzf + "");

    //接口方法保存点击或滑动的字母,用于回调

    if (yunn != null) {

    yunn.nunn(id, dqzf);

    }

    }

    mId = id;

    invalidate();//重新走OnDraw方法

    break;

    case MotionEvent.ACTION_UP:

    mId = -1;

    break;

    }

    return true;

    }

    //接口回调保存值

    private Yunn yunn;

    public interface Yunn {

    void nunn(int pop, String zf);

    }

    public void getYunn(Yunn yunn) {

    this.yunn = yunn;

    }

    //当前的宽度

    private float DanQianKuan(String s) {

    Rect rect = new Rect();

    paint.getTextBounds(s, 0, 1, rect);

    return rect.height();

    }

    }

    3  MainActivity 主代码:

    package com.example.yangai00.yy_2018_6_29.mudel.home.homeview.activity;

    public class ChengShiActivity extends AppCompatActivity implements HomeContract.ChengShiView, View.OnClickListener {

    private TextView mDaZiMu;

    private ListView mListView;

    private YunfengView mYunFengView;

    private List list;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    supportRequestWindowFeature(Window.FEATURE_NO_TITLE);

    setContentView(R.layout.activity_cheng_shi);

    //初始化

    initView();

    //获取数据

    initData();

    }

    public void initData(){

    //list1集合中的数据是网络请求,我就不粘贴了,你换成你自己的数据就可以,注意! 实体类有汉字转拼音的方法,不要覆盖了。

    for (int i = 0; i < list1.size(); i++) {

    list.add(new User(list1.get(i).getCity_name()));

    }

    //适配器

    myAdaptesList = new MyAdaptes_list(list, this);

    mListView.setAdapter(myAdaptesList);

    //自定义接口

    mYunFengView.getYunn(new YunfengView.Yunn() {

    @Override public void nunn(int pop, String zf) {

    for (int i = 0; i < list.size(); i++) {

    //获取到list集合中的每一个条目的首字母和接口传回来的进行匹配,成功就定位到listview对应的item。

    if (zf.equalsIgnoreCase(list.get(i).getFirstLetter())) {

    mListView.setSelection(i); // 选择到首字母出现的位置 return;

    }

    }

    msetText(zf);

    }

    });

    mDaZiMu.setVisibility(View.GONE);

    }

    }

    //通过hander来让土司的字母延迟2秒消失。

    Handler handler = new Handler();

    private void msetText(String s) {

    mDaZiMu.setText(s);

    mDaZiMu.setVisibility(View.VISIBLE);

    handler.postDelayed(new Runnable() {

    @Override

    public void run() {

    mDaZiMu.setVisibility(View.GONE);

    }

    }, 2000);

    }

    //初始化

    private void initView() {

    mListView = (ListView) findViewById(R.id.mListView);

    mYunFengView = findViewById(R.id.mYunFengView);

    mDaZiMu = findViewById(R.id.mDaZiMu2);

    }

    }

    4 适配器

    package com.example.yangai00.yy_2018_6_29.mudel.home.chengshi.adaptes;

    import android.content.Context;

    import android.view.LayoutInflater;

    import android.view.View;

    import android.view.ViewGroup;

    import android.widget.BaseAdapter;

    import android.widget.TextView;

    import com.example.yangai00.yy_2018_6_29.R;

    import com.example.yangai00.yy_2018_6_29.mudel.home.homeentity.MyChengShiBen;

    import com.example.yangai00.yy_2018_6_29.mudel.home.homeentity.MyZhuanHuan;

    import com.example.yangai00.yy_2018_6_29.mudel.home.homeentity.User;

    import java.util.ArrayList;

    import java.util.List;

    /**

    * Created by yangai00 on 2018/7/10.

    */

    public class MyAdaptes_list extends BaseAdapter {

    private List list;

    private Context context;

    public MyAdaptes_list(List 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) {

    User user = list.get(position);

    ViewHolder holder;

    if (convertView == null) {

    holder = new ViewHolder();

    convertView = LayoutInflater.from(context).inflate(R.layout.my_chengshilist, null);

    holder.mDingWeiText1 = (TextView) convertView.findViewById(R.id.mZiMuList);

    holder.mDingWeiText2 = (TextView) convertView.findViewById(R.id.mNameList);

    convertView.setTag(holder);

    } else {

    holder = (ViewHolder) convertView.getTag();

    }

    //根据position获取首字母作为目录catalog

    String catalog = list.get(position).getFirstLetter();

    //如果当前位置等于该分类首字母的Char的位置 ,则认为是第一次出现,第一次出现显示,其他的隐藏

    if (position == getPositionForSection(catalog)) {

    holder.mDingWeiText1.setVisibility(View.VISIBLE);

    holder.mDingWeiText1.setText(user.getFirstLetter().toUpperCase());

    } else {

    holder.mDingWeiText1.setVisibility(View.GONE);

    }

    //赋值给Textview

    holder.mDingWeiText2.setText(this.list.get(position).getName());

    return convertView;

    }

    private class ViewHolder {

    private TextView mDingWeiText1;

    private TextView mDingWeiText2;

    }

    /**

    * 获取catalog首次出现位置

    */

    public int getPositionForSection(String catalog) {

    for (int i = 0; i < getCount(); i++) {

    String sortStr = list.get(i).getFirstLetter();

    if (catalog.equalsIgnoreCase(sortStr)) {

    return i;

    }

    }

    return -1;

    }

    }

    5 适配器引入的xml布局

    android:layout_width="match_parent"

    android:layout_height="wrap_content"

    android:orientation="vertical">

    android:id="@+id/mZiMuList"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:background="#E0E0E0"

    android:padding="10dp"

    android:text="A"

    android:textColor="#FF2A2A2D"

    android:textSize="20sp" />

    android:id="@+id/mNameList"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:gravity="center_vertical"

    android:padding="10dp"

    android:text="云哥哥"

    android:textColor="#FF4859ED"

    android:textSize="16sp" />

    6  汉字转拼音的工具类:

    package com.example.yangai00.yy_2018_6_29.mudel.home.homeentity;

    import net.sourceforge.pinyin4j.PinyinHelper;

    import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;

    import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;

    import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;

    /**

    * Created by yangai00 on 2018/7/10.

    */

    public class MyZhuanHuan {

    public static StringBuffer sb = new StringBuffer();

    /**

    * 获取汉字字符串的首字母,英文字符不变

    * 例如:云哥哥→ygg

    */

    public static String getPinYinHeadChar(String chines) {

    sb.setLength(0);

    char[] chars = chines.toCharArray();

    HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();

    defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);

    defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);

    for (int i = 0; i < chars.length; i++) {

    if (chars[i] > 128) {

    try {

    sb.append(PinyinHelper.toHanyuPinyinStringArray(chars[i], defaultFormat)[0].charAt(0));

    } catch (Exception e) {

    e.printStackTrace();

    }

    } else {

    sb.append(chars[i]);

    }

    }

    return sb.toString();

    }

    /**

    * 获取汉字字符串的第一个字母

    */

    public static String getPinYinFirstLetter(String str) {

    sb.setLength(0);

    char c = str.charAt(0);

    String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(c);

    if (pinyinArray != null) {

    sb.append(pinyinArray[0].charAt(0));

    } else {

    sb.append(c);

    }

    return sb.toString();

    }

    /**

    * 获取汉字字符串的汉语拼音,英文字符不变

    */

    public static String getPinYin(String chines) {

    sb.setLength(0);

    char[] nameChar = chines.toCharArray();

    HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();

    defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);

    defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);

    for (int i = 0; i < nameChar.length; i++) {

    if (nameChar[i] > 128) {

    try {

    sb.append(PinyinHelper.toHanyuPinyinStringArray(nameChar[i], defaultFormat)[0]);

    } catch (Exception e) {

    e.printStackTrace();

    }

    } else {

    sb.append(nameChar[i]);

    }

    }

    return sb.toString();

    }

    }

    7  实体类:

    package com.example.yangai00.yy_2018_6_29.mudel.home.homeentity;

    /**

    * Created by yangai00 on 2018/7/11.

    */

    public class User implements Comparable {

    private String name; // 姓名

    private String pinyin; // 姓名对应的拼音

    private String firstLetter; // 拼音的首字母

    public User() {

    }

    public User(String name) {

    this.name = name;

    ​​​​​​​//MyZhuanHuan类,是汉字转拼音的工具类

    pinyin = MyZhuanHuan.getPinYin(name); // 根据姓名获取拼音

    firstLetter = pinyin.substring(0, 1).toUpperCase(); // 获取拼音首字母并转成大写

    if (!firstLetter.matches("[A-Z]")) { // 如果不在A-Z中则默认为“#”

    firstLetter = "#";

    }

    }

    public String getName() {

    return name;

    }

    public String getPinyin() {

    return pinyin;

    }

    public String getFirstLetter() {

    return firstLetter;

    }

    //排序

    @Override

    public int compareTo(User another) {

    if (firstLetter.equals("#") && !another.getFirstLetter().equals("#")) {

    return 1;

    } else if (!firstLetter.equals("#") && another.getFirstLetter().equals("#")){

    return -1;

    } else {

    return pinyin.compareToIgnoreCase(another.getPinyin());

    }

    }

    }

    到此代码完毕。

    相关文章

      网友评论

          本文标题:Android 自定义View 仿微信好友,字母排序

          本文链接:https://www.haomeiwen.com/subject/cnuwmftx.html