自定义控制6-索引条

属性文件:

<!--右侧索引条的属性-->
    <declare-styleable name="SideLetterBar">
        <attr name="text_normal_color" format="color"/>
        <!--选择与没选择的颜色-->
        <attr name="text_selected_color" format="color"/>
        <!--文本的大小-->
        <attr name="text_size" format="dimension"/>
    </declare-styleable>

控件类:

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;

import com.tstest.R;

/**
 * 索引条
 */
public class SideLetterBar extends View {

    /**
     * 索引的数据源
     */
    private String[] b = {"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"};

    /**
     * 被选中的索引,-1代表没有选择任何一个
     */
    private int choose = -1;
    private Paint paint = new Paint();

    /**
     * 是否在屏幕中间显示被选中的索引值
     */
    private boolean showBg = false;

    /**
     * 显示在屏幕中间的数据,也就是被选中的索引
     */
    private TextView overlay;

    /**
     * 回调
     */
    private OnLetterChangedListener onLetterChangedListener;


    //================================数据===========================
    /**
     * 正常的颜色,选中的颜色,文本的大小
     */
    private int text_normal_color = Color.parseColor("#666666");
    private int text_selected_color = Color.parseColor("#000000");
    private int text_size = 20;

    public SideLetterBar(Context context) {
        this(context,null);
    }

    public SideLetterBar(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }

    public SideLetterBar(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        //获取自定义属性
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.SideLetterBar);
        for (int i = 0; i < typedArray.getIndexCount(); i++) {
            int attr = typedArray.getIndex(i);
            switch (attr) {
                case R.styleable.SideLetterBar_text_normal_color:
                    text_normal_color = typedArray.getColor(attr, Color.BLUE);//文本正常的颜色
                    break;
                case R.styleable.SideLetterBar_text_selected_color:
                    text_selected_color = typedArray.getColor(attr, Color.RED);
                    break;
                case R.styleable.SideLetterBar_text_size:
                    text_size = typedArray.getDimensionPixelSize(attr, 30);
                    break;
            }
        }
        typedArray.recycle();//回收
    }

    /**
     * 设置悬浮的textview
     * @param overlay
     */
    public void setOverlay(TextView overlay){
        this.overlay = overlay;
    }

    /**
     * 设置被选中的数据
     * @param selectedText 索引条中的数据
     */
    public void setSelectedData(String selectedText){
        choose = -1;
        for (int i = 0; i < b.length; i++) {
            if(b[i].equals(selectedText)){
                choose = i;
                break;
            }
        }
        invalidate();
    }

    /**
     * 设置数据源
     * @param data
     */
    public void setSideBarData(String[] data){
        b = data;
        choose = -1;
        invalidate();
    }

    @SuppressWarnings("deprecation")
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (showBg) {
            canvas.drawColor(Color.TRANSPARENT);
        }
        int height = getHeight();
        int width = getWidth();
        int singleHeight = height / b.length;//每个的高度
        Paint.FontMetrics fontMetrics = paint.getFontMetrics();
        for (int i = 0; i < b.length; i++) {
            paint.setTextSize(text_size);
            paint.setColor(text_normal_color);//正常的颜色
            paint.setAntiAlias(true);
            if (i == choose) {
                paint.setColor(text_selected_color);//被选中的颜色
                paint.setFakeBoldText(true); //加粗
            }
            float xPos = width / 2 - paint.measureText(b[i]) / 2;
            float yPos = singleHeight * i + (singleHeight - (fontMetrics.bottom - fontMetrics.top))/2 + fontMetrics.bottom - fontMetrics.top;
            canvas.drawText(b[i], xPos, yPos, paint);
            paint.reset();
        }

    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        final int action = event.getAction();
        final float y = event.getY();
        final int oldChoose = choose;
        final OnLetterChangedListener listener = onLetterChangedListener;
        final int c = (int) (y / getHeight() * b.length);
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                showBg = true;
                if (oldChoose != c && listener != null) {
                    if (c >= 0 && c < b.length) {
                        listener.onLetterChanged(b[c]);
                        choose = c;
                        invalidate();
                        if (overlay != null){
                            overlay.setVisibility(VISIBLE);
                            overlay.setText(b[c]);
                        }
                    }
                }
                break;
            case MotionEvent.ACTION_MOVE:
                if (oldChoose != c && listener != null) {
                    if (c >= 0 && c < b.length) {
                        listener.onLetterChanged(b[c]);
                        choose = c;
                        invalidate();
                        if (overlay != null){
                            overlay.setVisibility(VISIBLE);
                            overlay.setText(b[c]);
                        }
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                showBg = false;
                choose = -1;
                invalidate();
                if (overlay != null){
                    overlay.setVisibility(GONE);
                }
                break;
        }
        return true;
    }
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return super.onTouchEvent(event);
    }


    /**
     * 索引改变的监听
     * @param onLetterChangedListener
     */
    public void setOnLetterChangedListener(OnLetterChangedListener onLetterChangedListener) {
        this.onLetterChangedListener = onLetterChangedListener;
    }

    public interface OnLetterChangedListener {
        void onLetterChanged(String letter);
    }

}

使用:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <!--悬浮的TextView的背景颜色-->
    <corners android:radius="10dp"/>
    <solid android:color="#888888"/>
</shape>

布局以及使用

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!--显示被选中的索引-->
    <TextView
        android:id="@+id/tv_letter_overlay"
        android:layout_width="120dp"
        android:layout_height="120dp"
        android:gravity="center"
        android:layout_centerInParent="true"
        android:background="@drawable/overlay_bg"
        android:textSize="40sp"
        android:textStyle="bold"
        android:textColor="#ffffff"
        android:visibility="gone"/>
    <!--右侧索引-->
    <com.tstest.view.SideLetterBar
        android:id="@+id/side_bar"
        android:layout_width="50dp"
        android:layout_height="match_parent"
        android:layout_marginTop="20dp"
        android:layout_marginBottom="20dp"
        android:gravity="center"
        android:layout_alignParentRight="true"
        app:text_normal_color="#000000"
        app:text_selected_color="#6699ff"
        app:text_size="15sp"/>

</RelativeLayout>
SideLetterBar side_bar = (SideLetterBar) findViewById(R.id.side_bar);
        TextView side_text = (TextView) findViewById(R.id.tv_letter_overlay);
        side_bar.setOverlay(side_text);//屏幕中央显示的被选中的索引值
        side_bar.setOnLetterChangedListener(new SideLetterBar.OnLetterChangedListener() {
            @Override
            public void onLetterChanged(String letter) {
                Log.e("tag","选择的:"+letter);
            }
        });

        side_bar.setSelectedData("Z");//设置当前选中的索引值
        //设置数据值
        side_bar.setSideBarData(new String[]{"还","有","3","小","时","下","班"});

效果图:

 

 

posted @ 2017-03-31 16:01  ts-android  阅读(214)  评论(0编辑  收藏  举报