精华内容
下载资源
问答
  • 间隔中数目最高的“-”,要比刻度上的“-”少输出个。 思考: 间隔部分是个递归,使用递归输出即可。刻度线上数字按需要的最大刻度来,刻度线做个循环,每循环次调用递归打印间隔。 python版本: ...

    1.打印尺子刻度

    输入类似于

    -----0
    -

    -


    -
    ----
    -

    -

    -

    -
    -----1
    ……
    间隔中数目最高的“-”,要比刻度上的“-”少输出一个。

    思考:
    间隔部分是一个递归,使用递归输出即可。刻度线上数字按需要的最大刻度来,刻度线做一个循环,每循环一次调用递归打印间隔。

    python版本:

    def jiange(m):
        if m==0:
            pass
        else:
            jiange(m-1)
            print ('-'*m)
            jiange(m-1)
    def chizi(n,m):
        for i in range(n+1):
            print ('-'*(m+1)+str(i))
            if i < n:
                jiange(m)   
    n = 5  #总刻度数
    m = 4 #小间隔最大长度
    chizi(n,m)
    
    

    C语言版本

    #include <stdio.h>
    #include <stdlib.h>
    int jiange(int m){
    	if(m==0);
    	else{
    		jiange(m-1);
    		int k;
    		for(k=0;k<m;k++){
    			printf("%c",'-');
    		};
    		printf("\n");
    		jiange(m-1);
    	}
    	return 0;
    }
    int chizi(int n,int m){
    	int i;
    	for(i=0;i<n+1;i++){
    		int w;
    		for(w=0;w<m+1;w++){
    			printf("%c",'-');
    		}
    		printf("%d",i);
    		printf("\n");
    		if(i<n)
    		jiange(m);	
    	}
    	return 0;		
    }
    int main(int argc, char *argv[]) {
    	int m,n;
    	n = 5;//总刻度
    	m = 4;//间隔最大长度
    	chizi(n,m);
    	return 0;
    }
    
    展开全文
  • 应项目需要我这边要定义个播放录音的控件,效果如图:这边先讲一下具体的初版思路吧1、首先我的思路是复杂的问题...组合成一个控件先上一下效果动图下面是上代码时间::首先来画刻度尺的部分刻度尺的部分是...
    应项目需要我这边要定义一个播放录音的控件,效果如图:

    这边先讲一下具体的初版思路吧

    1、首先我的思路是复杂的问题简单化,先把这个控件拆分为:上面的刻度和下面的进度条

    2、刻度可以根据录音的具体时间来画,下面的进度可以继承SeekBar来实现

    3、然后将两个控件的组合在一起放在一个自定义的Relativelayout中,组合成一个控件

    先上一下效果动图


    下面是上代码时间:

    一:首先来画刻度尺的部分

    刻度尺的部分是比较简单的这里我自定义了一个控件继承View然后同onDraw来画出这个刻度尺来

    如果要画出刻度尺则必须知道自定义控件在屏幕的中位置,下面是获取控件在屏幕中具体位置的方法

    下面是获取屏幕宽度的方法
    WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    DisplayMetrics dm = new DisplayMetrics();
    windowManager.getDefaultDisplay().getMetrics(dm);
    screenWidth = dm.widthPixels;
    
    下面是获取视图绝对坐标和相对坐标的方法
    getLocationOnScreen ,计算该视图在全局坐标系中的xy值,(注意这个值是要从屏幕顶端算起,也就是索包括了通知栏的高度)//获取在当前屏幕内的绝对坐标
    getLocationInWindow ,计算该视图在它所在的widnow的坐标xy值,//获取在整个窗口内的绝对坐标 (不是很理解= =)
    getLeft ,getTop,getBottom,getRight,这一组是获取相对在它父亲里的坐标
    如果在ActivityOnCreate()事件输出那些参数,是全为0,要等UI控件都加载完了才能获取到这些。
    
    可在onMeasure中中设置自定义控件的高度
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
    
        int width;
        int height;
    
        if (heightMode == MeasureSpec.EXACTLY) {
            height = heightSize;
        } else {
            height = Math.min(mMinHeight, heightSize);
        }
        width = widthSize;
        setMeasuredDimension(width, height);
    }
    
    控件的宽和高确定好之后接下来就是要画刻度值了,刻度值分为两部分,一部分是水平的横线另一部分是

    竖直的竖杠,横线比较简单至于竖线考虑到录音的时间是从一到无穷大的,于是这竖线的部分就需要分一分了

    首先是1-6s的时候分别画录取时间加一的竖线,大于6的时候则要将对录音的时间进行三等分或者两等分,把时间分的均匀一点就行了,上面的刻度只是个大概的显示所以尽力做到平均就行了。

    线画完之后就要画时间的显示了时间的显示如下

    将时间进行等分的处理函数

    private int courseTime(int record, int time) {
        if (record % 6 == 0) {//整除6则返回6的整倍数
            return record / 6 * time;
        } else if (record % 3 == 0) {//整除3
            if (time % 2 == 0) {//三等分的位置
                return (record / 3) * (time / 2);
            } else {//其他的位置
                return ((record / 3) * ((time + 1) / 2) - ((record / 3) * ((time - 1) / 2))) / 2 + ((record / 3) * ((time - 1) / 2));
            }
        } else if (record % 2 == 0) {//能整除2的数值
            if (time % 3 == 0) {//进行二等分的位置
                return (record / 2) * (time / 3);
            } else {//其他位置
                if ((record / 2) % 3 == 1) {//二等分之后再三等分进行余数的分配
                    if (time < 3) {//前半部分的二等分
                        return (record / 2 / 3 * time);
                    } else {//后半部分的二等分
                        return (record / 2 + record / 2 / 3 * (time - 3));
                    }
                } else {//同上
                    if ((record / 2) % 3 == 2) {
                        if (time < 3) {
                            return (record / 2 / 3 * time + time);
                        } else {
                            return (record / 2 + record / 2 / 3 * (time - 3) + (time - 3));
                        }
                    }
                }
            }
        } else {//质数的分配
            if (time == 0) {
                return 0;
            } else if (time == 3) {
                return record / 2;
            } else if (time == 6) {
                return record;
            } else if (time < 3) {
                if ((record / 2) % 3 == 1) {
                    return (record / 2 / 3 * time);
                } else if ((record / 2) % 3 == 2) {
                    return (record / 2 / 3 * time + time);
                } else {
                    return record / 2 / 3 * time;
                }
            } else {
                if ((record / 2 + 1) % 3 == 1) {
                    return (record / 2 + record / 2 / 3 * (time - 3));
                } else if ((record / 2) % 3 == 2) {
                    return (record / 2 + record / 2 / 3 * (time - 3) + (time - 3));
                } else {
                    return record / 2 + (record / 2 + 1) / 3 * (time - 3);
                }
            }
        }
        return 0;
    }
    

    直接获取绘制字符串的宽度
    textPaint.measureText(str)
    将int值的秒级数转换为时分秒格式
    private String getCourseTime(Integer seconds) {
        int day = seconds / (60 * 60 * 24);//换成天
        int hour = (seconds - (60 * 60 * 24 * day)) / 3600;//总秒数-换算成天的秒数=剩余的秒数    剩余的秒数换算为小时
        int minute = (seconds - 60 * 60 * 24 * day - 3600 * hour) / 60;//总秒数-换算成天的秒数-换算成小时的秒数=剩余的秒数    剩余的秒数换算为分
        int second = seconds - 60 * 60 * 24 * day - 3600 * hour - 60 * minute;//总秒数-换算成天的秒数-换算成小时的秒数-换算为分的秒数=剩余的秒数
        if (hour != 0) {
            return (hour >= 10 ? hour : "0" + hour) + ":" + (minute >= 10 ? minute : "0" + minute) + ":" + (second >= 10 ? second : "0" + second);
        } else if (minute != 0) {
            return (minute >= 10 ? minute : "0" + minute) + ":" + (second >= 10 ? second : "0" + second);
        } else {
            return "00:" + (second >= 10 ? second : "0" + second);
        }
    }
    
    然后直接在几道竖线下画平分的时间就行了,至此刻度尺就制作完毕了。

    二:接下来就是下面的进度条部分了,这个部分我是继承了SeekBar的自定义View制作的

    我们也分为三步

    1、首先是红色的游标

    把默认的游标去除

    android:duplicateParentState="true"
    android:thumb="@null"
    
    要画出完整的图标就必须把进度条的背景放大

    //设置控件的padding 给提示指示图标留出位置
    setPadding(linePadding, (int) Math.ceil(imageHeight) - 30, linePadding, 25);
    

    2、就是进度条的颜色、进度和上面的刻度尺要保持两端相同,我的思路是:①进度条的长度保持和上面的刻度尺长度相同 ②画一个图片来覆盖进度条默认的进度图片 ③画一个半透明的灰色横线来作为进度

    rectSeek = this.getProgressDrawable().getBounds();
    float bm_x = rectSeek.width() * getProgress() / getMax() + (linePadding - (int) Math.ceil(imageWidth) / 2);

    //设置控件的padding 给提示指示图标留出位置
    setPadding(linePadding, (int) Math.ceil(imageHeight) - 30, linePadding, 25);
    

    图片使用一个xml格式的shape做的可以添加起始、中部和结尾的颜色

    canvas.drawBitmap(seekbarThumbBitmap, 0, (int) Math.ceil(imageHeight) - 28, cursorImagePaint);//绘制假的进度条背景色

    canvas.drawLine(0, (int) Math.ceil(imageHeight) - 28, bm_x + (int) Math.ceil(imageWidth) / 2, (int) Math.ceil(imageHeight) - 28, seekbarThumbPaint);

    3、下面一个就是画tag的功能了,这个主要就是画一个红色的矩形

    根据打印tag的时间来确定红色矩形的位置就可以了

    mBarRect.left = getPaddingLeft();
    mBarRect.right = getWidth() - getPaddingRight();
    //final boolean isLayoutRtl = getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
    float cx;
    //float cy = getHeight() / 2 - getPaddingBottom() / 2 - 2;
    float barRectwidth = mBarRect.width() - 50;
    
    cx = mBarRect.left + barRectwidth
            * (mMarks.get(i).postion / (float) mDuration);
        //}
        //radius = getResources().getDimension(R.dimen.panit_line_space) / 3;
    //canvas.drawCircle(cx, cy, radius, mShapePaint);
        //canvas.drawBitmap(mBitmap, cx, cy, mPaintTag);
    canvas.drawRect(cx, (int) Math.ceil(imageHeight) - 28, cx + tagWidth, (int) Math.ceil(imageHeight) - 28 + tagHeight, tagPaint);
    
    至此这个控件就基本结束了,下面就是要合入record的代码中了。
    展开全文
  • 刚好看到刻度尺文章,实现手机屏幕上画刻度尺。 然后就有个疑问:这个现实中的1mm(1毫米)长度与手机像素之间的换算怎么来的呢? 看了下demo代码,发现这样写的: CGFloat sc_w = [[UIScreen ...

    刚好看到一个刻度尺文章,实现手机屏幕上画刻度尺。

     

    然后就有一个疑问:这个现实中的1mm(1毫米)长度与手机像素之间的换算比怎么来的呢?

     

    看了下demo代码,发现这样写的:

        CGFloat sc_w = [[UIScreen mainScreen] bounds].size.width;
        CGFloat sc_h = [[UIScreen mainScreen] bounds].size.height;
        CGFloat sc_s;
        CGFloat ff = [[UIScreen mainScreen] nativeBounds].size.height;
        
        if (ff == 1136) {
            sc_s = 4.0;
        }else if(ff == 1334.0){
            sc_s = 4.7;
        }else if (ff== 1920){
            sc_s = 5.5;
        }else if (ff== 2436){
            sc_s = 5.8;
        }else{
            sc_s = 3.5;
        }
        
        //1mm米的像素点
        pmm = sqrt(sc_w * sc_w + sc_h * sc_h)/(sc_s * 25.4);//mm

    以上这个pmm就是得到的 1mm = pmm像素

     

    何解呢?

    原来是这样:

    1、根据手机像素值:[UIScreen mainScreen] nativeBounds,得到手机大小英寸(4、4.7、5.5等等)

    2、根据手机宽高,根据三角形勾股定律,计算出斜边长度 Xiebian= sqrt(sc_w * sc_w + sc_h * sc_h)

    3、重点是这个25.4,之前一直不理解这个数字,终于发现是因为:1 英寸=2.54 厘米,也就是25.4mm,就能得到一个斜边对应的毫米值:(sc_s * 25.4)

    4、然后就是用得到的斜边长度像素/毫米值,得到1mm对应的像素值了

    5、最后就根据这个值 慢慢画刻度啦~

     

    soga~

     

    转载于:https://www.cnblogs.com/yajunLi/p/8056891.html

    展开全文
  • 具体思路是把个view分成三段,当总长度&amp;amp;amp;gt;... 这次除了无限滚动还我上次写的多了手指滑动速度的判断,去掉了滚动结束自动归位到对应刻度的效果,代码中除了极端情况默认...

    具体思路是把一个view分成三段,当总长度>=40个刻度向左滚动,滚动到2/3的时候view移动到1/3出然后刷新显示的刻度这时为第一页,一次更新页数,当向右滚动的时候滚动且不为第一页则每滚动到1/3处view移动到2/3处。之后在添加一些首页和最后一页的判断。
    这一次除了无限滚动还比我上一次写的多了手指滑动速度的判断,去掉了滚动结束自动归位到对应刻度的效果,代码中除了极端情况默认使用的view显示的刻度为30个,也就是说除了开始和结束,显示的位置始终在10~20之间,向右拖动图示:
    无标题.png

    效果展示:
    GIF.gif

    核心代码

    package com.zqb.scrolldividingrule;
    
    import android.annotation.SuppressLint;
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.os.Handler;
    import android.os.Looper;
    import android.support.annotation.Nullable;
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    import android.view.VelocityTracker;
    import android.view.View;
    import android.widget.Scroller;
    import java.util.ArrayList;
    
    /**
     * 横向滚动的刻度尺
     * Created by zhangqingbin on 2018/1/5.
     */
    
    public class ScrollDividingRuleView extends View {
    
      private Scroller mScroller;
      private Paint mPaint;
      private VelocityTracker mVelocityTracker;
      private OnScrollListener mListener;
      private int mScaleMargin; //刻度间距
      private float mScaleWidth; //总刻度宽度
      private float mTextSize;//文字大小
      private ArrayList<String> mTextList;//刻度文字
      private ArrayList<String> mTotalTextList;//所有的刻度
      private float mLineHeight;//线高度
      private int mRectHeight;//总高度
      private int mScrollLastX;
      private int mInitDistance;//初始距离
      private int mInitPosition;//初始位置
      private int mTextLineMargin;//文字距线的距离
      private int mPage;//当前为复用所在页
      private long mLastInstance;//余数刻度
      private long mStartMoney;//开始金额
      private int mUnit;//每个小格的单位
      private long mFinalMoney;//结束金额
    
      public ScrollDividingRuleView(Context context) {
        this(context, null);
      }
    
      public ScrollDividingRuleView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
      }
    
      public ScrollDividingRuleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setWillNotDraw(false);
        init(context, attrs);
      }
    
      private void init(Context context, @Nullable AttributeSet attrs) {
        if (attrs != null) {
          for (int i = 0; i < attrs.getAttributeCount(); i++) {
            String name = attrs.getAttributeName(i);
            if ("layout_width".equals(name)) {
              String value = attrs.getAttributeValue(i);
              if (value.length() > 2) {
                if (value.endsWith("dp")) {
                  float margin = Float.valueOf(value.substring(0, value.length() - 2));
                  mScaleWidth = Utils.dp2px(context, margin);
                } else {
                  mScaleWidth = Float.valueOf(value.substring(0, value.length() - 2));
                }
              } else if (value.equals("-1") || value.equals("-2") || value.equals("0")) {
                mScaleWidth = 0;
              }
            } else if ("line_height".equals(name)) {
              String value = attrs.getAttributeValue(i);
              if (value.length() > 2) {
                if (value.endsWith("dp")) {
                  mLineHeight =
                      Utils.dp2px(context, Float.valueOf(value.substring(0, value.length() - 2)));
                } else {
                  mLineHeight = Float.valueOf(value.substring(0, value.length() - 2));
                }
              } else {
                mLineHeight = 50;
              }
            } else if ("dividing_text_size".equals(name)) {
              String value = attrs.getAttributeValue(i);
              if (value.length() > 2) {
                if (value.endsWith("sp")) {
                  mTextSize =
                      Utils.sp2px(context, Float.valueOf(value.substring(0, value.length() - 2)));
                } else {
                  mTextSize = Float.valueOf(value.substring(0, value.length() - 2));
                }
              } else {
                mTextSize = 32;
              }
            }
          }
        }
        // 画笔
        mPaint = new Paint();
        //总的高度,因为text的高度和设置的textSize会有误差所以加上20的高度
        mRectHeight = (int) (mLineHeight + mTextSize + mTextLineMargin + 20);
        //初始设置每个刻度间距为30px
        mScaleMargin = 20;
        mTextList = new ArrayList<>();
        mTotalTextList = new ArrayList<>();
        mScroller = new Scroller(context);
      }
    
      @Override
      protected void onDraw(Canvas canvas) {
        mPaint.setColor(Color.GRAY);
        // 抗锯齿
        mPaint.setAntiAlias(true);
        // 设定是否使用图像抖动处理,会使绘制出来的图片颜色更加平滑和饱满,图像更加清晰
        mPaint.setDither(true);
        // 空心
        mPaint.setStyle(Paint.Style.STROKE);
        // 文字居中
        mPaint.setTextAlign(Paint.Align.CENTER);
        onDrawScale(canvas, mPaint); //画刻度
        onDrawLine(canvas, mPaint);//画刻度中间横线
        super.onDraw(canvas);
      }
    
      @Override
      protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int height = MeasureSpec.makeMeasureSpec(mRectHeight, MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, height);
        //初始化开始位置
        mInitDistance = getMeasuredWidth() / 2 - mInitPosition * mScaleMargin * 10;
      }
    
      @SuppressLint("ClickableViewAccessibility")
      @Override
      public boolean onTouchEvent(MotionEvent event) {
        if (mVelocityTracker == null) {
          mVelocityTracker = VelocityTracker.obtain();
        }
        mVelocityTracker.addMovement(event);
        int x = (int) event.getX();
        int startX = 0;
        switch (event.getAction()) {
          case MotionEvent.ACTION_DOWN:
            if (mScroller != null) {//重新初始化fling效果,防止下一次移动有初始速度
              mScroller.fling(mScroller.getFinalX(), mScroller.getFinalY(), 0, 0, 0,
                  (int) (mScaleWidth - mInitPosition * mScaleMargin * 10), 0, 0);
              mScroller.abortAnimation();
            }
            startX = x;
            mScrollLastX = x;
            return true;
          case MotionEvent.ACTION_MOVE:
            int dataX = mScrollLastX - x;
            smoothScrollBy(dataX, 0);
            mScrollLastX = x;
            return true;
          case MotionEvent.ACTION_CANCEL:
          case MotionEvent.ACTION_UP:
            dealActionUp(x - startX);
            return true;
        }
        return super.onTouchEvent(event);
      }
    
      /**
       * 处理手势抬起之后的操作
       *
       * @param i 根据正负判断方向
       */
      private void dealActionUp(int i) {
        mVelocityTracker.computeCurrentVelocity(1000);
        if (mScroller.getFinalX() >= mScaleMargin * 10 * 10 * 2 - 10 * mScaleMargin && i > 0) {
          if (!notifyDataChanged(0)) {
            dealFling();
          }
        } else if (mScroller.getFinalX() <= mScaleMargin * 10 * 10 - 10 * mScaleMargin && i < 0) {
          if (!notifyDataChanged(1)) {
            dealFling();
          }
        } else {
          dealFling();
        }
        long i1 = mPage > 0 ? mPage * 100 : 0;
        if (mListener != null) {
          mListener.onScaleScrollChanged(
              mScroller.getFinalX() / mScaleMargin + mInitPosition * 10 + i1 + mStartMoney);//返回滚动选中的位置
        }
        mVelocityTracker.clear();
        mVelocityTracker.recycle();
        mVelocityTracker = null;
      }
    
      /**
       * 处理手指抬起之后的减速滚动
       */
      private void dealFling() {
        int minX;//最小值
        if (mPage == 0) {
          minX = -mInitPosition * mScaleMargin * 10;
        } else {
          minX = -mInitPosition * mScaleMargin * 10 + mScaleMargin * 10 * 10 - mScaleMargin * 10;
        }
        int maxX;//最大值 根据位置和总数改变
        if (mPage == (mTotalTextList.size() - 20) / 10 - 1 || mTotalTextList.size() < 40) {
          maxX = (int) (mScaleWidth - mInitPosition * mScaleMargin * 10);
        } else {
          maxX = mScaleMargin * 10 * 20 - mScaleMargin * 10;
        }
        mScroller.fling(mScroller.getFinalX(), mScroller.getFinalY(),
            -(int) mVelocityTracker.getXVelocity(), 0, minX, maxX, 0, 0);
      }
    
      private void onDrawScale(Canvas canvas, Paint paint) {
        paint.setAntiAlias(true);
        paint.setTextSize(mTextSize);
        paint.setStyle(Paint.Style.FILL);
        for (int i = 0, k = 0; i < mTextList.size() * 10; i++) {
          if (i < mTextList.size() * 10 - 9) {
            if (i % 10 == 0) { //整值
              paint.setColor(Color.GRAY);
              canvas.drawLine(i * mScaleMargin + mInitDistance, mRectHeight,
                  i * mScaleMargin + mInitDistance, mRectHeight - mLineHeight - mTextLineMargin + 20,
                  paint);
              //整值文字
              paint.setColor(Color.GRAY);
              canvas.drawText(mTextList.get(k), i * mScaleMargin + mInitDistance,
                  mRectHeight - mLineHeight - mTextLineMargin, paint);
              k++;
            } else {
              paint.setColor(Color.GRAY);
              canvas.drawLine(i * mScaleMargin + mInitDistance, mRectHeight,
                  i * mScaleMargin + mInitDistance, mRectHeight - mLineHeight / 2 - mTextLineMargin,
                  paint);
            }
          } else {//画滚动到末尾余数 30200
            if (mPage == (mTotalTextList.size() - 20) / 10 - 1 || mTotalTextList.size() < 40) {
              if ((mLastInstance / mScaleMargin) > 0
                  && (mLastInstance / mScaleMargin) > i - (mTextList.size() * 10 - 9)) {
                paint.setColor(Color.GRAY);
                canvas.drawLine(i * mScaleMargin + mInitDistance, mRectHeight,
                    i * mScaleMargin + mInitDistance, mRectHeight - mLineHeight / 2 - mTextLineMargin,
                    paint);
              }
            }
          }
        }
      }
    
      private void onDrawLine(Canvas canvas, Paint paint) {
        paint.setStrokeWidth(2);
        canvas.drawLine(mInitDistance, mRectHeight, mScaleWidth + mInitDistance, mRectHeight, paint);
      }
    
      /**
       * 使用Scroller的时候需要重写该方法
       */
      @Override
      public void computeScroll() {
        if (mScroller.computeScrollOffset()) {
          scrollTo(mScroller.getCurrX(), 0);
          postInvalidate();
        }
      }
    
      private void smoothScrollBy(int dx, int dy) {
        if (mScroller.getFinalX() >= mScaleMargin * 10 * 10 * 2 - 10 * mScaleMargin
            && dx > 0) {//向左滚动,判断是否滚动到第三部分起始位置
          if (!notifyDataChanged(0)) {
            mScroller.startScroll(mScroller.getFinalX(), mScroller.getFinalY(), dx, dy);
          }
        } else if (mScroller.getFinalX() <= mScaleMargin * 10 * 10 - 10 * mScaleMargin
            && dx < 0) {///向右滚动,判断是否滚动到第二部分开始位置
          if (!notifyDataChanged(1)) {
            mScroller.startScroll(mScroller.getFinalX(), mScroller.getFinalY(), dx, dy);
          }
        } else {//否则根据手指滚动
          mScroller.startScroll(mScroller.getFinalX(), mScroller.getFinalY(), dx, dy);
        }
        postInvalidate();
      }
    
      public interface OnScrollListener {
        void onScaleScrollChanged(long scale);
      }
    
      /**
       * 设置当前位置
       *
       * @param scale 刻度
       */
      public void setNowScale(float scale) {
        float i = scale * mScaleMargin;
        int maxPage = (mTotalTextList.size() - 20) / 10 - 1;
        mPage = 0;
        if (mTotalTextList.size() < 40) {//如果总数小于40 不需要处理多页
          mPage = 0;
          smoothScrollBy((int) (i - mScroller.getFinalX()), 0);
          return;
        } else if (i < mScaleMargin * 10 * 10 * 2 - mScaleMargin * 10) {//判断刻度是否在第一页
          mPage = 0;
        } else if (scale >= 10 * 10 + maxPage * 10 * 10) {//判断刻度是否在最后一页
          mPage = maxPage;
        } else {
          mPage = (int) (scale / 100 - 1);
        }
        if (scale * mUnit >= mFinalMoney) {//如果要设置的刻度大于集合里的最大值 则只滚动到末尾
          mPage = maxPage;
          mTextList.clear();
          for (int j = mPage * 10; j < mTotalTextList.size(); j++) {
            mTextList.add(mTotalTextList.get(j));
          }
          mScaleWidth = (mTextList.size() * 10 - 10) * mScaleMargin + mLastInstance;
          smoothScrollBy((int) (mScaleWidth - mScroller.getFinalX()), 0);
        } else {
          if (mPage == (mTotalTextList.size() - 20) / 10 - 1) {//判断是否是最后一页
            if (mTotalTextList.size() >= mPage * 10 + 30) {
              mTextList.clear();
              for (int j = mPage * 10; j < mTotalTextList.size(); j++) {//更新刻度
                mTextList.add(mTotalTextList.get(j));
              }
              mScaleWidth = (mTextList.size() * 10 - 10) * mScaleMargin + mLastInstance;//加上余数的宽度
              smoothScrollBy((int) (i - ((mPage + 1) * 10 * 10 * mScaleMargin) + 10 * 10 * mScaleMargin
                  - mScroller.getFinalX()), 0);
            }
          } else {
            if (mTotalTextList.size() >= mPage * 10 + 30) {
              mTextList.clear();
              for (int j = mPage * 10; j < mPage * 10 + 30; j++) {//更新刻度
                mTextList.add(mTotalTextList.get(j));
              }
              mScaleWidth = (mTextList.size() * 10 - 10) * mScaleMargin;
              smoothScrollBy((int) (i - ((mPage + 1) * 10 * 10 * mScaleMargin) + 10 * 10 * mScaleMargin
                  - mScroller.getFinalX()), 0);
            }
          }
        }
      }
    
      /**
       * 初始化数据
       *
       * @param startMoney 开始金额
       * @param finalMoney 最终金额
       * @param unit 每个刻度单位
       * @param listener 滚动监听
       */
      public void bindMoneyData(int startMoney, int finalMoney, int unit, OnScrollListener listener) {
        if (mTotalTextList != null && mTotalTextList.size() > 0) {
          refresh(startMoney, finalMoney);
        } else {
          mPage = 0;
          mUnit = unit;
          mStartMoney = startMoney / unit;
          mTextList = new ArrayList<>();
          mTotalTextList = new ArrayList<>();
          mFinalMoney = finalMoney;
          for (int i = 0; i < (finalMoney - startMoney) / (unit * 10) + 1; i++) {
            if (i < 30 || (finalMoney - startMoney) / (unit * 10) + 1 < 40) {//当前显示刻度数
              mTextList.add(String.valueOf(i * unit * 10 + startMoney));
            }
            mTotalTextList.add(String.valueOf(i * unit * 10 + startMoney));//总共刻度数
          }
          mLastInstance = ((finalMoney - startMoney) % (unit * 10)) / 100 * mScaleMargin;//余数刻度
          if (mTotalTextList.size() < 40) {
            mScaleWidth = (mTextList.size() * 10 - 10) * mScaleMargin + mLastInstance;
          } else {
            mScaleWidth = (mTextList.size() * 10 - 10) * mScaleMargin;
          }
          mListener = listener;
          postInvalidate();
        }
      }
    
      /**
       * 判断更新当前页
       *
       * @param type 0左滑  1右滑
       * @return 是否处理了滚动到对应页
       */
      private boolean notifyDataChanged(int type) {
        if (mTotalTextList.size() < 40) {
          return false;
        }
        if (type == 0) {//向前移动
          if ((mTotalTextList.size() - 20) / 10 - 1 == 0) {
            return false;
          }
          if (mPage < (mTotalTextList.size() - 20) / 10 - 1) {
            mPage++;
            if (mPage == (mTotalTextList.size() - 20) / 10 - 1) {
              if (mTotalTextList.size() >= mPage * 10 + 30) {
                mTextList.clear();
                for (int i = mPage * 10; i < mTotalTextList.size(); i++) {
                  mTextList.add(mTotalTextList.get(i));
                }
                mScaleWidth = (mTextList.size() * 10 - 10) * mScaleMargin + mLastInstance;
                mScroller.startScroll(mScroller.getFinalX(), mScroller.getFinalY(),
                    -mScroller.getFinalX() + mScaleMargin * 10 * 10 - 10 * mScaleMargin,
                    mScroller.getFinalY());
                return true;
              }
            } else {
              if (mTotalTextList.size() >= mPage * 10 + 30) {
                mTextList.clear();
                for (int i = mPage * 10; i < mPage * 10 + 30; i++) {
                  mTextList.add(mTotalTextList.get(i));
                }
                mScaleWidth = (mTextList.size() * 10 - 10) * mScaleMargin;
                mScroller.startScroll(mScroller.getFinalX(), mScroller.getFinalY(),
                    -mScroller.getFinalX() + mScaleMargin * 10 * 10 - 10 * mScaleMargin,
                    mScroller.getFinalY());
                return true;
              }
            }
          }
        } else {//向后移动
          if (mPage > 0) {
            mPage--;
            if (mTotalTextList.size() > mPage * 10 + 30) {
              mTextList.clear();
              for (int i = mPage * 10; i < mPage * 10 + 30; i++) {
                mTextList.add(mTotalTextList.get(i));
              }
              mScaleWidth = (mTextList.size() * 10 - 10) * mScaleMargin;
              mScroller.startScroll(mScroller.getFinalX(), mScroller.getFinalY(),
                  mScaleMargin * 10 * 10, mScroller.getFinalY());
              return true;
            }
          }
        }
        return false;
      }
    
      /**
       * 刷新操作
       */
      public void refresh(final int startMoney, final int finalMoney) {
        new Thread(new Runnable() {//防止数据量过多导致阻塞主线程
          @Override
          public void run() {
            mPage = 0;
            mStartMoney = startMoney / mUnit;
            mFinalMoney = finalMoney;
            mTextList.clear();
            mTotalTextList.clear();
            for (int i = 0; i < (finalMoney - startMoney) / (mUnit * 10) + 1; i++) {
              if (i < 30 || (finalMoney - startMoney) / (mUnit * 10) + 1 < 40) {//当前显示刻度数
                mTextList.add(String.valueOf(i * mUnit * 10 + startMoney));
              }
              mTotalTextList.add(String.valueOf(i * mUnit * 10 + startMoney));//总共刻度数
            }
            mLastInstance = ((finalMoney - startMoney) % (mUnit * 10)) / 100 * mScaleMargin;//余数刻度
            if (mTotalTextList.size() < 40) {
              mScaleWidth = (mTextList.size() * 10 - 10) * mScaleMargin + mLastInstance;
            } else {
              mScaleWidth = (mTextList.size() * 10 - 10) * mScaleMargin;
            }
            new Handler(Looper.getMainLooper()).post(new Runnable() {
              @Override
              public void run() {
                postInvalidate();
              }
            });
          }
        });
      }
    
      /**
       * 设置每个刻度间距
       *
       * @param margin 间距
       * @return 返回当前view 链式编程
       */
      public ScrollDividingRuleView setScaleMargin(int margin) {
        mScaleMargin = margin;
        mRectHeight = (int) (mLineHeight + mTextSize + mTextLineMargin + 20);
        return this;
      }
    
      /**
       * 设置文字和刻度线的间距
       */
      public ScrollDividingRuleView setTextLineMargin(int textLineMargin) {
        mTextLineMargin = textLineMargin;
        mRectHeight = (int) (mLineHeight + mTextSize + mTextLineMargin + 20);
        return this;
      }
    
      /**
       * 设置文字和刻度线的间距(滚动有问题)
       */
      public ScrollDividingRuleView setInitPosition(int position) {
        mInitPosition=position;
        return this;
      }
    }
    

    调用代码:

    final ScrollDividingRuleView scrollDividingRuleView = findViewById(R.id.scroll_dividing_rule_view);
        editText = findViewById(R.id.edit_text);
        scrollDividingRuleView.bindMoneyData(0, 100000, 100,
            new ScrollDividingRuleView.OnScrollListener() {
              @Override public void onScaleScrollChanged(long scale) {
                isDividingScroll=true;//防止滚动的时候和edittext绑定数据出问题
                editText.setText(String.valueOf(scale*100));
                editText.setSelection(String.valueOf(scale*100).length());
              }
            });
    
        scrollDividingRuleView.setScaleMargin(30)
            .setTextLineMargin(30);
    
        editText.addTextChangedListener(new TextWatcher() {
          @Override
          public void beforeTextChanged(CharSequence s, int start, int count, int after) {
          }
    
          @Override
          public void onTextChanged(CharSequence s, int start, int before, int count) {
          }
    
          @Override
          public void afterTextChanged(Editable s) {
            String money = s.toString().trim();
            if (money.length() > 0 && !TextUtils.isEmpty(money)) {
              float i = Float.parseFloat(money);
                if (!isDividingScroll) {
                  scrollDividingRuleView.setNowScale(i >= 100? i / 100 : 0);
                } else {
                  isDividingScroll = false;
                }
              }
          }
        });

    布局代码:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.zqb.scrolldividingrule.MainActivity">
        <com.zqb.scrolldividingrule.ScrollDividingRuleView
            android:layout_marginTop="50px"
            android:id="@+id/scroll_dividing_rule_view"
            android:layout_width="match_parent"
            android:layout_marginLeft="30px"
            android:layout_marginRight="30px"
            android:layout_height="wrap_content"
            app:line_height="80px"
            app:dividing_text_size="30px"/>
        <View
            android:layout_marginTop="90px"
            android:background="@color/colorAccent"
            android:layout_centerHorizontal="true"
            android:layout_width="1px"
            android:layout_height="120px"/>
        <EditText
            android:inputType="number"
            android:id="@+id/edit_text"
            android:layout_marginLeft="10dp"
            android:textSize="25sp"
            android:layout_marginTop="300px"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    </RelativeLayout>
    

    下载地址

    如果显示30个有卡顿的话,可以自己调整。
    注:paint.setStyle(Paint.Style.FILL); 防止画出来的文字带空心
    paint.measureText(“123”); 获取文字显示的宽度

    展开全文
  • 昨天帮老婆弄个医用的刻度尺,很是花了一番功夫,最终在做了近俩小时没弄出来准备睡觉的瞬间想到了怎么做。考虑到在网上搜索到的教程中只有篇是使用Firework做的,但是实际应用中,在排版打印方面的便利性上,...
  • 、千分尺的正确使用方法()、千分尺的简介千分尺是常用的精密测量量具,主要的优点是它的结构设计稳定,因此它的测量精度游标卡尺高得多,所以千分尺游标卡尺更适合测量精度和光洁度高的物件。常见的千分尺如...
  • 解决的问题:有时,个或几个点大部分数据大得多。在这种情况下,需要将轴的刻度设置为对数刻度,而不是普通刻度。这就是对数比例。在Matplotlib中,可以通过设置axes对象的xscale或vscale属性为’log’来实现...
  • 关注并私信“归纳总结”,获取完整打印版和答案:专题概述、游标卡尺1....不管游标上有多少个小等分刻度,它的刻度部分的总长度上的同样多的小等分刻度少1 mm.常见的游标卡尺的游标...
  • + 首先它有刻度尺代表了时间段(也可以是别的什么),并且可以看到完整的刻度尺屏幕宽度大的,因此肯定需要可以左右滑动。 + 其次,可以有不可选的区域(gif中灰色块)和选中的区域(gif中蓝色块),点击...
  • 请你开动脑筋,想出办法测量身边难以用刻度尺直接测量的长度,比一比看一看哪位同学测量的物体最新奇,办法最有创意。[优秀实验成果展]1.德强学校七年十八班——黄子恒同学一、实验思路因为自行车走过的路程满足以下...
  • okvis 预积分

    2020-05-13 15:18:19
    Imu和视觉的融合部分,imu因为数据频率视觉高很多,所以在融合的过程像是把带有刻度的尺子(多个imu数据)去测量两个点(关键帧i、j)之间的距离。这需要imu数据的时间要能够包住视觉的时间。 如图1所示,两个...
  • 复杂度:粗略衡量算法好坏的刻度尺(工具) 两个维度:快慢 时间复杂度 (重点) 使用空间的情况空间复杂度 时间复杂度: 直接用运行时间衡量不现实,测试环境多变,不好控制变量 前提:如果指定CPU的情况下...
  • 、前言 这个控件写了很久了,是最早期的批控件中的个,和温度计...由于当时的qpainter绘制功底还不够如火纯情,所以当时的刻度尺部分都是定死的字体大小,并不会随着控件变化而增大。 二、实现的功能 1:可...
  • 初识数据结构

    2019-07-22 15:34:21
    复杂度 :粗略衡量算法好坏的刻度尺。(工具) 两个维度 : 快慢 时间复杂度 使用空间的情况 空间复杂度 时间复杂度: 之间利用允许时间衡量不现实。测试环境多变,不好控制变量。 前提:如果指定的cpu的情况...
  • 【数据结构】复杂度

    2019-12-02 17:15:01
    复杂度:粗略衡量算法好坏的刻度尺(工具) 两个维度: 时间和空间 时间复杂度(重点) 快慢 空间复杂度 使用空间的情况 时间复杂度: 直接利用允许时间衡量不现实,测试环境多变,不好控制变量 前提:如果指定...
  •  高考是知识、能力、心理、信心、体力的场综合考试. 孩子,你是爸爸妈妈生命的延续,也是爸爸妈妈未来的希望,你的一举动时刻牵动着爸爸妈妈的心。今后的路还很长,你要勇敢地面对任何挑战,爸爸...
  • 课前复习:二分查找 时间复杂度(O(N)) 空间复杂度:范围最大的长度复杂度:粗略衡量算法好坏的刻度尺(工具)两个维度:快慢 时间复杂度(重点)使用空间的情况 空间复杂度时间复杂度:直接利用允许时间衡量不现实...
  • **→粗略衡量算法好坏的刻度尺(工具)<指的是最坏情况下的时间复杂度> 两个维度: 快慢 : 时间复杂度 使用空间情况 : 空间复杂度 1.时间复杂度:算法的基本操作的执行次数为算法的时间复杂度 1>....
  •  (2)认识尺子,学会用尺子测量物体的长度,特别是不从0刻度开始测量时的注意事项。 第二节x老师的《认识平均数》。于老师先通过两名选手以前比赛成绩,让学生决定应该派谁上场。有同学说总分,但两人场次有...
  • 祝高考成功贺词.doc

    2021-01-18 16:51:39
    高考试卷是刻度不均匀的尺子:对于你自己来说,难题的分值不一定高。 6. 高考得高分的秘诀就是少丢分! 7. 面对高考试卷的“前120分”,志在必得,细大不捐;“后30分”多多益善,失不足惜。 8. 高考试卷的...
  • 2020高三励志标语口号_高三班级横幅正能量句子精选100句 高考试卷是刻度不均匀的尺子:对于你自己来说,难题的分值不一定高。今天小编就给大家整理了高三励志标语口号_高三班级横幅正能量句子,希望对大家的工作...
  •  游标卡尺由于是种精密地丈量仪器,那么其生产的厂家对卡游标尺本身的刻度打标要求就非常高。现代化生产中必须要考虑生产效率,而生产效率又与操纵方便、生产速度等因素相关。本文设计了采用PC

空空如也

空空如也

1 2
收藏数 35
精华内容 14
关键字:

一比一刻度尺