1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        Android仿京東金融的數(shù)值滾動(dòng)尺功能

        共 10243字,需瀏覽 21分鐘

         ·

        2021-03-01 13:13

        現(xiàn)在就講講自定義數(shù)值滾動(dòng)尺,這個(gè)用的還是挺多的,例如京東金融的通過滾動(dòng)尺選擇金額等,而這次就是高仿京東金融的數(shù)值滾動(dòng)尺。首先看看下效果圖,如下:



        首先先給你們各個(gè)變量的含義,以免在后面的講解中不知變量的意思,代碼如下:

        //最小值private int minValue;//最大值private int maxValue;//當(dāng)前值private int currentValue;//最小單位值private int minUnitValue;//最小當(dāng)前值private int minCurrentValue;//字體大小private int textSize;//字體顏色private int textColor;//線顏色private int dividerColor;//指示線顏色private int indicatrixColor;//畫線的畫筆private Paint linePaint;//控價(jià)的寬度private int slideRulerWidth=0;//滑動(dòng)的寬度private int rollingWidth;//屏幕的寬private int wrapcontentWidth;//屏幕的高private int wrapcontentHeight;//一屏顯示Itemprivate int showItemSize;//刻度和數(shù)值的間距private int marginCursorData;//長刻度的大小private int longCursor;//短刻度的大小private int shortCursor;//計(jì)算每個(gè)刻度的間距private int marginWidth=0;//數(shù)據(jù)回調(diào)接口private SlideRulerDataInterface slideRulerDataInterface;//正在滑動(dòng)狀態(tài)private int isScrollingState=1;//快速一滑private int fastScrollState=2;//結(jié)束滑動(dòng)private int finishScrollState=3;
        private GestureDetector mDetector;private Display display =null;private Scroller scroller;
        public SlideRuler(Context context, AttributeSet attrs, int defStyleAttr) { super(context,attrs,defStyleAttr); display=((WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); //屏幕寬高 wrapcontentWidth=display.getWidth(); wrapcontentHeight=display.getHeight(); //初始化自定義的參數(shù) TypedArray typedArray=context.getTheme().obtainStyledAttributes(attrs,R.styleable.slideruler,defStyleAttr,0); textSize = typedArray.getDimensionPixelSize(R.styleable.slideruler_textSize,(int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_SP,15,getResources().getDisplayMetrics())); textColor=typedArray.getColor(R.styleable.slideruler_textColor,Color.DKGRAY); dividerColor=typedArray.getColor(R.styleable.slideruler_dividerColor,Color.BLACK); indicatrixColor=typedArray.getColor(R.styleable.slideruler_indicatrixColor,Color.BLACK); minValue=typedArray.getInteger(R.styleable.slideruler_min_value,0); maxValue=typedArray.getInteger(R.styleable.slideruler_max_value,199000); currentValue=typedArray.getInteger(R.styleable.slideruler_current_value,10000); minUnitValue=typedArray.getInteger(R.styleable.slideruler_min_unitValue,1000); minCurrentValue=typedArray.getInteger(R.styleable.slideruler_min_currentValue,1000); showItemSize=typedArray.getInteger(R.styleable.slideruler_show_itemSize,30); marginCursorData=typedArray.getDimensionPixelSize(R.styleable.slideruler_margin_cursor_data,(int)TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_SP,10,getResources().getDisplayMetrics())); longCursor=typedArray.getDimensionPixelSize(R.styleable.slideruler_longCursor,(int)TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_SP,25,getResources().getDisplayMetrics())); shortCursor=typedArray.getDimensionPixelSize(R.styleable.slideruler_shortCursor,(int)TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_SP,15,getResources().getDisplayMetrics()));
        scroller=new Scroller(context); mDetector=new GestureDetector(context,myGestureListener);
        //初始化Paint linePaint=new Paint(); linePaint.setAntiAlias(true); linePaint.setTextAlign(Paint.Align.CENTER); linePaint.setStyle(Paint.Style.STROKE); linePaint.setTextSize(textSize); //檢查當(dāng)前值是不是正確值 checkCurrentValue();    }


        其次自定義View也好自定義控價(jià)也好

        protected void onMeasure(int widthMeasureSpec, int heigh)


        也是蠻重要的所以照例也講講,用來確定控件的大小,代碼如下:

         @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        int widthModel=MeasureSpec.getMode(widthMeasureSpec);        int heightModel=MeasureSpec.getMode(heightMeasureSpec);        int widthSize=MeasureSpec.getSize(widthMeasureSpec);            int heightSize=MeasureSpec.getSize(heightMeasureSpec);        int width;        int height;        if(widthModel==MeasureSpec.EXACTLY){            width=widthSize;        }else{            width=wrapcontentWidth;        }        if(heightModel==MeasureSpec.EXACTLY){            height=heightSize;        }else{            height=(getPaddingBottom()+getPaddingTop()+(wrapcontentHeight/4));        }        setMeasuredDimension(width,height);    }


        代碼的意思也很簡單,當(dāng)MeasureSpec里的specMode類型是EXACTLY時(shí),即設(shè)置了明確的值或者是MATCH_PARENT時(shí),就直接把MeasureSpec.getSize()的值賦進(jìn)去,如果不是即為WARP_CONTENT時(shí),就直接賦給屏幕的寬高??丶膶捀叨际峭粯拥淖龇?。


        當(dāng)控件大小確定之后,我們再利用

        protected void onSizeChanged(int w, int h, int oldw, int oldh)


        進(jìn)行一些變量的賦值,代碼如下:

         @Override    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        //計(jì)算每個(gè)刻度的間距        marginWidth=getWidth()/showItemSize;        //開始時(shí)的距離        rollingWidth=(int)(marginWidth*cursorNum());        //整個(gè)控件的寬度        slideRulerWidth=(maxValue/minUnitValue)*marginWidth;        super.onSizeChanged(w, h, oldw, oldh);    }


        到此我們就可以在onDraw(Canvas canvas)方法里畫出初始的界面,而以后的動(dòng)態(tài)只是通過不斷的改變數(shù)值再進(jìn)行繪畫而已,代碼如下:

        @Overrideprotected void onDraw(Canvas canvas){    //畫最基礎(chǔ)的兩條線    drawBaseView(canvas);    //畫初始的界面    drawBaseLine(canvas);}
        //畫最基礎(chǔ)的兩條線public void drawBaseLine(Canvas canvas){ //畫中間的線 linePaint.setColor(indicatrixColor); canvas.drawLine(getWidth()/2,0,getWidth()/2,getHeight(),linePaint); //畫底部的直線 linePaint.setColor(dividerColor); canvas.drawLine(0,getHeight(),slideRulerWidth,getHeight(),linePaint);}
        //畫初始的界面public void drawBaseView(Canvas canvas){ //整數(shù)刻度的個(gè)數(shù) int integerWidth= (int)Math.rint((currentValue-minValue)/minUnitValue); //剩余不整一個(gè)刻度的數(shù)值 int residueWidth=(currentValue-minValue)%minUnitValue; //開始畫圖的X軸位置 int startCursor=(getWidth()/2)-(marginWidth*integerWidth)-(int)(marginWidth*(float)residueWidth/minUnitValue); for(int i=0;i<(maxValue/minUnitValue)+1;i++){ float xValue=startCursor+(marginWidth*i); if(i%10==0){ //畫長刻度 linePaint.setColor(textColor); canvas.drawText((minCurrentValue*i)+"",xValue,getHeight()-longCursor-marginCursorData,linePaint); linePaint.setColor(dividerColor); canvas.drawLine(xValue,getHeight(),xValue,getHeight()-longCursor,linePaint); }else{ //畫短刻度 canvas.drawLine(xValue,getHeight(),xValue,getHeight()-shortCursor,linePaint); } }    }    


        在drawBaseView()方法里,也很簡單,就是在二分之一寬度,畫一條直線,然后在控價(jià)的底部畫出寬度為整個(gè)控件的寬度的底線。接著在

        drawBaseView(Canvas canvas)

        方法里


        1. 首先用當(dāng)前值(currentValue)-最小值(minValue)之后再除于最小單位值(minUnitValue)以獲取整數(shù)刻度的個(gè)數(shù)


        2. 因?yàn)橛杏鄶?shù)的情況,我們再當(dāng)前值(currentValue)-最小值(minValue)之后求余與最小單位值(minUnitValue)以獲取余數(shù)


        3. 接著我們要獲取我們畫圖的X軸開始的位置,因?yàn)樽钚≈抵荒芑街虚g,所以開始的位置為控件一半的寬度(getWidth()/2)
          減去計(jì)算每個(gè)刻度的間距(marginWidth)乘以整數(shù)刻度的個(gè)數(shù)(integerWidth)即
          marginWidth*integerWidth再減去余數(shù)對應(yīng)所產(chǎn)生的X軸距離即 :

        (int)(marginWidth*(float)residueWidth/minUnitValue)

        4、再通過For循環(huán)刻度的個(gè)數(shù),不同的進(jìn)行刻度的繪畫,當(dāng)i%10==0時(shí)即為一個(gè)大的單位刻度否者為一個(gè)小的單位刻度,具體代碼我上面已有注釋,原理和畫中間線一直就不在贅述。


        到此我們就已經(jīng)把自定義控價(jià)靜態(tài)的部分寫完了,效果如下:



        接著我們用GestureDetector綁定手勢事件,根據(jù)回調(diào)手勢事件的方法來改變數(shù)據(jù)和刷新頁面,在GestureDetector里,我們只會(huì)回調(diào):

        //手指在觸摸屏上滑動(dòng)public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
        //手指在觸摸屏上迅速移動(dòng),并松開的動(dòng)作public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)

        這兩個(gè)方法就可以了。


        具體代碼如下:

        private GestureDetector.SimpleOnGestureListener myGestureListener =new  GestureDetector.SimpleOnGestureListener(){        @Override        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {            //滑動(dòng)刷新UI            updateView(rollingWidth+(int)distanceX,isScrollingState);            return true;        }        @Override        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {            //快速滑動(dòng)的動(dòng)畫            scroller.fling(rollingWidth,0,(int)(-velocityX/1.5),0,0,(maxValue/minUnitValue)*marginWidth,0,0);            return true;        }    };
        //動(dòng)態(tài)更新滑動(dòng)Viewpublic void updateView(int srcollWidth,int action){ if(action==isScrollingState){ //正在滑動(dòng)狀態(tài)(onScroll()) rollingWidth=srcollWidth; float itemNum=(float)srcollWidth/marginWidth; currentValue=(int)(minUnitValue*itemNum); }else if(action==fastScrollState){ //快速一滑(onFling()) rollingWidth=srcollWidth; int itemNum=(int)Math.rint((float)rollingWidth/marginWidth); currentValue=(minUnitValue*itemNum); }else if(action==finishScrollState){ //結(jié)束滑動(dòng)(ACTION_UP) int itemNum=(int)Math.rint((float)rollingWidth/marginWidth); currentValue=minUnitValue*itemNum; } //判斷是否在最小選擇值 if(currentValue<=minCurrentValue){ rollingWidth=(minCurrentValue/minUnitValue)*marginWidth; currentValue=minCurrentValue; } //判斷是否在最大值 if(currentValue>=maxValue){ rollingWidth=marginWidth*allCursorNum(); currentValue=maxValue; } //回調(diào)數(shù)值 if(slideRulerDataInterface!=null){ slideRulerDataInterface.getText(currentValue+""); } invalidate();



        1.當(dāng)我們滑動(dòng)我們的控件是,就會(huì)回調(diào)GestureDetector里的onScroll()方法,然后rollingWidth+(int)distanceX即當(dāng)前滑動(dòng)的寬度(rollingWidth)加上滑動(dòng)產(chǎn)生的寬度(distanceX)為動(dòng)態(tài)產(chǎn)生的寬度,再除于計(jì)算每個(gè)刻度的間距(marginWidth)從而得到刻度的數(shù)量,有了刻度的數(shù)量即可得到當(dāng)前值

        currentValue=(int)(minUnitValue*itemNum);

        有了當(dāng)前值調(diào)用invalidate();刷新onDraw()即可完成連續(xù)滑動(dòng)時(shí)動(dòng)態(tài)繪制。



        2.當(dāng)我們快速一劃時(shí),就會(huì)回調(diào)GestureDetector里的onFling()方法,在方法里用

        scroller.fling(rollingWidth,0,(int)(-velocityX/1.5),0,0,(maxValue/minUnitValue)*marginWidth,0,0);

        以實(shí)現(xiàn)滑動(dòng)有一個(gè)好的動(dòng)畫效果,此時(shí)在如下代碼里:

          @Override  public void computeScroll() {    if(scroller.computeScrollOffset()){        //快滑刷新UI        updateView(scroller.getCurrX(),fastScrollState);    }  }
        scroller.computeScrollOffset()==true;而scroller.getCurrX()

        就相當(dāng)于為動(dòng)態(tài)產(chǎn)生的滑動(dòng)寬度剩下的也是調(diào)用updateView()方法不斷的刷新,當(dāng)

        scroller.computeScrollOffset()==false

        就滑動(dòng)動(dòng)畫結(jié)束了。



        3.最后當(dāng)我們滑動(dòng)結(jié)束手指抬起時(shí):

         @Override    public boolean onTouchEvent(MotionEvent event) {        switch(event.getAction()){            case MotionEvent.ACTION_UP:                updateView(0,finishScrollState);            default:                mDetector.onTouchEvent(event);                break;        }        return true;    }


        我們也要掉updateView(),以保持滑動(dòng)的最后結(jié)構(gòu)都指在指針上。


        源碼地址:

        https://github.com/gaojuanjuan/MaterialDesign_V7

        到這里就結(jié)束啦


        點(diǎn)擊這里留言交流哦


        瀏覽 59
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評論
        圖片
        表情
        推薦
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            黑人巨大翔田千里AⅤ | 91精品国产91综合久久蜜臀 | 亚洲最新免费视频 | 国产无码乱伦视频 | 欧美午夜福利在线观看 | 18禁福利网站 | 婷婷乱伦视频 | 日韩一品道 | 最新版中文官网资源 | 免费又黄又爽又色的视频 |