android仿ios版本飞常准app字母列表索引,纯原创。

仿飞常准字母索引,纯原创。


android仿ios版本飞常准app字母列表索引,纯原创。_第1张图片

android仿ios版本飞常准app字母列表索引,纯原创。_第2张图片

偶然看见飞常准(ios)的字母列表索引,觉得很酷炫,ios可以的android没有不行的,所以就写了一个demo,实现效果完全一样。

自定义字母索引view

package com.example.sunsh.letter;

import android.animation.Animator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by sunsh on 2017/8/7.
 */

public class LetterIndext extends View {

    private Paint paint;
    private float TEXT_WIDTH = 60;
    private float MAX_DISTANCE = 140;
    private final float NORMAL_SIZE = 26;
    private float MAX_SIZE = 80;
    private String DEFAULT_COLOR = "606060";
    private int SELECT_COLOR = Color.WHITE;
    //字母容器
    private ArrayList<LetterData> list = new ArrayList<>();
    private int width;
    private int height;
    private int text_height;

    //抛物线系数
    private float ratio = 0.005f;
    private int position;

    public LetterIndext(Context context) {
        super(context);
        initPaint();
    }

    public LetterIndext(Context context, AttributeSet attrs) {
        super(context, attrs);
        initPaint();
    }

    public LetterIndext(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initPaint();
    }

    public void setList(List list) {
        this.list.clear();
        for (int i = 0; i < list.size(); i++) {
            //默认距离移动距离0,默认大小40,默认颜色灰色cdcdcd,默认不加粗
            this.list.add(new LetterData(list.get(i), 0, NORMAL_SIZE, Color.parseColor("#"+DEFAULT_COLOR), false));
        }
        invalidate();
    }

    public void setSelectColor(int color){
        this.SELECT_COLOR = color;
    }

    private void initPaint() {
        paint = new Paint();
        paint.setStyle(Paint.Style.FILL);
        paint.setTextAlign(Paint.Align.CENTER);
        paint.setAntiAlias(true);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        width = canvas.getWidth();
        height = canvas.getHeight();
        canvas.translate(width - TEXT_WIDTH, 0);
        if (list.size() > 0) {
            text_height = height / list.size();
            for (int i = 0; i < list.size(); i++) {
                if (i != position) {
                    LetterData letterData = list.get(i);
                    paint.setColor(Color.TRANSPARENT);
                    Rect rect = new Rect(0, i * text_height, (int) TEXT_WIDTH, i * text_height + text_height);
                    canvas.drawRect(rect, paint);
                    Paint.FontMetrics fontMetrics = paint.getFontMetrics();
                    int baseline = (int) ((rect.bottom + rect.top - fontMetrics.bottom - fontMetrics.top) / 2);
                    paint.setTextSize(letterData.getTextSize());
                    paint.setColor(letterData.getTextColor());
                    if (letterData.isBlod)
                        paint.setFakeBoldText(true);
                    else paint.setFakeBoldText(false);
                    canvas.drawText(letterData.getText(), 30 - letterData.distance, baseline, paint);
                }
            }
            if (position < list.size() && position >= 0) {
                LetterData letterData = list.get(position);
                paint.setColor(Color.TRANSPARENT);
                Rect rect = new Rect(0, position * text_height, (int) TEXT_WIDTH, position * text_height + text_height);
                canvas.drawRect(rect, paint);
                Paint.FontMetrics fontMetrics = paint.getFontMetrics();
                int baseline = (int) ((rect.bottom + rect.top - fontMetrics.bottom - fontMetrics.top) / 2);
                paint.setTextSize(letterData.getTextSize());
                paint.setColor(letterData.getTextColor());
                if (letterData.isBlod)
                    paint.setFakeBoldText(true);
                else paint.setFakeBoldText(false);
                canvas.drawText(letterData.getText(), 30 - letterData.distance, baseline, paint);
            }
        }
    }


