HorizontalNumberView与seekbar共享滑动的自定义view

这是一个简单的,能与seekbar共享滑动的自定义view

我的博客:详解


简单分析:

  1. 初始化一些参数,设置数据,准备在onDraw方法中连续绘制TextView
  2. 计算出TextView绘制的坐标点,根据左滑还是右滑设置TextView之间间隙,大小,颜色
  3. 将seekbar注入进来,根据对调监听设置当前位置,进行重绘,绘制最新的数组列表


实现难点:

  1. 计算出绘制数组宽度与高度
  2. TextView绘制坐标与方式
  3. seekbar回调,改变哪一些值可以达到预期的滑动效果
  4. 往左滑计算方式,往右滑计算方式
  5. 设置不同状态下TextViewde参数

自定义View分析:

HorizontalNumberView

  1. 首先,初始化构造器与必要参数


        public class HorizontalNumberView extends View implements SeekBar.OnSeekBarChangeListener {

          private static final int SPACE_NUM = 2;

          private static String[] NUMBERS = new String[] {
              "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"
          };

          private static int mNormalTextColor;
          private static int mSelectTextColor;

          private int mNormalTextSize = 32;
          private int mSelectTextSize = 60;

          private int mNumberMax;

          private SeekBar mSeekBar;

          private int mItemHeight;
          private int mItemWidth;

          private int mOffset;
          private int mCurrentProgress = 0;
          private int mBeforeProgress = 0;

          private int mCurrentIndex = 1;

          private double mCurrentValue;

          private Paint mPaint;
          private Paint mSelectPaint;
          private Rect mBounds;

          private OnSeekBarChangeListener mOnSeekBarChangeListener;

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

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

          public HorizontalNumberView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init();
          }

          private void init() {
            mNumberMax = NUMBERS.length + SPACE_NUM;
            mNormalTextColor = getResources().getColor(R.color.number_view_normal_text_color);
            mSelectTextColor = getResources().getColor(R.color.number_view_select_text_color);

            //init text paint
            mPaint = new Paint();
            mPaint.setColor(mNormalTextColor);
            mPaint.setAntiAlias(true);
            mPaint.setTextSize(mNormalTextSize);

            //init color paint
            mSelectPaint = new Paint();
            mSelectPaint.setColor(mSelectTextColor);
            mSelectPaint.setAntiAlias(true);
            mSelectPaint.setTextSize(mSelectTextSize);

            //init text bound rect
            mBounds = new Rect();
          }

  1. 获取PullRelativeLayoutState的状态值,根据它来判断是否处理事件:自己处理,子View处理,不处理等
  2. OnScrollStateChangeListener把ScrollView滚动高度状态回调出去,给外面使用

