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


偶然看见飞常准(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

<?xml version="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

更多相关文章

  1. 史上最全的Android开发索引帖
  2. Android动画资源(三)——插值器
  3. NDK编译Libyuv
  4. MD2模型結構解釋
  5. Realm简单使用
  6. Android(安卓)Toast大全(五种情形)建立属于你自己的Toast
  7. Ionic Tabs
  8. Android(安卓)Eclipse 自动安装到真机(免去选择的麻烦)
  9. [转]微信ANDROID客户端-会话速度提升70%的背后

随机推荐

  1. android电池信息简介
  2. Android开发之拖动条/滑动条控件、星级评
  3. 笔记!
  4. Android 左右滑屏效果
  5. android adb 命令大全
  6. API 23 widget.Space——属性分析
  7. 在android创建bitmap避免低记忆法
  8. Android日志框架SLF4J Android
  9. android configuration example
  10. android全屏,强制竖屏,强制横屏