栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 移动开发 > Android

Android自定义字母导航栏

Android 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Android自定义字母导航栏

本文实例为大家分享了Android字母导航栏的具体代码,供大家参考,具体内容如下

效果

实现逻辑

明确需求

字母导航栏在实际开发中还是比较多见的,城市选择、名称选择等等可能需要到。 现在要做到的就是在滑动控件过程中可以有内容以及 下标的回调,方便处理其他逻辑!

整理思路

1、确定控件的尺寸,防止内容显示不全。相关的逻辑在onMeasure()方法中处理;
2、绘制显示的内容,在按下和抬起不同状态下文字、背景的颜色。相关逻辑在onDraw()方法中;
3、滑动事件的处理以及事件回调。相关逻辑在onTouchEvent()方法中;

动手实现

在需求明确、思路清晰的情况下就要开始动手实现(需要了解自定义View的一些基础API)。核心代码就onDraw()中。在代码中有思路和注释,可以结合代码一起看看。如果有疑惑、优化、错误的地方请在评论区提出,共同进步!

完整代码


public class CustomLetterNavigationView extends View {
  private static final String TAG = "CustomLetterNavigation";
  //导航内容
  private String[] mNavigationContent;
  //导航栏内容间隔
  private float mContentDiv;
  //导航栏文字大小
  private float mContentTextSize;
  //导航栏文字颜色
  private int mContentTextColor;
  //导航栏按下时背景颜色
  private int mBackgroundColor;
  //导航栏按下时圆角度数
  private int mBackGroundAngle = 0;
  //导航栏按下时文字颜色
  private int mDownContentTextColor;
  private TextPaint mTextPaint;
  private Paint mPaintBackgrount;
  private boolean mEventActionState = false;
  private String mCurrentLetter = "";
  private onNavigationScrollerListener mOnNavigationScrollerListener;
  private final RectF mRectF = new RectF();
  public CustomLetterNavigationView(Context context) {
    this(context, null);
  }

  public CustomLetterNavigationView(Context context, @Nullable AttributeSet attrs) {
    this(context, attrs, 0);
  }

