自定义控件系列二(26字母导航条)

先来句古德莫宁

26字母导航条很早就有了,比如微信的联系人列表,比如网易云搜索音乐的列表都有。不过我不怎么喜欢这个设计感觉有点老。不过项目需求需要还是自己手撸了一个,思路也很简单,唯一的麻烦就知识判断坐标而已,但如果你看过事件分发源码这个也是很好理解。

先上代码:

public class XzPyNavigationBar extends LinearLayout {
    private Context context;
	//数据源
    private String[] arr = {"◉", "热", "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 AttachPopup attachPopup;
    private OnChangeNavigation onChangeNavigation;
    private int LightIndex = 1; //高亮下标 默认为1

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

    public XzPyNavigationBar(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        setOrientation(VERTICAL);
		//设置一下导航条的背景色美化下导航条
        setBackgroundResource(R.drawable.xz_py_navigation_back);
        setPadding(10, 20, 10, 40);
        if (this.context == null) {
            this.context = context;
        }
        initView();
        addListener();
    }

//设置选中的元素,根据下标设置
    public void setLightIndex(int lightIndex) {
        LightIndex = lightIndex;
        for (int i = 0; i < getChildCount(); i++) {
            if (i == this.LightIndex) {
                ((TextView) getChildAt(i)).setTextColor(Color.parseColor("#F9BD00"));
            } else {
                ((TextView) getChildAt(i)).setTextColor(Color.parseColor("#C5C5C5"));
            }
        }
    }
//设置选中的元素,根据内容设置
    public void setLightIndex(String v) {
        for (int i = 0; i < arr.length; i++) {
            if (v.equals(arr[i])) {
                setLightIndex(i);
                break;
            }
        }
    }

    private void initView() {
        for (int i = 0; i < arr.length; i++) {
            final TextView textView = (TextView) LayoutInflater.from(context).inflate(R.layout.xz_py_navigation_item, null);
            textView.setText(arr[i]);
            if (i == LightIndex) textView.setTextColor(Color.parseColor("#F9BD00"));
            addView(textView);
        }
    }

//默认拦截为true
//这里必须这样做
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return true;
    }

    private void addListener() {
        setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        for (int i = 1; i < getChildCount(); i++) {
                            ((TextView) getChildAt(i)).setTextColor(Color.parseColor("#C5C5C5"));
                            if (isTouchPointInView(getChildAt(i), (int) event.getRawX(), (int) event.getRawY())) {
                                popwin((TextView) getChildAt(i), ((TextView) getChildAt(i)).getText().toString());
                                ((TextView) getChildAt(i)).setTextColor(Color.parseColor("#F9BD00"));
                                if (onChangeNavigation != null)
                                    onChangeNavigation.Chanage(((TextView) getChildAt(i)).getText().toString());
                            }
                        }
                        break;
                    case MotionEvent.ACTION_MOVE:
                        for (int i = 1; i < getChildCount(); i++) {
                            ((TextView) getChildAt(i)).setTextColor(Color.parseColor("#C5C5C5"));
                            if (isTouchPointInView(getChildAt(i), (int) event.getRawX(), (int) event.getRawY())) {
                                if (attachPopup != null) {
                                    attachPopup.UploadText(((TextView) getChildAt(i)).getText().toString());
                                    ((TextView) getChildAt(i)).setTextColor(Color.parseColor("#F9BD00"));
                                    if (onChangeNavigation != null)
                                        onChangeNavigation.Chanage(((TextView) getChildAt(i)).getText().toString());
                                }
                            }
                        }
                        break;
                    case MotionEvent.ACTION_UP:
                        if (attachPopup != null) attachPopup.dismiss();
                        break;
                }
                return true;
            }
        });
    }

//震动效果
    private void zd() {
        Vibrator vibrator = (Vibrator) context.getSystemService(context.VIBRATOR_SERVICE);
        vibrator.vibrate(10);
    }

//判断坐标在哪个子元素范围
    private boolean isTouchPointInView(View view, int x, int y) {
        if (view == null) {
            return false;
        }
        int[] location = new int[2];
        view.getLocationOnScreen(location);
        int left = location[0];
        int top = location[1];
        int right = left + view.getMeasuredWidth();
        int bottom = top + view.getMeasuredHeight();
        if (y >= top && y <= bottom) {
            return true;
        }
        return false;
    }
//弹窗
    private void popwin(TextView t, String s) {
        attachPopup = new AttachPopup(context, s);
        attachPopup.setBackgroundColor(Color.TRANSPARENT);
        attachPopup.showPopupWindow();
    }
//弹窗内部类 
//三方控件   implementation 'com.github.razerdp:BasePopup:2.2.1'
    public class AttachPopup extends BasePopupWindow {
        private TextView textView;

        public void UploadText(String s) {
            if (!textView.getText().equals(s)) {
                zd();
                textView.setText(s);
            }
        }

        public AttachPopup(Context context, String s) {
            super(context);
            textView = findViewById(R.id.tv_desc);
            textView.setText(s);
        }

        @Override
        protected Animation onCreateShowAnimation() {
            return null;
        }

        @Override
        protected Animation onCreateDismissAnimation() {
            return null;
        }

        @Override
        public View onCreateContentView() {
            return createPopupById(R.layout.xz_py_navigation_pop);
        }

    }
//移动改变回调方法
    public void setOnChangeNavigation(OnChangeNavigation onChangeNavigation) {
        this.onChangeNavigation = onChangeNavigation;
    }

    public interface OnChangeNavigation {
        void Chanage(String value);
    }
}

思路:继承已个线性布局,设置为VERTICAL,这样就省的你自己去布局了,然后直接addview进去Textview。当然这里的TextVIew你需要根据你的数据源去动态添加一下。然后就是重写一下拦截方法,直接改为true,就是只要到了它导航条这里,就默认自己处理了,这样的目的是为了你手指离开导航的时候还能随意滑动。那么怎么判断呢,这里判断我门只判断y坐标。判断当前的y坐标在哪个textview的范围内,就亮哪个。
判断坐标方法:

private boolean isTouchPointInView(View view, int x, int y) {
        if (view == null) {
            return false;
        }
        int[] location = new int[2];
        view.getLocationOnScreen(location);
        int left = location[0];
        int top = location[1];
        int right = left + view.getMeasuredWidth();
        int bottom = top + view.getMeasuredHeight();
		//只判断上下
        if (y >= top && y <= bottom) {
            return true;
        }
        return false;
    }

ok,搞定收工。困死了。

原创文章 29 获赞 5 访问量 4311

猜你喜欢

转载自blog.csdn.net/weixin_41078100/article/details/105041240
今日推荐