    private boolean isAnimation = false;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int action = event.getAction();
        if (event.getPointerCount() == 1) {
            switch (action) {
                case MotionEvent.ACTION_DOWN:
                    float x = event.getX();
                    float y = event.getY();
                    if (x > width - TEXT_WIDTH) {
                        if (text_height != 0) {
                            position = (int) (y / text_height);
                            if (position >= 0 && position < list.size())
                                if (!isAnimation) {
                                    isAnimation = true;
                                    onActionDown(position, y);
                                }
                        }
                        return true;
                    }
                    break;
                case MotionEvent.ACTION_MOVE:
                    float moveX = event.getX();
                    float moveY = event.getY();
                    if (text_height != 0) {
                        position = (int) (moveY / text_height);
                        if (position >= 0 && position < list.size())
                            onActionMove(position, moveY);
                        else {
                            if (position < 0) position = 0;
                            if (position >= list.size()) position = list.size() - 1;
                            onActionUp();
                        }
                        return true;
                    }
                    break;
                case MotionEvent.ACTION_UP:
                    if (text_height != 0) {
                        int upPosition = (int) (event.getY() / text_height);
                        if (upPosition >= 0 && upPosition < list.size()) {
                            isAnimation = true;
                            if (onSeletListener!=null){
                                onSeletListener.onSelect(upPosition,list.get(upPosition).getText());
                            }
                            onActionUp();
                            return true;
                        }
                    }
                    break;
                default:
                    isAnimation = true;
                    onActionUp();
                    break;
            }
        }