HeaderFrameLayout



    public class HeaderFrameLayout extends FrameLayout {

        private Scroller mScroller;
        private int mHeight;
        private boolean isOpen;

        public HeaderFrameLayout(Context context) {
            super(context);
            init();
        }

        public HeaderFrameLayout(Context context, AttributeSet attrs) {
            super(context, attrs);
            init();
        }

        public HeaderFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init();
        }

        private void init() {
            mScroller = new Scroller(getContext());
        }

        @Override
        public void computeScroll() {
            if (mScroller.computeScrollOffset()) {
                scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
                postInvalidate();
            }
        }

        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            mHeight = getMeasuredHeight();
        }

        public void setOpen(boolean flag) {
            isOpen = flag;
        }

        public boolean isOpen() {
            return isOpen;
        }

        public void open() {
            if (!isOpen) {
                return;
            }
            smoothScrollTo(0, mHeight, 0, -mHeight, 800);
            isOpen = false;
        }

        private void smoothScrollTo(int startX, int startY,
                                    int dx, int dy, int duration) {
            mScroller.startScroll(startX, startY, dx, dy, duration);
            invalidate();
        }
    }



  1. 计算TextView宽高,注入seekbar设置监听,设置必要参数


          @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            //init text width and height
            mItemHeight = getMeasuredHeight();
            mItemWidth = getMeasuredWidth() / mNumberMax;

            //check set seek bar
            if (mSeekBar == null) {
              throw new RuntimeException("you must call set seekBar method!");
            }
            mSeekBar.setOnSeekBarChangeListener(this);
          }


          public void setSeekBar(SeekBar seekBar) {
            mSeekBar = seekBar;
            mSeekBar.setMax((NUMBERS.length - 1) * 10);//set seekBar max value
          }


          @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
            mCurrentProgress = progress;
            mCurrentIndex = (mCurrentProgress / NUMBERS.length) + 1;
            mCurrentValue = mCurrentIndex + ((mCurrentProgress % 10) / 10.0f);
            invalidate();

            if (mOnSeekBarChangeListener != null) {
              mOnSeekBarChangeListener.onProgressChanged(seekBar, progress, fromUser);
              mOnSeekBarChangeListener.onStateChangeBack(mCurrentProgress, mCurrentIndex,
                  getCurrentValue());
            }
          }



  1. onDraw方法中根据左滑还是右滑设置TextView距离,即实际的位置


          @Override protected void onDraw(Canvas canvas) {
            //start draw text
            for (int i = 0; i < NUMBERS.length; i++) {
              String text = NUMBERS[i];
              int textIndex = i + 1;

              if (mCurrentProgress > 0 && mCurrentProgress > mBeforeProgress) {//left to right slip

                //item % value
                float value = (mCurrentProgress % 10) / 10.0f;

                if (textIndex - mCurrentIndex == 0) {//current text
                  mOffset = (int) (mOffset + mItemWidth - value * mItemWidth);
                }

                if (textIndex - mCurrentIndex == 1) {//current+1
                  mOffset += mItemWidth;
                }

                if (textIndex - mCurrentIndex == 2) {//current+2
                  mOffset = (int) (mOffset + value * mItemWidth);
                }
              } else if (mCurrentProgress > 0 && mCurrentProgress < mBeforeProgress) {//right to left slip

                //item % value
                float value = 1 - ((mCurrentProgress % 10) / 10.0f);

                if (textIndex - mCurrentIndex == 0 && mCurrentIndex != 1) {//current text
                  mOffset += mItemWidth;
                }

                if (textIndex - mCurrentIndex == -1) {//current - 1
                  mOffset = (int) (mOffset + value * mItemWidth);
                }

                if (textIndex - mCurrentIndex == 1 && mCurrentIndex != 1) {//current + 1
                  mOffset = (int) (mOffset + mItemWidth - value * mItemWidth);
                }
              }

              //text width
              int textX = (int) (mItemWidth * 0.5f + i * mItemWidth + mOffset);
              mPaint.getTextBounds(text, 0, text.length(), mBounds);

              //text height
              float textHeight = mBounds.height();
              int textY = (int) (mItemHeight * 0.5f + textHeight * 0.5f);
              float fontHeight = mPaint.getFontMetrics().bottom - mPaint.getFontMetrics().top;
              float posValue = fontHeight / 2 - mPaint.getFontMetrics().descent - 10;

              //text draw
              if (textIndex == mCurrentIndex) {
                canvas.drawText(text, textX, textY + posValue, mSelectPaint);
              } else {
                canvas.drawText(text, textX, textY + posValue, mPaint);
              }
            }

            //reset params
            mOffset = 0;
            mBeforeProgress = mCurrentProgress;
          }




onDraw方法为核心内容,必要的地方都有注释,实现方式可能有很多种,分析就到这里。


再来看一次效果图:

Demo下载:我的Github HorizontalNumberView

10/31/2016 12:49:08 AM

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android中,可以通过自定义SeekBar实现数字滑动功能。首先,在布局文件中定义自定义SeekBar的样式,可以使用ProgressBar来实现。如下所示: ``` <ProgressBar android:id="@+id/customSeekBar" style="@style/Widget.AppCompat.ProgressBar.Horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:max="100" android:progress="50" android:progressDrawable="@drawable/custom_seekbar_progress" android:thumb="@drawable/custom_seekbar_thumb" /> ``` 在drawable文件夹下创建custom_seekbar_progress.xml和custom_seekbar_thumb.xml来定义SeekBar的背景和滑块样式。在custom_seekbar_progress.xml中,可以使用shape和gradient标签来定义进度条的背景样式。在custom_seekbar_thumb.xml中,可以使用shape标签来定义滑块的样式。 接下来,在Activity或Fragment中找到SeekBar的实例,并设置OnSeekBarChangeListener监听器。在监听器中,通过getProgress方法获取SeekBar的进度值,并根据需要进行相应的处理。例如,可以在TextView中显示SeekBar的进度值,如下所示: ``` SeekBar customSeekBar = findViewById(R.id.customSeekBar); final TextView progressTextView = findViewById(R.id.progressTextView); customSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { progressTextView.setText(String.valueOf(progress)); } @Override public void onStartTrackingTouch(SeekBar seekBar) { // 当开始滑动SeekBar时执行的操作 } @Override public void onStopTrackingTouch(SeekBar seekBar) { // 当结束滑动SeekBar时执行的操作 } }); ``` 通过设置OnSeekBarChangeListener监听器,可以在SeekBar滑动时实时更新进度值,并进行相应的处理操作。根据自己的需求,可以在onProgressChanged、onStartTrackingTouch和onStopTrackingTouch方法中添加自定义的逻辑。 以上就是使用自定义SeekBar实现数字滑动的简单方法。可以根据自己的需求进行进一步的定制和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值