效果图:
布局去指定
view.custom.shangguigucustomview.MyCustomIndexView 自定义View对象
<!-- 自定义联系人快速索引 --> <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" android:orientation="vertical" tools:context=".ShangGuiguTestActivity"> <ListView android:layout_width="match_parent" android:layout_height="wrap_content"> </ListView> <TextView android:id="@+id/tv_word" android:layout_width="80dp" android:layout_height="80dp" android:background="#22000000" android:layout_centerInParent="true" android:textSize="40dp" android:textColor="@android:color/black" android:gravity="center_horizontal|center_vertical" android:visibility="gone" /> <view.custom.shangguigucustomview.MyCustomIndexView android:id="@+id/mycustom_indexview" android:layout_width="30dp" android:layout_height="match_parent" android:layout_alignParentRight="true" android:background="#f00000" /> </RelativeLayout>
自定义联系人快速索引处理类:
public class MyCustomIndexView extends View { // 为什么是继承View,因为不需要操纵孩子,只需要操纵TextView private static final String TAG = MyCustomIndexView.class.getSimpleName(); 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 IMyCustomIndexBack iBack2; public void setBack(IMyCustomIndexBack iBack2) { this.iBack2 = iBack2; } private Paint paint; public MyCustomIndexView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); paint = new Paint(); paint.setTextSize(40); paint.setAntiAlias(true); paint.setTypeface(Typeface.DEFAULT_BOLD); paint.setColor(Color.WHITE); } private int indexViewWidth; private int itemIndexViewHeight; private int heightMeasureSpec; private int itemHeight; @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); itemIndexViewHeight = heightMeasureSpec / words.length; indexViewWidth = widthMeasureSpec; this.heightMeasureSpec = heightMeasureSpec; // setMeasuredDimension(indexViewWidth, indexViewHeight); // itemHeight = getMeasuredHeight() / words.length; itemHeight = MeasureSpec.getSize(heightMeasureSpec) / words.length; Log.i(TAG, "高度实验: getMeasuredHeight():"+getMeasuredHeight() + " heightMeasureSpec:" + heightMeasureSpec); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int w = MeasureSpec.getSize(indexViewWidth); int h = MeasureSpec.getSize(itemIndexViewHeight); int defaultH = MeasureSpec.getSize(heightMeasureSpec); int defaultH26 = defaultH / words.length; for (int i=0; i<words.length;i++) { if (wordIndexValue==i) { paint.setColor(Color.BLACK); paint.setTextSize(50); } else { paint.setColor(Color.WHITE); paint.setTextSize(40); } String word = words[i]; // 我要得到字体到宽度 Rect rect = new Rect(); // 需要用到画笔 把值处理好传递给Rect paint.getTextBounds(word, 0, 1, rect); canvas.drawText(word, (w/2) - rect.width()/2, i==0?defaultH26:defaultH26*(i+1), paint); } } private int wordIndexValue = -1; private int tempWordIndexValue; @Override public boolean onTouchEvent(MotionEvent event) { super.onTouchEvent(event); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_MOVE: /*float endY = event.getY(); Log.i(TAG, "endy:" + endY); // 得到字母索引 int abcIndex = (int) (endY / itemIndexViewHeight); Log.i(TAG, "abcIndex:" + abcIndex);*/ float Y = event.getY(); wordIndexValue = (int) (Y/itemHeight);//字母索引 Log.i(TAG, "wordIndexValue;" + wordIndexValue); if (tempWordIndexValue != wordIndexValue) { iBack2.back(wordIndexValue, words[wordIndexValue]); } tempWordIndexValue = wordIndexValue; invalidate(); break; case MotionEvent.ACTION_UP: iBack2.upEnd(); tempWordIndexValue = 0; wordIndexValue = -1; invalidate(); break; default: break; } return true; } }
如何使用自定义联系人快速索引:
/** * 自定义联系人快速索引 */ tv_word = (TextView) findViewById(R.id.tv_word); final MyCustomIndexView myCustomIndexView = findViewById(R.id.mycustom_indexview); myCustomIndexView.setBack(new IMyCustomIndexBack() { @Override public void back(int index, String word) { tv_word.setVisibility(View.VISIBLE); tv_word.setText(word); // Toast.makeText(MainActivity.this, "index:" + index + " word:" + word, Toast.LENGTH_SHORT).show(); } @Override public void upEnd() { handler.sendEmptyMessageDelayed(0, 0); } });
/** * 自定义联系人快速索引 */ private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); AlphaAnimation alphaAnimation = new AlphaAnimation(1.0f, 0.0f); alphaAnimation.setDuration(3000); alphaAnimation.setFillAfter(true); tv_word.startAnimation(alphaAnimation); // tv_word.setVisibility(View.GONE); } };
分类:
Android-自定义控件
标签:
Android
, 自定义联系人快速索引
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
· ThreeJs-16智慧城市项目(重磅以及未来发展ai)
· 软件产品开发中常见的10个问题及处理方法
· Vite CVE-2025-30208 安全漏洞
· 互联网不景气了那就玩玩嵌入式吧,用纯.NET开发并制作一个智能桌面机器人(四):结合BotSharp
· MQ 如何保证数据一致性?