        return super.onTouchEvent(event);
    }

    private void onActionUp() {
        for (int i = position - 4; i <= position + 4; i++) {
            if (i >= 0 && i < list.size()) {
                final LetterData letterData = list.get(i);
                final float distance = letterData.getDistance();
                final ValueAnimator valueAnimator = ValueAnimator.ofFloat(distance, 0);
                if (i == position) {
                    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                        @Override
                        public void onAnimationUpdate(ValueAnimator valueAnimator) {
                            float animatedValue = (float) valueAnimator.getAnimatedValue();
                            float scaleSize = animatedValue / MAX_DISTANCE;
                            float offsetSize = (MAX_SIZE - NORMAL_SIZE) * scaleSize;
                            int alpha = (int) (255 * (1 - (animatedValue / MAX_DISTANCE)));
                            String str_alpha = Integer.toHexString(alpha);
                            int length = str_alpha.length();
                            if (length < 2) {
                                str_alpha = "0" + str_alpha;
                            }
                            if (animatedValue < 70) {
                                letterData.setState(animatedValue, NORMAL_SIZE + offsetSize, Color.parseColor("#" + str_alpha + DEFAULT_COLOR), false);
                            } else {
                                letterData.setState(animatedValue, NORMAL_SIZE + offsetSize, SELECT_COLOR, false);
                            }
                            invalidate();
                        }
                    });
                    valueAnimator.setDuration(100);
                    valueAnimator.start();
                } else {
                    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                        @Override
                        public void onAnimationUpdate(ValueAnimator valueAnimator) {
                            float animatedValue = (float) valueAnimator.getAnimatedValue();
                            float scaleSize = animatedValue / MAX_DISTANCE;
                            float offsetSize = (MAX_SIZE - NORMAL_SIZE) * scaleSize;
                            int alpha = (int) (255 * (1 - (animatedValue / MAX_DISTANCE)));
                            String str_alpha = Integer.toHexString(alpha);
                            int length = str_alpha.length();
                            if (length < 2) {
                                str_alpha = "0" + str_alpha;
                            }
                            letterData.setState(animatedValue, NORMAL_SIZE + offsetSize, Color.parseColor("#" + str_alpha + DEFAULT_COLOR), false);
                            invalidate();
                        }
                    });
                    valueAnimator.setDuration(100);
                    valueAnimator.start();
                }
                if (i == position + 4 || i == list.size() - 1) {
                    valueAnimator.addListener(new Animator.AnimatorListener() {
                        @Override
                        public void onAnimationStart(Animator animator) {

                        }

                        @Override
                        public void onAnimationEnd(Animator animator) {
                            isAnimation = false;
                            animator.removeAllListeners();
                        }

                        @Override
                        public void onAnimationCancel(Animator animator) {

                        }

                        @Override
                        public void onAnimationRepeat(Animator animator) {

                        }
                    });
                }
            }
        }
    }

    private void onActionDown(final int indext, float downY) {
        for (int i = 0; i < list.size(); i++) {
            if (i >= indext - 4 && i <= indext + 4) {
                float distance = -ratio * (downY - getCenterY(i)) * (downY - getCenterY(i)) + MAX_DISTANCE;
                if (distance < 0) distance = 0;
                final LetterData data = list.get(i);
                ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, distance);
                if (i != indext) {
                    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                        @Override
                        public void onAnimationUpdate(ValueAnimator valueAnimator) {
                            float animatedValue = (float) valueAnimator.getAnimatedValue();
                            float scaleSize = animatedValue / MAX_DISTANCE;
                            float offsetSize = (MAX_SIZE - NORMAL_SIZE) * scaleSize;
                            int alpha = (int) (255 * (1 - (animatedValue / MAX_DISTANCE)));
                            String str_alpha = Integer.toHexString(alpha);
                            int length = str_alpha.length();
                            if (length < 2) {
                                str_alpha = "0" + str_alpha;
                            }
                            data.setState(animatedValue, NORMAL_SIZE + offsetSize, Color.parseColor("#" + str_alpha + DEFAULT_COLOR), false);
                            invalidate();
                        }
                    });
                    valueAnimator.setDuration(100);
                    valueAnimator.start();
                } else {
                    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                        @Override
                        public void onAnimationUpdate(ValueAnimator valueAnimator) {
                            float animatedValue = (float) valueAnimator.getAnimatedValue();
                            float scaleSize = animatedValue / MAX_DISTANCE;
                            float offsetSize = (MAX_SIZE - NORMAL_SIZE) * scaleSize;
                            int alpha = (int) (255 * (1 - (animatedValue / MAX_DISTANCE)));
                            String str_alpha = Integer.toHexString(alpha);
                            int length = str_alpha.length();
                            if (length < 2) {
                                str_alpha = "0" + str_alpha;
                            }
                            if (animatedValue > 70)
                                data.setState(animatedValue, NORMAL_SIZE + offsetSize, SELECT_COLOR, true);
                            else
                                data.setState(animatedValue, NORMAL_SIZE + offsetSize, Color.parseColor("#" + str_alpha + DEFAULT_COLOR), false);
                        }
                    });

                    valueAnimator.setDuration(100);
                    valueAnimator.start();
                }
            } else {
                list.get(i).setState(0, NORMAL_SIZE, Color.parseColor("#"+DEFAULT_COLOR), false);
            }
        }
        invalidate();
    }

    private void onActionMove(int indext, float downY) {
        for (int i = 0; i < list.size(); i++) {
            LetterData data = list.get(i);
            if (i >= indext - 4 && i <= indext + 4) {
                float distance = -ratio * (downY - getCenterY(i)) * (downY - getCenterY(i)) + MAX_DISTANCE;
                if (distance < 0) distance = 0;
                float scaleSize = distance / MAX_DISTANCE;
                float offsetSize = (MAX_SIZE - NORMAL_SIZE) * scaleSize;
                int alpha = (int) (255 * (1 - (distance / MAX_DISTANCE)));
                String str_alpha = Integer.toHexString(alpha);
                int length = str_alpha.length();
                if (length < 2) {
                    str_alpha = "0" + str_alpha;
                }
                if (i == indext) {
                    data.setState(distance, NORMAL_SIZE + offsetSize, SELECT_COLOR, true);
                } else {
                    data.setState(distance, NORMAL_SIZE + offsetSize, Color.parseColor("#" + str_alpha + DEFAULT_COLOR), false);
                }
            } else {
                data.setState(0, NORMAL_SIZE, Color.parseColor("#"+DEFAULT_COLOR), false);
            }
        }
        invalidate();
    }

    private OnSeletListener onSeletListener;

    public void setOnSeletListener(OnSeletListener o) {
        this.onSeletListener = o;
    }

    public interface OnSeletListener {
        void onSelect(int position, String letter);
    }

    private float getCenterY(int index) {
        int i = text_height / 2 + index * text_height;
        return i;
    }

    class LetterData {
        private float distance;
        private float textSize;
        private String text;
        private int textColor;
        private boolean isBlod;

        public LetterData(String text, float distance, float textSize, int textColor, boolean isBlod) {
            this.distance = distance;
            this.textSize = textSize;
            this.text = text;
            this.textColor = textColor;
            this.isBlod = isBlod;
        }

        public void setState(float distance, float textSize, int textColor, boolean isBlod) {
            this.distance = distance;
            this.textSize = textSize;
            this.textColor = textColor;
            this.isBlod = isBlod;
        }

        public boolean isBlod() {
            return isBlod;
        }

        public void setBlod(boolean blod) {
            isBlod = blod;
        }

        public int getTextColor() {
            return textColor;
        }

        public void setTextColor(int textColor) {
            this.textColor = textColor;
        }

        public float getDistance() {
            return distance;
        }

        public void setDistance(float distance) {
            this.distance = distance;
        }

        public float getTextSize() {
            return textSize;
        }

        public void setTextSize(int textSize) {
            this.textSize = textSize;
        }

        public String getText() {
            return text;
        }

        public void setText(String text) {
            this.text = text;
        }
    }
}

