美文网首页Android开发Android知识程序员
一个仿手机联系人自动排序的列表实现sortlistview(一

一个仿手机联系人自动排序的列表实现sortlistview(一

作者: 不识水的鱼 | 来源:发表于2017-12-19 15:46 被阅读100次

一个仿手机联系人自动排序的列表实现sortlistview(一)

先上图,直接看预览,只是右边的一个导航条

我的github链接

来自网络的图片

三种效果的截图,

S71219-14192930.jpg
S71219-14193705.jpg
S71219-14191837.jpg

在项目中,这种列表很常见,类似于手机联系人,或者聊天的人员列表,可以快速的定位到我们需要找到的信息

这里是第一篇,实现右边的导航,一步一步实现。

实现的原理如下:

自定义view,继承与Textview,基本设置没什么特别的,看代码:

private 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", "#"};

这里是需要的符号实现列表字母排序。

在手势的触摸事件里,获取到我们需要的y坐标

@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
    case MotionEvent.ACTION_MOVE:

        //保证在文字上才获取y
        if(event.getX()>(w-getPaddingRight()-singleTextH-10)) {
            eventY = event.getY();
            invalidate();
            return true;
        }else{
            eventY = 0;
            invalidate();
            break;
        }
    case MotionEvent.ACTION_CANCEL:
        //只有normal才会回调
        if(style==2){
            //离开的回调
            callBack.onSelectEnd();
        }
        eventY = 0;
        invalidate();
        return true;
    case MotionEvent.ACTION_UP:
        //只有normal才会回调
        if(style==2){
            //离开的回调
            callBack.onSelectEnd();
        }
        //滑动离开文字
        if(event.getX()>(w-getPaddingRight()-singleTextH-10)) {
            eventY = 0;
            invalidate();
            return true;
        }else
            break;
}
return super.onTouchEvent(event);

}

获取到了y坐标,为了后续的坐标位置作安排

 @Override
  protected void onDraw(Canvas canvas) {
  this.canvas = canvas;
  DrawView(eventY);
}

下面才是正式的逻辑

//更具y来实现绘制,即点击在文字上
  private void DrawView(float y) {
    int currentSelectIndex = -1;
      //有触摸才绘制大文字
    if (y != 0) {
    for (int i = 0; i < letters.length; i++) {
   //当前的高度
   float currentItemY = itemH * i;
   //下一个的高度
   float nextItemY = itemH * (i + 1);
   //判断位置在点中的字母间
   if (y >= currentItemY && y < nextItemY) {

       currentSelectIndex = i;
       if(callBack!=null){
           callBack.onSelectStr(currentSelectIndex,letters[i]);
       }
       //画大的字母
       Paint.FontMetrics fontMetrics = bigTextPaint.getFontMetrics();
       //文字绘制,有基线的区别,获取到文字的高度
       float bigTextSize = fontMetrics.descent - fontMetrics.ascent;
       //判断类型
       if(style==0||style==1){
           //绘制字母,大文字
           canvas.drawText(letters[i], w - getPaddingRight() - scaleWidth - bigTextSize, singleTextH + itemH * i, bigTextPaint);
       }
       //2才会回调
       if(style==2){
           //选中的回调
           callBack.onSelectStart();
       }
   }
   }
   }
   //其他的绘制
  drawLetters(y, currentSelectIndex);
}

在代码里面写了很多注释了,可以直接看看

这样最后才是最后的绘制,如下:

