自定义高亮显示的字母序列控件
来源:互联网 发布:c语言 音乐函数 编辑:程序博客网 时间:2024/06/06 01:20
最近看到有代码在实现类似通讯录字母索引的功能的时候,使用了ListView来做处理,个人觉得用ListView甚至现在很流行的RecycleView来做并不好,可以来自定义一个索引的控件,达到更好的效果,话不多说,先上效果图:
首先:先来说说需求
- 把字母[A - Z - #]在控件中画出来(这里以字母来举例)
- 当触摸到某个字母时,高亮显示
- 给控件设置监听,显示当前触摸到的字母
下面,就开始撸码(其实自定义View基本上就是那几个套路);
1:自定义需要的属性:
<declare-styleable name="CustomSideBar"> <!-- 字体大小 高亮的颜色 普通颜色(未选中时候) --> <attr name="slideBarTextSize" format="dimension"/> <attr name="highLightColor" format="color"/> <attr name="normalColor" format="color"/> </declare-styleable>
2:在布局文件中使用
<com.justh.dell.customsidebar.CustomSideBar android:id="@+id/side_bar" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_alignParentRight="true" android:paddingLeft="10dp" android:paddingRight="10dp" app:slideBarTextSize="20dp" app:highLightColor="@color/colorAccent" app:normalColor="@color/colorPrimary"/>
3:在自定义View中获取属性,并使用
public CustomSideBar(Context context) { this(context,null); } public CustomSideBar(Context context, @Nullable AttributeSet attrs) { this(context, attrs,0); } public CustomSideBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray array = context.obtainStyledAttributes(attrs,R.styleable.CustomSideBar); mSideBarTextSize = array.getDimensionPixelSize(R.styleable.CustomSideBar_slideBarTextSize,dp2px(mSideBarTextSize)); mHighLightColor = array.getColor(R.styleable.CustomSideBar_highLightColor,mHighLightColor); mNormalColor = array.getColor(R.styleable.CustomSideBar_normalColor,mNormalColor); array.recycle(); //初始化画笔 mHightPaint = getPaint(mHighLightColor); mNormalPaint = getPaint(mNormalColor); } //初始化画笔 private Paint getPaint(int color){ Paint paint = new Paint(); paint.setColor(color); paint.setAntiAlias(true); paint.setDither(true); paint.setTextSize(mSideBarTextSize); return paint; }
在onMeasure中去测量空间的宽高
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); //计算宽度大小 //宽度大小等于一个字母的宽度加上左右的padding值 治理取A来做例子 int width = (int) mNormalPaint.measureText("A") + getPaddingLeft() + getPaddingRight(); int height = MeasureSpec.getSize(heightMeasureSpec); setMeasuredDimension(width,height); }
然后在onDraw方法中间字母滑到对应的位置(这里直接将触摸到的时候的高亮显示字母的代码一并贴上了,懒死算了 哈哈哈)
@Override protected void onDraw(Canvas canvas) { //首先 由于是竖直排列的 所以先计算出一个字母所占据的高度 //一个字母所占据的高度 = (高度总和 - paddingTop - paddingBottom) / 元素总和 mLetterHeight = (getHeight() - getPaddingTop() - getPaddingBottom()) / letters.length; for(int i = 0;i<letters.length;i++){ //计算每一个字母所在的位置的位置的中间值centerY int centerY = getPaddingTop() + i * mLetterHeight + mLetterHeight /2; Paint.FontMetricsInt fontMetricsInt = mNormalPaint.getFontMetricsInt(); int dy = (fontMetricsInt.bottom - fontMetricsInt.top)/2 - fontMetricsInt.bottom; int baseLine = centerY + dy; //计算每一个字母所在的位置的X的起点 (居中情况下) int startX = (int) (getWidth()/2 - mNormalPaint.measureText(letters[i])/2); if(letters[i].equals(mCurrentLetter)){ canvas.drawText(letters[i],startX,baseLine,mHightPaint); }else{ canvas.drawText(letters[i],startX,baseLine,mNormalPaint); } } }
最后重写onTouch方法,用来获取当前触摸到的是哪一个字母:
@Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_MOVE: //根据当前的坐标 计算当前触摸到的是哪个条目 int dy = (int) event.getY(); int currentItem = (dy - getPaddingTop())/mLetterHeight; if(currentItem < 0){ currentItem = 0; } if(currentItem >= letters.length){ currentItem = letters.length - 1; } //获取到惦记的是哪个字母 mCurrentLetter = letters[currentItem]; if(mSideBarTouchLetterListener != null){ mSideBarTouchLetterListener.onTouchLetter(mCurrentLetter,true); } invalidate(); break; case MotionEvent.ACTION_UP: //设置延迟消失 mHandler.sendEmptyMessageDelayed(1,1000); break; } return true; } private Handler mHandler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); if(msg.what == 1){ if(mSideBarTouchLetterListener != null){ mSideBarTouchLetterListener.onTouchLetter(mCurrentLetter,false); } } } };
这里,使用了一个Handler 的延迟发送消息来处理延迟1秒消失TextView的效果
最后,给其设置字母的触摸监听回调
private SideBarTouchLetterListener mSideBarTouchLetterListener; public void setSideBarTouchLetterListener(SideBarTouchLetterListener listener){ this.mSideBarTouchLetterListener = listener; } //设置回调监听 public interface SideBarTouchLetterListener{ //flag控制显示与不显示在Activity中的圆形TextView void onTouchLetter(String letter,boolean flag); }
一直习惯了把注释写到代码里,这样阅读起来也会更方便,相信大家都能理解我的良苦用心,这里就不过多解释了。
最后 只需要在actvity中监听CustomSideBar的回调,并将对应点击的字母设置给TextView显示出来就可以了。
public class MainActivity extends AppCompatActivity implements CustomSideBar.SideBarTouchLetterListener{ private TextView mTextView; private CustomSideBar mSideBar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); initListener(); } private void initView(){ mTextView = (TextView) findViewById(R.id.textView); mSideBar = (CustomSideBar) findViewById(R.id.side_bar); } private void initListener(){ mSideBar.setSideBarTouchLetterListener(this); } @Override public void onTouchLetter(String letter,boolean flag) { if(flag){ mTextView.setVisibility(View.VISIBLE); mTextView.setText(letter); }else{ mTextView.setVisibility(View.GONE); } }}
好了,到这里就已经结束了,再来一波最后的效果图,如果大家发现有什么问题,可以回复交流下,谢谢!
阅读全文
1 0
- 自定义高亮显示的字母序列控件
- Android自定义控件样式及高亮显示
- 自定义控件【按照宽高比例显示】
- 自定义控件:动态获取控件的高
- 自定义显示图片的控件
- 自定义字母导航条控件
- 给当前选中的控件提供高亮显示功能
- 自定义宽高比例的布局控件
- Android自定义控件5----继承View通讯录索引功能之1初始化显示字母列表
- RichEdit 控件:语法高亮显示
- CListCtrl控件选中并高亮显示
- 语法高亮显示控件ICSharpCode.TextEditor
- 新手引导之控件高亮显示
- 如何自定义控件的显示效果
- VS的工具箱中显示自定义控件
- 自定义控件 - 可以显示进度的Button
- 自定义显示动态图的Android控件
- Android自定义屏幕侧边字母排序控件
- html-css练习题 (注册表单)
- Matlab中train与adapt的区别
- CSU 1993 大司马的三角形中单(数位dp)
- 手撕代码(一)快速排序
- 菜鸟的第七篇日志
- 自定义高亮显示的字母序列控件
- 安装zookeeper(单机)
- caffe下用PyQt5预测手写数字输入小程序
- spring的一些思考
- Python -练习4
- Day09 多态 抽象方法 借口
- 【hpu oj 1020 985的“树”难题 [DFS]】
- ORACLE数据库试题
- Cookie与Session的区别