... prompt'''

Activity

package com.example.sunsh.letter;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    private ArrayList<String> strings;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final ListView listView = (ListView) findViewById(R.id.listview);

        LetterIndext letterIndext = (LetterIndext) findViewById(R.id.letter);
        final ArrayList<String> list = new ArrayList<>();
        for (char i = 63; i <= 90; i++) {
            list.add(i+"");
        }
        letterIndext.setList(list);
        letterIndext.setOnSeletListener(new LetterIndext.OnSeletListener() {
            @Override
            public void onSelect(int position,String letter) {
                int i = strings.indexOf(letter);
                listView.setSelection(i);
            }
        });
        findViewById(R.id.text).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(MainActivity.this,"keyi ",Toast.LENGTH_SHORT).show();
            }
        });

        strings = new ArrayList<>();

        for (char i = 63; i <= 90; i++) {
            strings.add(i+"");
            for (int j = 0; j < 10; j++) {
                strings.add(i+""+i);
            }
        }
        listView.setAdapter(new BaseAdapter() {
            @Override
            public int getCount() {
                return strings.size();
            }

            @Override
            public Object getItem(int i) {
                return null;
            }

            @Override
            public long getItemId(int i) {
                return 0;
            }

            @Override
            public View getView(int i, View view, ViewGroup viewGroup) {
                TextView textView = new TextView(MainActivity.this);
                textView.setText(strings.get(i));
                textView.setPadding(20,20,20,20);
                return textView;
            }
        });

    }
}

... prompt'''

xml

"1.0" encoding="utf-8"?>
"http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:background="#70000000"
    android:layout_height="match_parent"
    tools:context="com.example.sunsh.letter.MainActivity">
    "@+id/listview"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    
    "@+id/text"
        android:layout_width="wrap_content"
        android:layout_centerInParent="true"
        android:layout_height="wrap_content"
        android:text="Hello World!" />

    "@+id/letter"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>


... prompt'''

下载地址

http://download.csdn.net/detail/qq_35959231/9923874

你可能感兴趣的:(自定义控件)