zoukankan      html  css  js  c++  java
  • android 双向滑动 seekbar

    实现原理:
    1、自定义View,在onDraw(Canvas canvas)中,画出2个Drawable滑动块,2个Drawable滑动条,2个Paint(text)
    2、监听onTouchEvent()事件,修改滑块和滑动条的坐标,调用invalidate()来更新界面
    使用方法
    1、自定义View   SeekBarPressure.class
    package xxxxxxxxx
    
    import android.content.Context;
    import android.content.res.Resources;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.drawable.Drawable;
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    import android.view.View;
    import java.math.BigDecimal;
    import com.zjcpo.mobileapp.R;
    
    public class SeekBarPressure extends View {
        private static final String TAG = "SeekBarPressure";
        private static final int CLICK_ON_LOW = 1;      //点击在前滑块上
        private static final int CLICK_ON_HIGH = 2;     //点击在后滑块上
        private static final int CLICK_IN_LOW_AREA = 3;
        private static final int CLICK_IN_HIGH_AREA = 4;
        private static final int CLICK_OUT_AREA = 5;
        private static final int CLICK_INVAILD = 0;
        /*
         * private static final int[] PRESSED_STATE_SET = {
         * android.R.attr.state_focused, android.R.attr.state_pressed,
         * android.R.attr.state_selected, android.R.attr.state_window_focused, };
         */
        private static final int[] STATE_NORMAL = {};
        private static final int[] STATE_PRESSED = {
                android.R.attr.state_pressed, android.R.attr.state_window_focused,
        };
        private Drawable hasScrollBarBg;        //滑动条滑动后背景图
        private Drawable notScrollBarBg;        //滑动条未滑动背景图
        private Drawable mThumbLow;         //前滑块
        private Drawable mThumbHigh;        //后滑块
    
        private int mScollBarWidth;     //控件宽度=滑动条宽度+滑动块宽度
        private int mScollBarHeight;    //滑动条高度
    
        private int mThumbWidth;        //滑动块宽度
        private int mThumbHeight;       //滑动块高度
    
        private double mOffsetLow = 0;     //前滑块中心坐标
        private double mOffsetHigh = 0;    //后滑块中心坐标
        private int mDistance = 0;      //总刻度是固定距离 两边各去掉半个滑块距离
    
        private int mThumbMarginTop = 30;   //滑动块顶部距离上边框距离,也就是距离字体顶部的距离
    
        private int mFlag = CLICK_INVAILD;
        private OnSeekBarChangeListener mBarChangeListener;
    
    
        private double defaultScreenLow = 0;    //默认前滑块位置百分比
        private double defaultScreenHigh = 100;  //默认后滑块位置百分比
    
        private boolean isEdit = false;     //输入框是否正在输入
    
        public SeekBarPressure(Context context) {
            this(context, null);
        }
    
        public SeekBarPressure(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public SeekBarPressure(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
    //        this.setBackgroundColor(Color.BLACK);
    
            Resources resources = getResources();
            notScrollBarBg = resources.getDrawable(R.drawable.seekbarpressure_bg_progress);
            hasScrollBarBg = resources.getDrawable(R.drawable.seekbarpressure_bg_normal);
            mThumbLow = resources.getDrawable(R.drawable.seekbarpressure_thumb);
            mThumbHigh = resources.getDrawable(R.drawable.seekbarpressure_thumb);
    
            mThumbLow.setState(STATE_NORMAL);
            mThumbHigh.setState(STATE_NORMAL);
    
            mScollBarWidth = notScrollBarBg.getIntrinsicWidth();
            mScollBarHeight = notScrollBarBg.getIntrinsicHeight();
    
            mThumbWidth = mThumbLow.getIntrinsicWidth();
            mThumbHeight = mThumbLow.getIntrinsicHeight();
    
        }
    
        //默认执行,计算view的宽高,在onDraw()之前
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            int width = measureWidth(widthMeasureSpec);
    //        int height = measureHeight(heightMeasureSpec);
            mScollBarWidth = width;
            mOffsetHigh = width - mThumbWidth / 2;
            mOffsetLow = mThumbWidth / 2;
            mDistance = width - mThumbWidth;
    
            mOffsetLow = formatDouble(defaultScreenLow / 100 * (mDistance ))+ mThumbWidth / 2;
            mOffsetHigh = formatDouble(defaultScreenHigh / 100 * (mDistance)) + mThumbWidth / 2;
            setMeasuredDimension(width, mThumbHeight + mThumbMarginTop+2);
        }
    
    
        private int measureWidth(int measureSpec) {
            int specMode = MeasureSpec.getMode(measureSpec);
            int specSize = MeasureSpec.getSize(measureSpec);
            //wrap_content
            if (specMode == MeasureSpec.AT_MOST) {
            }
            //fill_parent或者精确值
            else if (specMode == MeasureSpec.EXACTLY) {
            }
    
            return specSize;
        }
    
        private int measureHeight(int measureSpec) {
            int specMode = MeasureSpec.getMode(measureSpec);
            int specSize = MeasureSpec.getSize(measureSpec);
            int defaultHeight = 100;
            //wrap_content
            if (specMode == MeasureSpec.AT_MOST) {
            }
            //fill_parent或者精确值
            else if (specMode == MeasureSpec.EXACTLY) {
                defaultHeight = specSize;
            }
    
            return defaultHeight;
        }
    
        protected void onLayout(boolean changed, int l, int t, int r, int b) {
            super.onLayout(changed, l, t, r, b);
        }
    
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
    
            Paint text_Paint = new Paint();
            text_Paint.setTextAlign(Paint.Align.CENTER);
            text_Paint.setColor(Color.RED);
            text_Paint.setTextSize(20);
    
            int aaa = mThumbMarginTop + mThumbHeight / 2 - mScollBarHeight / 2;
            int bbb = aaa + mScollBarHeight;
    
            //白色,不会动
            notScrollBarBg.setBounds(mThumbWidth / 2, aaa, mScollBarWidth - mThumbWidth / 2, bbb);
            notScrollBarBg.draw(canvas);
    
            //蓝色,中间部分会动
            hasScrollBarBg.setBounds((int)mOffsetLow, aaa, (int)mOffsetHigh, bbb);
            hasScrollBarBg.draw(canvas);
    
            //前滑块
            mThumbLow.setBounds((int)(mOffsetLow - mThumbWidth / 2), mThumbMarginTop, (int)(mOffsetLow + mThumbWidth / 2), mThumbHeight + mThumbMarginTop);
            mThumbLow.draw(canvas);
    
            //后滑块
            mThumbHigh.setBounds((int)(mOffsetHigh - mThumbWidth / 2), mThumbMarginTop, (int)(mOffsetHigh + mThumbWidth / 2), mThumbHeight + mThumbMarginTop);
            mThumbHigh.draw(canvas);
    
            double progressLow = formatDouble((mOffsetLow - mThumbWidth / 2) * 100 / mDistance);
            double progressHigh = formatDouble((mOffsetHigh - mThumbWidth / 2) * 100 / mDistance);
    //            Log.d(TAG, "onDraw-->mOffsetLow: " + mOffsetLow + "  mOffsetHigh: " + mOffsetHigh   + "  progressLow: " + progressLow + "  progressHigh: " + progressHigh);
            canvas.drawText((int) progressLow + "", (int)mOffsetLow - 2 - 2, 15, text_Paint);
            canvas.drawText((int) progressHigh + "", (int)mOffsetHigh - 2, 15, text_Paint);
    
            if (mBarChangeListener != null) {
                if (!isEdit) {
                    mBarChangeListener.onProgressChanged(this, progressLow, progressHigh);
                }
    
            }
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent e) {
            //按下
            if (e.getAction() == MotionEvent.ACTION_DOWN) {
                if (mBarChangeListener != null) {
                    mBarChangeListener.onProgressBefore();
                    isEdit = false;
                }
                mFlag = getAreaFlag(e);
    //            Log.d(TAG, "e.getX: " + e.getX() + "mFlag: " + mFlag);
    //            Log.d("ACTION_DOWN", "------------------");
                if (mFlag == CLICK_ON_LOW) {
                    mThumbLow.setState(STATE_PRESSED);
                } else if (mFlag == CLICK_ON_HIGH) {
                    mThumbHigh.setState(STATE_PRESSED);
                } else if (mFlag == CLICK_IN_LOW_AREA) {
                    mThumbLow.setState(STATE_PRESSED);
                    //如果点击0-mThumbWidth/2坐标
                    if (e.getX() < 0 || e.getX() <= mThumbWidth/2) {
                        mOffsetLow = mThumbWidth/2;
                    } else if (e.getX() > mScollBarWidth - mThumbWidth/2) {
    //                    mOffsetLow = mDistance - mDuration;
                        mOffsetLow = mThumbWidth/2 + mDistance;
                    } else {
                        mOffsetLow = formatDouble(e.getX());
    //                    if (mOffsetHigh<= mOffsetLow) {
    //                        mOffsetHigh = (mOffsetLow + mDuration <= mDistance) ? (mOffsetLow + mDuration)
    //                                : mDistance;
    //                        mOffsetLow = mOffsetHigh - mDuration;
    //                    }
                    }
                } else if (mFlag == CLICK_IN_HIGH_AREA) {
                    mThumbHigh.setState(STATE_PRESSED);
    //                if (e.getX() < mDuration) {
    //                    mOffsetHigh = mDuration;
    //                    mOffsetLow = mOffsetHigh - mDuration;
    //                } else if (e.getX() >= mScollBarWidth - mThumbWidth/2) {
    //                    mOffsetHigh = mDistance + mThumbWidth/2;
                    if(e.getX() >= mScollBarWidth - mThumbWidth/2) {
                        mOffsetHigh = mDistance + mThumbWidth/2;
                    } else {
                        mOffsetHigh = formatDouble(e.getX());
    //                    if (mOffsetHigh <= mOffsetLow) {
    //                        mOffsetLow = (mOffsetHigh - mDuration >= 0) ? (mOffsetHigh - mDuration) : 0;
    //                        mOffsetHigh = mOffsetLow + mDuration;
    //                    }
                    }
                }
                //设置进度条
                refresh();
    
                //移动move
            } else if (e.getAction() == MotionEvent.ACTION_MOVE) {
    //            Log.d("ACTION_MOVE", "------------------");
                if (mFlag == CLICK_ON_LOW) {
                    if (e.getX() < 0 || e.getX() <= mThumbWidth/2) {
                        mOffsetLow = mThumbWidth/2;
                    } else if (e.getX() >= mScollBarWidth - mThumbWidth/2) {
                        mOffsetLow = mThumbWidth/2 + mDistance;
                        mOffsetHigh = mOffsetLow;
                    } else {
                        mOffsetLow = formatDouble(e.getX());
                        if (mOffsetHigh - mOffsetLow <= 0) {
                            mOffsetHigh = (mOffsetLow <= mDistance+mThumbWidth/2) ? (mOffsetLow) : (mDistance+mThumbWidth/2);
                        }
                    }
                } else if (mFlag == CLICK_ON_HIGH) {
                    if (e.getX() <  mThumbWidth/2) {
                        mOffsetHigh = mThumbWidth/2;
                        mOffsetLow = mThumbWidth/2;
                    } else if (e.getX() > mScollBarWidth - mThumbWidth/2) {
                        mOffsetHigh = mThumbWidth/2 + mDistance;
                    } else {
                        mOffsetHigh = formatDouble(e.getX());
                        if (mOffsetHigh - mOffsetLow <= 0) {
                            mOffsetLow = (mOffsetHigh >= mThumbWidth/2) ? (mOffsetHigh) : mThumbWidth/2;
                        }
                    }
                }
                //设置进度条
                refresh();
                //抬起
            } else if (e.getAction() == MotionEvent.ACTION_UP) {
    //            Log.d("ACTION_UP", "------------------");
                mThumbLow.setState(STATE_NORMAL);
                mThumbHigh.setState(STATE_NORMAL);
    
                if (mBarChangeListener != null) {
                    mBarChangeListener.onProgressAfter();
                }
                //这两个for循环 是用来自动对齐刻度的,注释后,就可以自由滑动到任意位置
    //            for (int i = 0; i < money.length; i++) {
    //                 if(Math.abs(mOffsetLow-i* ((mScollBarWidth-mThumbWidth)/ (money.length-1)))<=(mScollBarWidth-mThumbWidth)/(money.length-1)/2){
    //                     mprogressLow=i;
    //                     mOffsetLow =i* ((mScollBarWidth-mThumbWidth)/(money.length-1));
    //                     invalidate();
    //                     break;
    //                }
    //            }
    //
    //            for (int i = 0; i < money.length; i++) {
    //                  if(Math.abs(mOffsetHigh-i* ((mScollBarWidth-mThumbWidth)/(money.length-1) ))<(mScollBarWidth-mThumbWidth)/(money.length-1)/2){
    //                      mprogressHigh=i;
    //                       mOffsetHigh =i* ((mScollBarWidth-mThumbWidth)/(money.length-1));
    //                       invalidate();
    //                       break;
    //                }
    //            }
            }
            return true;
        }
    
        public int getAreaFlag(MotionEvent e) {
    
            int top = mThumbMarginTop;
            int bottom = mThumbHeight + mThumbMarginTop;
            if (e.getY() >= top && e.getY() <= bottom && e.getX() >= (mOffsetLow - mThumbWidth / 2) && e.getX() <= mOffsetLow + mThumbWidth / 2) {
                return CLICK_ON_LOW;
            } else if (e.getY() >= top && e.getY() <= bottom && e.getX() >= (mOffsetHigh - mThumbWidth / 2) && e.getX() <= (mOffsetHigh + mThumbWidth / 2)) {
                return CLICK_ON_HIGH;
            } else if (e.getY() >= top
                    && e.getY() <= bottom
                    && ((e.getX() >= 0 && e.getX() < (mOffsetLow - mThumbWidth / 2)) || ((e.getX() > (mOffsetLow + mThumbWidth / 2))
                    && e.getX() <= ((double) mOffsetHigh + mOffsetLow) / 2))) {
                return CLICK_IN_LOW_AREA;
            } else if (e.getY() >= top
                    && e.getY() <= bottom
                    && (((e.getX() > ((double) mOffsetHigh + mOffsetLow) / 2) && e.getX() < (mOffsetHigh - mThumbWidth / 2)) || (e
                    .getX() > (mOffsetHigh + mThumbWidth/2) && e.getX() <= mScollBarWidth))) {
                return CLICK_IN_HIGH_AREA;
            } else if (!(e.getX() >= 0 && e.getX() <= mScollBarWidth && e.getY() >= top && e.getY() <= bottom)) {
                return CLICK_OUT_AREA;
            } else {
                return CLICK_INVAILD;
            }
        }
    
        //更新滑块
        private void refresh() {
            invalidate();
        }
    
        //设置前滑块的值    
        public void setProgressLow(double  progressLow) {
            this.defaultScreenLow = progressLow;
            mOffsetLow = formatDouble(progressLow / 100 * (mDistance ))+ mThumbWidth / 2;
            isEdit = true;
            refresh();
        }
    
        //设置后滑块的值
        public void setProgressHigh(double  progressHigh) {
            this.defaultScreenHigh = progressHigh;
            mOffsetHigh = formatDouble(progressHigh / 100 * (mDistance)) + mThumbWidth / 2;
            isEdit = true;
            refresh();
        }
    
        public void setOnSeekBarChangeListener(OnSeekBarChangeListener mListener) {
            this.mBarChangeListener = mListener;
        }
    
        //回调函数,在滑动时实时调用,改变输入框的值
        public interface OnSeekBarChangeListener {
            //滑动前
            public void onProgressBefore();
    
            //滑动时
            public void onProgressChanged(SeekBarPressure seekBar, double progressLow,
                                          double progressHigh);
    
            //滑动后
            public void onProgressAfter();
        }
    
    /*    private int formatInt(double value) {
            BigDecimal bd = new BigDecimal(value);
            BigDecimal bd1 = bd.setScale(0, BigDecimal.ROUND_HALF_UP);
            return bd1.intValue();
        }*/
    
        public static double formatDouble(double pDouble) {
            BigDecimal bd = new BigDecimal(pDouble);
            BigDecimal bd1 = bd.setScale(2, BigDecimal.ROUND_HALF_UP);
            pDouble = bd1.doubleValue();
            return pDouble;
        }
    
    }

    2、布局调用 xxx.xml

            <com.xxx.SeekBarPressure
                android:id="@+id/seekBar_tg2"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentTop="true"
                android:layout_marginBottom="10dp"
                android:layout_marginLeft="10dp"
                android:layout_marginRight="10dp" />

    3、在Activity中实现XxxActivity.class

    seekBarPressures = (SeekBarPressure) findViewById(R.id.seekBar_tg2);
    
            seekBarPressures.setOnSeekBarChangeListener(new SeekBarPressure.OnSeekBarChangeListener() {
                @Override
                public void onProgressBefore() {
                    isScreen = true;
                }
    
                @Override
                public void onProgressChanged(SeekBarPressure seekBar, double progressLow, double progressHigh) {
            
                        editTexts_min.setText((int) progressLow + "");
     
                
                        editTexts_max.setText((int) progressHigh + "");
                  
                }
    
                @Override
                public void onProgressAfter() {
                    isScreen = false;
                }
             });

    注意:seekBar的父容器必须LinearLayout,别问我为什么,我也不知道。反正如果是Rinearlayout的话,滑动会不正常,我曹了,为这问题搞了整整3个小时

  • 相关阅读:
    SQL Server2005重新安装不上的问题及其解决(转)
    取消2003默认共享
    自写生成实体类工具
    双核886针CPU简明制作教程
    VS 2008 在安装SP1后智能提示变成英文的解决办法
    VS2008 安装盘的问题
    拖放 DataGrid 列摘自MSDN
    VB.net SP1 的兼容性问题
    Windows Server 2008+VS2008
    Combobox 的解决方法
  • 原文地址:https://www.cnblogs.com/zhujiabin/p/5697151.html
Copyright © 2011-2022 走看看