废话不多说先上效果图
先分析实现方法:
1,将26个字母和两个符号绘制在画布上。
2,复写onTouchEvent方法监听手指触摸控件位置。
代码很简单首先创建MySideBar类继承View类
public class MySideBar extends View {
private String[] letters = {"+","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 Paint paint;
private TextView textViewDialog;//显示选中的字母
private float letterHeight;//单个字母的区域高度
private OnSideBarTouchListener onSideBarTouchListener;
public MySideBar(Context context) {
this(context,null);
}
public MySideBar(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.slideswitch);
a.recycle();
initPaint();
}
private void initPaint(){
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setFakeBoldText(true);
paint.setColor(Color.parseColor("#0066FF"));
paint.setTextSize(16);
}
}
上面代码是申明一个类继承View,并初始化画笔和存放字母的字符串数组。
/**
* 在画布上绘制26个字母
* */
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int width = getWidth();
int height = getHeight();
letterHeight = (height*1f)/letters.length;
for(int i=0;i<letters.length;i++){
float textHeight = paint.measureText(letters[i]);
float y = (letterHeight*i)+letterHeight/2-textHeight/2;//字母y方向的起始绘制位置
float x = (width*1f)/2-textHeight/2;
canvas.drawText(letters[i],x,y,paint);
}
}
上面代码是计算每个字母的位置并用canvas的drawText将字母绘制在画布上。要注意paint.measureText方法是算出字母在画布上的所占的宽高。
最后一步是监听触摸事件。
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_UP:
if(textViewDialog!=null){
textViewDialog.setVisibility(GONE);
}
break;
default:
if(textViewDialog!=null){
float touchY = event.getY();
int touchP = (int) (touchY/letterHeight);
if(touchP<=27&&touchP>=0) {
textViewDialog.setVisibility(VISIBLE);
textViewDialog.setText(letters[touchP]);
if(onSideBarTouchListener!=null){
onSideBarTouchListener.onLetterChange(letters[touchP]);
}
}else {
textViewDialog.setVisibility(GONE);
}
}
break;
}
return true;
}
根据event.getY()获得手指在y方向的位置除以每个字母所占区域的高度就得到当前手指所处区域,然后从字符串数组中取出该字符大功告成。
下面贴上完整代码
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
/**
* Created by yxd on 2017/12/7.
* 字母列表侧边栏
*/
public class MySideBar extends View {
private String[] letters = {"*","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 Paint paint;
private TextView textViewDialog;//显示选中的字母
private float letterHeight;//单个字母的区域高度
private OnSideBarTouchListener onSideBarTouchListener;
public MySideBar(Context context) {
this(context,null);
}
public MySideBar(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.slideswitch);
a.recycle();
initPaint();
}
private void initPaint(){
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setFakeBoldText(true);
paint.setColor(Color.parseColor("#0066FF"));
paint.setTextSize(16);
}
/**
* 在画布上绘制26个字母
* */
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int width = getWidth();
int height = getHeight();
letterHeight = (height*1f)/letters.length;
for(int i=0;i<letters.length;i++){
float textHeight = paint.measureText(letters[i]);
float y = (letterHeight*i)+letterHeight/2-textHeight/2;//字母y方向的起始绘制位置
float x = (width*1f)/2-textHeight/2;
canvas.drawText(letters[i],x,y,paint);
}
}
public void setTextViewDialog(TextView textViewDialog) {
this.textViewDialog = textViewDialog;
}
public void setOnSideBarTouchListener(OnSideBarTouchListener onSideBarTouchListener) {
this.onSideBarTouchListener = onSideBarTouchListener;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_UP:
if(textViewDialog!=null){
textViewDialog.setVisibility(GONE);
}
break;
default:
if(textViewDialog!=null){
float touchY = event.getY();
int touchP = (int) (touchY/letterHeight);
if(touchP<=27&&touchP>=0) {
textViewDialog.setVisibility(VISIBLE);
textViewDialog.setText(letters[touchP]);
if(onSideBarTouchListener!=null){
onSideBarTouchListener.onLetterChange(letters[touchP]);
}
}else {
textViewDialog.setVisibility(GONE);
}
}
break;
}
return true;
}
public interface OnSideBarTouchListener{
void onLetterChange(String s);
}
}
下面我们创建一个activity测试该控件。
public class TestActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
TextView tvDialog = (TextView) findViewById(R.id.tv_dialog);
MySideBar mySideBar = (MySideBar) findViewById(R.id.country_sidebar);
mySideBar.setTextViewDialog(tvDialog);
}
}
布局代码
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.view.MySideBar
android:id="@+id/country_sidebar"
android:layout_width="30.0dip"
android:layout_height="match_parent"
android:layout_gravity="right|center"
/>
<TextView
android:id="@+id/tv_dialog"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:textSize="20dp"
android:gravity="center"
android:visibility="gone"
android:background="@color/bg_color"/>
</FrameLayout>
</LinearLayout>
com.example.view.MySideBar就是自定义的MySideBar控件,放在包com.example.view下。tv_dialog就是在屏幕正中间显示的文字。
测试效果与文章开头的gif图效果一至。