private void drawLetters(float y, int index) {
  //第一次进来没有缩放情况,默认画原图
    if (index == -1) {
w = getMeasuredWidth();
h = getMeasuredHeight();
//每一个字母的高度
itemH = h / letters.length;
Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
//文字绘制,有基线的区别,获取到文字的高度
singleTextH = fontMetrics.descent - fontMetrics.ascent;
//绘制字母,每个item
for (int i = 0; i < letters.length; i++) {
    canvas.drawText(letters[i], w - getPaddingRight(), singleTextH + itemH * i, textPaint);
}
//触摸的时候画缩放图
  } else {
//遍历所有字母
for (int i = 0; i < letters.length; i++) {
    //要画的字母的起始Y坐标
    float currentItemToDrawY = singleTextH + itemH * i;
    float centerItemToDrawY;
    if (index < i)
        centerItemToDrawY = singleTextH + itemH * (index + scaleItemCount);
    else
        centerItemToDrawY = singleTextH + itemH * (index - scaleItemCount);
    //最麻烦的计算,距离当前点中的字母的距离远,则比例越小,距离x越小 (delta在字母移动范围内为0-1)
    float delta = 1 - Math.abs((y - currentItemToDrawY) / (centerItemToDrawY - currentItemToDrawY));
      //                Log.i("size", letters[i] + "--->" + delta + "");
    float maxRightX = w - getPaddingRight();
    //如果大于0,表明在y坐标上方
    scaleTextPaint.setTextSize(getTextSize() + getTextSize() * delta);
    //                Log.i("scaleTextPaint_size",getTextSize() + getTextSize() * delta+"");
    float drawX = maxRightX - scaleWidth * delta;
    //超出边界直接花在边界上
   if (style==0){//波浪形状
        if (drawX > maxRightX) {
            //画边上的字母
            canvas.drawText(letters[i], maxRightX, singleTextH + itemH * i, textPaint);
        }else {
            //画弧线字母
            canvas.drawText(letters[i], drawX, singleTextH + itemH * i, scaleTextPaint);
        }
        //没有波浪
    }else {
        canvas.drawText(letters[i], maxRightX, singleTextH + itemH * i, textPaint);
    }
    }

这样才算是绘制完成,如上图的效果

其中有几个开放的方法,可以设置一些属性

如下:

    /**
    * 设置字体缩放比例
    * @param scale
    */
    public void setScaleTime(int scale){
    scaleTime=scale;
    invalidate();
    }

    /**
    * 设置缩放字体的个数,即开口大小
    * @param scaleItemCount
    */
    public  void setScaleItemCount(int scaleItemCount){
    this.scaleItemCount=scaleItemCount;
    invalidate();
    }

    /**
    * 设置样式
    * @param style
    */
    public void setStyle(int style){
    this.style=style;
    }

下面是使用

  <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"
  xmlns:sidebar="http://schemas.android.com/apk/res-auto"
  tools:context="com.yukunkun.SilderBarActivity">
  <LinearLayout android:layout_width="wrap_content"
                android:layout_height="wrap_content">
      <Button android:layout_width="wrap_content"
              android:onClick="wave"
              android:text="wave"
              android:layout_height="wrap_content"/>
      <Button android:layout_width="wrap_content"
              android:text="nowave"
              android:onClick="nowave"
              android:layout_height="wrap_content"/>
      <Button android:layout_width="wrap_content"
              android:text="normal"
              android:onClick="normal"
              android:layout_height="wrap_content"/>
  </LinearLayout>
  <com.yukunkun.SideBar
      android:textColor="@color/colorAccent"
      android:textSize="15sp"
      android:paddingRight="10dp"
      sidebar:scaleTime="1"
      android:layout_width="200dp"
      android:id="@+id/bar"
      android:layout_height="match_parent"
      android:layout_alignParentTop="true"
      android:layout_alignParentRight="true"
      android:layout_alignParentEnd="true"/>
  <TextView android:layout_width="55dp"
            android:text="A"
            android:id="@+id/tv"
            android:gravity="center"
            android:textSize="25sp"
            android:visibility="gone"
            android:textColor="#bb4e79f1"
            android:background="@color/green"
            android:layout_centerInParent="true"
            android:layout_height="55dp"/>
  </RelativeLayout>

Activity里:

public class SilderBarActivity extends AppCompatActivity {

    private SideBar mSideBar;
    private TextView mTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_silder_bar);
        mSideBar = (SideBar) findViewById(R.id.bar);
        mTextView = (TextView) findViewById(R.id.tv);
        mSideBar.setOnStrSelectCallBack(new ISideBarSelectCallBack() {
            @Override
            public void onSelectStr(int index, String selectStr) {
                mTextView.setText(selectStr);
            }

            @Override
            public void onSelectEnd() {
                //只有SideBar.STYLENORMAL才会调用这个方法
                mTextView.setVisibility(View.GONE);
            }

            @Override
            public void onSelectStart() {
                //只有SideBar.STYLENORMAL才会调用这个方法
                mTextView.setVisibility(View.VISIBLE);
            }
        });
    }

    //设置三种style
    public void wave(View view) {
        mSideBar.setStyle(SideBar.STYLEWAVE);
    }
    public void nowave(View view) {
        mSideBar.setStyle(SideBar.STYLENOWAVE);

    }
    public void normal(View view) {
        mSideBar.setStyle(SideBar.STYLENORMAL);
    }
}

在下一篇就能完成基本的功能,要使用到这里的这个silderbar

一个仿手机联系人自动排序的列表实现sortlistview(二)
参考链接

相关文章

网友评论

    本文标题: 一个仿手机联系人自动排序的列表实现sortlistview(一

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