  public CustomLetterNavigationView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    initDefaultData();//初始化默认数据
    initAttrs(context, attrs);
  }

  @Override
  protected void onDraw(Canvas canvas) {
    
    int mViewWidth = getWidth();
    //绘制背景
    mRectF.set(0, 0, mViewWidth, getHeight());
    if (mEventActionState) {
      mTextPaint.setColor(mDownContentTextColor);
      mPaintBackgrount.setColor(mBackgroundColor);
      canvas.drawRoundRect(mRectF, mBackGroundAngle, mBackGroundAngle, mPaintBackgrount);
    } else {
      mTextPaint.setColor(mContentTextColor);
      mPaintBackgrount.setColor(Color.TRANSPARENT);
      Drawable mBackground = getBackground();
      if (mBackground instanceof ColorDrawable) {
 mPaintBackgrount.setColor(((ColorDrawable) mBackground).getColor());
      }
      canvas.drawRoundRect(mRectF, mBackGroundAngle, mBackGroundAngle, mPaintBackgrount);
    }
    //绘制文本
    float textX = mViewWidth / 2;
    //X轴坐标
    int contentLenght = getContentLength();
    //Y轴坐标(这里在测量的时候多加入了两个间隔高度要减去,同时还有Padding值)
    float heightShould = (getHeight() - mContentDiv * 2 - getPaddingTop() - getPaddingBottom()) / contentLenght;
    for (int i = 0; i < contentLenght; i++) {
      //计算Y轴的坐标
      float startY = ((i + 1) * heightShould) + getPaddingTop();
      //绘制文字
      canvas.drawText(mNavigationContent[i], textX, startY, mTextPaint);
    }
  }

  @Override
  public boolean onTouchEvent(MotionEvent event) {
    
    float mEventY = event.getY();
    switch (event.getAction()) {
      case MotionEvent.ACTION_DOWN:
 //手指按下的时候,修改Enent状态、重绘背景、触发回调
 mEventActionState = true;
 invalidate();
 if (monNavigationScrollerListener != null) {
   mOnNavigationScrollerListener.onDown();
 }
 scrollCount(mEventY);
 break;
      case MotionEvent.ACTION_MOVE:
 scrollCount(mEventY);
 break;
      case MotionEvent.ACTION_CANCEL:
      case MotionEvent.ACTION_UP:
 //手指离开的时候,修改Enent状态、重绘背景、触发回调
 mEventActionState = false;
 invalidate();
 if (monNavigationScrollerListener != null) {
   mOnNavigationScrollerListener.onUp();
 }
 break;
    }
    return true;
  }


  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    
    int widhtMode = MeasureSpec.getMode(widthMeasureSpec);
    int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    //获取控件的尺寸
    int actualWidth = MeasureSpec.getSize(widthMeasureSpec);
    int actualHeight = MeasureSpec.getSize(heightMeasureSpec);
    int contentLegth = getContentLength();
    //计算一个文字的尺寸
    Rect mRect = measureTextSize();
    //内容的最小宽度
    float contentWidth = mRect.width() + mContentDiv * 2;
    //内容的最小高度
    float contentHeight = mRect.height() * contentLegth + mContentDiv * (contentLegth + 3);
    if (MeasureSpec.AT_MOST == widhtMode) {
      //宽度包裹内容
      actualWidth = (int) contentWidth + getPaddingLeft() + getPaddingRight();
    } else if (MeasureSpec.EXACTLY == widhtMode) {
      //宽度限制
      if (actualWidth < contentWidth) {
 actualWidth = (int) contentWidth + getPaddingLeft() + getPaddingRight();
      }
    }
    if (MeasureSpec.AT_MOST == heightMode) {
      //高度包裹内容
      actualHeight = (int) contentHeight + getPaddingTop() + getPaddingBottom();
    } else if (MeasureSpec.EXACTLY == widhtMode) {
      //高度限制
      if (actualHeight < contentHeight) {
 actualHeight = (int) contentHeight + getPaddingTop() + getPaddingBottom();
      }
    }
    setMeasuredDimension(actualWidth, actualHeight);
  }


  
  private void initDefaultData() {
    mNavigationContent = 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"};
    mContentDiv = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, getResources().getDisplayMetrics());
    mContentTextSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 14, getResources().getDisplayMetrics());
    mContentTextColor = Color.parseColor("#333333");
    mDownContentTextColor = Color.WHITE;
    mBackgroundColor = Color.parseColor("#d7d7d7");
    mBackGroundAngle = 0;
    //绘制文字画笔
    mTextPaint = new TextPaint();
    mTextPaint.setAntiAlias(true);
    mTextPaint.setTextSize(mContentTextSize);
    mTextPaint.setColor(mContentTextColor);
    mTextPaint.setTextAlign(Paint.Align.CENTER);
    //绘制背景画笔
    mPaintBackgrount = new Paint();
    mPaintBackgrount.setAntiAlias(true);
    mPaintBackgrount.setStyle(Paint.Style.FILL);
  }

  
  private void initAttrs(Context context, AttributeSet attrs) {
    TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomLetterNavigationView);
    mContentTextColor = mTypedArray.getColor(R.styleable.CustomLetterNavigationView_customTextColorDefault, mContentTextColor);
    mBackgroundColor = mTypedArray.getColor(R.styleable.CustomLetterNavigationView_customBackgroundColorDown, mBackgroundColor);
    mDownContentTextColor = mTypedArray.getColor(R.styleable.CustomLetterNavigationView_customTextColorDown, mDownContentTextColor);
    mContentTextSize = mTypedArray.getDimension(R.styleable.CustomLetterNavigationView_customTextSize, mContentTextSize);
    mContentDiv = mTypedArray.getFloat(R.styleable.CustomLetterNavigationView_customLetterDivHeight, mContentDiv);
    mBackGroundAngle = mTypedArray.getInt(R.styleable.CustomLetterNavigationView_customBackgroundAngle, mBackGroundAngle);
    mTypedArray.recycle();
  }


  
  private int getContentLength() {
    if (mNavigationContent != null) {
      return mNavigationContent.length;
    }
    return 0;
  }

  
  private void scrollCount(float mEventY) {
    //滑动的时候利用滑动距离和每一个字符高度进行取整,获取到Index
    Rect mRect = measureTextSize();
    int index = (int) ((mEventY - getPaddingTop() - getPaddingBottom() - mContentDiv * 2) / (mRect.height() + mContentDiv));
    //防止越界
    if (index >= 0 && index < getContentLength()) {
      String newLetter = mNavigationContent[index];
      //防止重复触发回调
      if (!mCurrentLetter.equals(newLetter)) {
 mCurrentLetter = newLetter;
 if (monNavigationScrollerListener != null) {
   mOnNavigationScrollerListener.onScroll(mCurrentLetter, index);
 }
      }
    }
  }

  
  public Rect measureTextSize() {
    Rect mRect = new Rect();
    if (mTextPaint != null) {
      mTextPaint.getTextBounds("田", 0, 1, mRect);
    }
    return mRect;
  }


  
  public void setonNavigationScrollerListener(onNavigationScrollerListener onNavigationScrollerListener) {
    this.monNavigationScrollerListener = onNavigationScrollerListener;
  }

  
  public void setNavigationContent(String content) {
    if (!TextUtils.isEmpty(content)) {
      mNavigationContent = null;
      mNavigationContent = new String[content.length()];
      for (int i = 0; i < content.length(); i++) {
 mNavigationContent[i] = String.valueOf(content.charAt(i));
      }
    }
    //需要重新测量
    requestLayout();
  }

  public interface onNavigationScrollerListener {
    //按下
    void onDown();

    //滑动
    void onScroll(String letter, int position);

    //离开
    void onUp();

  }
}

自定义属性


    
    
    
    
    
    

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持考高分网。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/154611.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号