列表单项选择器

本文介绍了一款自定义的SelectView组件,该组件能够通过滑动选择列表项并返回选中项的索引。文章详细阐述了其实现原理及难点,包括条件判断逻辑和TextView文本大小设置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先看UI图:
这里写图片描述
当时看到UI图的时候,想在网上随便找个控件用就好,结果找了半天没有合适的,算了自己撸一个吧,下边上效果图:
这里写图片描述
这里可以传集合数据,传多个选择项,返回的是选中数据的集合下标,本文的难点在于条件的判断,比如我滑动多少距离,我选中是那个数据,当时我也懵了很久。。。还有值得注意的是用代码给textview设置textsize时如果用px单位需要 textView.setTextSize(TypedValue.COMPLEX_UNIT_PX,UIUtils.getDimens(R.dimen.size_30px));

代码
public class SelectView extends ViewGroup {
    ViewGroup.LayoutParams  params;
    private Context mContext;
    private Scroller scroller;  // 用于滚动操作的实例
    private ArrayList<String> mlist ;
    private OnPayListener listener;
    private  float yDown;   // 手指按下时,Y 的屏幕坐标
    private float  yMove;    // 移动时,Y的屏幕坐标
    private float yLastMove ; // 上一次 move事件的屏幕坐标
    int select =0;
    List<TextView> tlist = new ArrayList<>();

    int t ;
    public SelectView(Context context) {
        super(context);
    }

    public SelectView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        scroller = new Scroller(context);
    }
    public SelectView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int childCount  = getChildCount();
        for (int i = 0; i < childCount; i++) {
            View childView = getChildAt(i);
            // 为ScrollerLayout中的每一个子控件测量大小
            measureChild(childView, widthMeasureSpec, heightMeasureSpec);
        }
    }
    @Override
    protected void onLayout(boolean b, int l, int i1, int i2, int i3) {
        if (b) {
            int childCount = getChildCount();
            for (int i = 0; i < mlist.size(); i++) {
                    TextView childView = (TextView) getChildAt(i);
                    tlist.add(childView);
                // 为ScrollerLayout中的每一个子控件在水平方向上进行布局
                childView.layout(getWidth()/2-childView.getMeasuredWidth()/2, getHeight()/2+i *2* childView.getMeasuredHeight(), getWidth()/2+childView.getMeasuredWidth()/2, getHeight()/2+(i+1) *2* childView.getMeasuredHeight());
            }

        }
    }
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int scrolledY = 0;
        TextView childView = (TextView) getChildAt(0);
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
//                if (scroller != null && !scroller.isFinished()) {
//                    scroller.abortAnimation();
//                }
                yDown = event.getRawY();
                yMove=yDown;
                yLastMove = yMove;
                return  true;
            case MotionEvent.ACTION_MOVE:
                yMove =event.getRawY();
                 scrolledY = (int) (yLastMove - yMove);
                 //下滑边界
                if ( scrolledY<0 &&getScrollY()<0) {
//                    Log.d("=================","TTTTTTTTTTTTTTTT"+getScrollY());
                   return super.onTouchEvent(event);
                   // 上滑边界
                } else if (   scrolledY>0  &&getScrollY()>(mlist.size()-1)*childView.getHeight()) {
//                    Log.d("=================","BBBBBBBBBBBBBBBBB"+getScrollY());
                  return super.onTouchEvent(event);
                }

            if (getScrollY()<(mlist.size()-1)*childView.getHeight()) {
             if (getScrollY()>=childView.getHeight()/2) t = (getScrollY())/(childView.getHeight())+1;
            if (scrolledY<0&&getScrollY()<=childView.getHeight()/2) t=0;
//                Log.d("=================","SSSSSSSSSSSSSS"+getScrollY());
//                Log.d("=================","SSSSSSSSSSSSSS"+t);
            }
                for (int i =0;i<mlist.size();i++){
                    if (i==t){
                        tlist.get(i).setTextColor(Color.parseColor("#333333"));
                        select =i;
                    }else {
                        tlist.get(i).setTextColor(Color.parseColor("#dddddd"));
                    }
                }
                yLastMove = yMove;
                scrollBy(0, scrolledY);
//                  scroller.startScroll(0, getScrollY(), 0, scrolledY,50);
                invalidate();
                return true;
            case MotionEvent.ACTION_UP:

                if (listener!=null) listener.onGetPoint(select);
                return true;
        }
        return super.onTouchEvent(event);
    }

//    @Override
//    public void computeScroll() {
//        // 第三步,重写computeScroll()方法,并在其内部完成平滑滚动的逻辑
//        if (scroller.computeScrollOffset()) {
//            scrollTo(scroller.getCurrX(), scroller.getCurrY());
//            postInvalidate();
//        }
//    }
    public  void  setCount(ArrayList<String> list){
        mlist  = list;
        if (params==null) params = new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        for (int i = 0;i< mlist.size();i++){
            TextView textView = new TextView(mContext);
            textView.setText(list.get(i));
            if (i==0){textView.setTextColor(Color.parseColor("#333333"));}
            else {
                textView.setTextColor(Color.parseColor("#dddddd"));
            }
            textView.setTextSize(TypedValue.COMPLEX_UNIT_PX,UIUtils.getDimens(R.dimen.size_30px));
            textView.setLayoutParams(params);
            addView(textView);
        }
        invalidate();
    }
    public interface OnPayListener {
        void onGetPoint(int pas);
    }
    public  void  setListener(OnPayListener mlistener){
        this.listener = mlistener;
    }

}

activity调用

      sv.setCount(list);
        sv.setListener(new SelectView.OnPayListener() {
            @Override
            public void onGetPoint(int pas) {
                Toast.makeText(getApplicationContext(),""+pas, Toast.LENGTH_SHORT).show();
            }
        });

地址:
github:https://github.com/liuzhenhang/myview

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值