Android自定义字母选择侧边栏
程序员文章站
2022-03-07 23:05:13
本文实例为大家分享了android自定义字母选择侧边栏的具体代码,供大家参考,具体内容如下lettersidebar.javapackage com.zb.customview.widgets; im...
本文实例为大家分享了android自定义字母选择侧边栏的具体代码,供大家参考,具体内容如下
lettersidebar.java
package com.zb.customview.widgets; import android.content.context; import android.content.res.typedarray; import android.graphics.canvas; import android.graphics.color; import android.graphics.paint; import android.graphics.rect; import android.text.textutils; import android.util.attributeset; import android.view.motionevent; import android.view.view; import androidx.annotation.nullable; import com.zb.customview.r; public class lettersidebar extends view { private paint mpaint; private int color, selectedcolor; private float textsize, spacing; private string mchoosing = "z"; private onletterselectedlistener listener; private int width, height; 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"}; public interface onletterselectedlistener { //空表示取消选中 void onselected(string letter); } public void setonletterselectedlistener(onletterselectedlistener listener) { this.listener = listener; } public lettersidebar(context context) { this(context, null); } public lettersidebar(context context, @nullable attributeset attrs) { super(context, attrs); if(null != attrs) { typedarray ta = context.obtainstyledattributes(attrs, r.styleable.lettersidebar); color = ta.getcolor(r.styleable.lettersidebar_lettersidebar_textcolor, color.black); selectedcolor = ta.getcolor(r.styleable.lettersidebar_lettersidebar_textselectedcolor, color.red); textsize = ta.getdimensionpixelsize(r.styleable.lettersidebar_lettersidebar_textsize, sp2px(12)); spacing = ta.getdimensionpixelsize(r.styleable.lettersidebar_lettersidebar_spacing, dp2px(5)); ta.recycle(); } init(); } private void init() { mpaint = new paint(); mpaint.setantialias(true); mpaint.setcolor(color); mpaint.settextsize(textsize); } @override protected void ondraw(canvas canvas) { drawtext(canvas); drawselectedtext(canvas, mchoosing); } private void drawtext(canvas canvas) { mpaint.setcolor(color); for (int i=0; i<letters.length; i++) { drawletterat(canvas, i, letters[i]); } } private void drawselectedtext(canvas canvas, string selected) { if(textutils.isempty(selected)) return; mpaint.setcolor(selectedcolor); int position = -1; for(int i=0; i<letters.length; i++) { if(selected.equals(letters[i])) { position = i; break; } } if(position < 0 || position >= letters.length) return; drawletterat(canvas, position, selected); } @override public boolean ontouchevent(motionevent event) { int action = event.getaction(); switch (action) { case motionevent.action_down: case motionevent.action_move: float x = event.getx(); float y = event.gety(); if(istouchinsideview(x, y)) { //触摸在控件内 int position = caculateposition(y); if(position >= 0 && position < letters.length) { //合规位置 string letter = letters[position]; if(!letter.equals(mchoosing)) { //与选中的不符 去刷新控件 mchoosing = letter; performlistener(mchoosing); invalidate(); } } else { //不合规位置 if(null != mchoosing) { mchoosing = null; performlistener(mchoosing); invalidate(); } } } else if(null != mchoosing) { //点击事件不在view内部 mchoosing = null; performlistener(mchoosing); invalidate();//触摸在view之外 取消选中 } return true; default: if(mchoosing != null) { mchoosing = null; performlistener(mchoosing); invalidate(); } break; } return super.ontouchevent(event); } private void performlistener(string letter) { if(null != listener) listener.onselected(letter); } private boolean istouchinsideview(float x, float y) { //左右可以适当判断在控件内 if(x >= 0 && x <= width && y >= getpaddingtop() && y < height) return true; return false; } /** * 计算触摸的位置 * @param y * @return */ private int caculateposition(float y) { float heightwithoutpadding = height - getpaddingtop() - getpaddingbottom(); float eachelementheight = heightwithoutpadding / letters.length; y -= getpaddingtop(); int position = (int) (y / eachelementheight); return position; } private void drawletterat(canvas canvas, int position, string letter) { float heightforeach = ((height * 1f - getpaddingtop() - getpaddingbottom()) - (letters.length - 1) * spacing) / letters.length; float spacinginup = spacing * (position - 1); if(spacinginup < 0) spacinginup = 0; float currenttop = getpaddingtop() + (heightforeach * position) + spacinginup; float currentbottom = currenttop + heightforeach; paint.fontmetrics fmi = mpaint.getfontmetrics(); float x = (width - getpaddingleft() - getpaddingright() - mpaint.measuretext(letter)) / 2f + getpaddingleft(); float baseline = (fmi.descent + math.abs(fmi.ascent)) / 2f - fmi.descent; float y = (currentbottom + currenttop) / 2f + baseline; canvas.drawtext(letter, 0, 1, x, y, mpaint); } @override protected void onlayout(boolean changed, int left, int top, int right, int bottom) { super.onlayout(changed, left, top, right, bottom); if(changed) { width = getwidth(); height = getheight(); } } @override protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { super.onmeasure(widthmeasurespec, heightmeasurespec); int textwidth = (int) (getpaddingleft() + getpaddingright() + mpaint.measuretext("a")); rect textbounds = new rect(); mpaint.gettextbounds("a", 0, 1, textbounds); int singletextheight = textbounds.height(); int totalheight = (int) (27f * singletextheight + 26f * spacing) + getpaddingbottom() + getpaddingtop();//26个字母+1个# int widthmode = measurespec.getmode(widthmeasurespec); int heightmode = measurespec.getmode(widthmeasurespec); int specwidth = measurespec.getsize(widthmeasurespec); int specheight = measurespec.getsize(widthmeasurespec); int realwidth, realheight; if(widthmode == measurespec.exactly) { realwidth = specwidth; } else { realwidth = textwidth; } if(heightmode == measurespec.exactly) { realheight = specheight; } else { realheight = totalheight; } setmeasureddimension(realwidth, realheight); } protected int dp2px(int dp) { return (int) (getcontext().getresources().getdisplaymetrics().density * dp + 0.5); } protected int sp2px(int sp) { return (int) (getcontext().getresources().getdisplaymetrics().scaleddensity * sp + 0.5); } }
attrs.xml
<declare-styleable name="lettersidebar"> <attr name="lettersidebar_textcolor" format="color"/> <attr name="lettersidebar_textselectedcolor" format="color"/> <attr name="lettersidebar_textsize" format="dimension"/> <attr name="lettersidebar_spacing" format="dimension"/> </declare-styleable>
layout.xml
<com.zb.customview.widgets.lettersidebar android:id="@+id/lettersidebar" android:layout_width="wrap_content" android:layout_height="wrap_content" app:lettersidebar_textsize="14sp" app:lettersidebar_textcolor="#ffffff" android:padding="10dp" app:lettersidebar_textselectedcolor="#ff0000" app:lettersidebar_spacing="2dp" app:layout_constraintright_torightof="parent" app:layout_constrainttop_totopof="parent" app:layout_constraintbottom_tobottomof="parent" android:background="#a4a4a4"/>
代码中使用
sidebar.setonletterselectedlistener(new lettersidebar.onletterselectedlistener() { @override public void onselected(string letter) { if(textutils.isempty(letter)) { p.p("取消选中"); lettertxt.setvisibility(view.gone); } else { p.p("选中" + letter); lettertxt.settext(letter); lettertxt.setvisibility(view.visible); } } });
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
下一篇: laravel多视图共享数据实例代码