Android自定义正负双向SeekBar
来源:互联网 发布:python opencv hough 编辑:程序博客网 时间:2024/05/29 02:15
第一次写Android技术博客,有不足之处还望指正。接下来言归正传,之前在MIX滤镜大师上看到一个类似于seekbar的控件,用来调节图像属性,比如,对比度、亮度、饱和度等等。感觉很不错,现在项目中也要用到类似的控件,刚开始在网上找了一下demo,但都不符合要求,于是就自己写了一个。先上一下效果图:![](http://img.blog.csdn.net/20151013175307447)![](http://img.blog.csdn.net/20151013175331218)![](http://img.blog.csdn.net/20151013175349310)接下来直接上代码:
import java.math.BigDecimal;import android.annotation.SuppressLint;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.util.Log;import android.view.MotionEvent;import android.view.View;public class TwoWaysSeekBar extends View { private static final int CLICK_ON_PRESS = 1; //点击在滑块上 private static final int CLICK_INVAILD = 0; private static final int[] STATE_NORMAL = {}; private static final int[] STATE_PRESSED = {android.R.attr.state_pressed,android.R.attr.state_window_focused}; private static final String tag = "TwoWaysSeekBar"; private Drawable notScrollBarBg; //滑动条背景图 private Drawable hasScrollBarBg; //滑动条滑动时背景图 private Drawable mThumb; //滑块 private Drawable mCenterCircle; //中间分隔小圆点 private int mSeekBarWidth; //控件宽度 private int mSeekBarHeight; //滑动条高度 private int mCenterCircleWidth; //中间分割点宽度 private int mCenterCircleHeight; //中间分割点高度 private int mThumbWidth; //滑块宽度 private int mThumbHeight; //滑块高度 private double mThumbOffset = 0; //滑块中心坐标 private double mDefaultThumbOffSet = 100; //默认滑块位置百分比 private int mThumbMarginTop = 70; //滑动块顶部距离上边框距离,也就是距离字体顶部的距离 private int mDistance = 0; //滑动的总距离,固定值 private int mFlag = CLICK_INVAILD; private OnSeekBarChangeListener mSeekBarChangeListener; public TwoWaysSeekBar(Context context) { this(context, null); } public TwoWaysSeekBar(Context context, AttributeSet attrs) { this(context, attrs, 0); } public TwoWaysSeekBar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } public void init(){ Resources resources = getResources(); notScrollBarBg = resources.getDrawable(R.drawable.seek_background_line); hasScrollBarBg = resources.getDrawable(R.drawable.seek_progress_line); mThumb = resources.getDrawable(R.drawable.seek_adjust_btn); mCenterCircle = resources.getDrawable(R.drawable.seek_middle_btn); mSeekBarWidth = notScrollBarBg.getIntrinsicWidth(); mSeekBarHeight = notScrollBarBg.getIntrinsicHeight(); mThumbWidth = mThumb.getIntrinsicWidth(); mThumbHeight = mThumb.getIntrinsicHeight(); mCenterCircleWidth = mCenterCircle.getIntrinsicWidth(); mCenterCircleHeight = mCenterCircle.getIntrinsicHeight(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = measureWidth(widthMeasureSpec); mSeekBarWidth = width; mThumbOffset = width/2; mDistance = width - mThumbWidth; mThumbOffset = formatDouble(mDefaultThumbOffSet/200*(mDistance) + mThumbWidth/2); setMeasuredDimension(width, mThumbHeight + mThumbMarginTop+2); } private int measureWidth(int measureSpec){ int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); if(specMode == MeasureSpec.AT_MOST){ } else if (specMode == MeasureSpec.EXACTLY) { } return specSize; } @SuppressWarnings("unused") 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; } @Override protected void onLayout(boolean changed, int left, int top, int right,int bottom) { super.onLayout(changed, left, top, right, bottom); } @SuppressLint("DrawAllocation") @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); Paint text_Paint = new Paint(); text_Paint.setTextAlign(Paint.Align.CENTER); text_Paint.setColor(Color.parseColor("#4e8795")); text_Paint.setAntiAlias(true); //抗锯齿 text_Paint.setAlpha(255); //透明度 text_Paint.setTextSize(40); int aaa = mThumbMarginTop + mThumbHeight/2 - mSeekBarHeight/2; int bbb = aaa + mSeekBarHeight; int ccc = mThumbMarginTop + mThumbHeight/2 - mCenterCircleHeight/2; int ddd = ccc + mCenterCircleHeight; notScrollBarBg.setBounds(mThumbWidth/2, aaa, mSeekBarWidth-mThumbWidth/2, bbb); //左,上,右,下 notScrollBarBg.draw(canvas); if(mThumbOffset > mSeekBarWidth/2){ hasScrollBarBg.setBounds(mSeekBarWidth/2, aaa, (int)mThumbOffset, bbb); }else if(mThumbOffset < mSeekBarWidth/2){ hasScrollBarBg.setBounds((int)mThumbOffset, aaa, mSeekBarWidth/2, bbb); }else{ hasScrollBarBg.setBounds((int)mThumbOffset, aaa, mSeekBarWidth/2, bbb); } hasScrollBarBg.draw(canvas); mCenterCircle.setBounds(mSeekBarWidth/2 - mCenterCircleWidth/2, ccc, mSeekBarWidth/2 + mCenterCircleWidth/2, ddd); mCenterCircle.draw(canvas); mThumb.setBounds((int)mThumbOffset - mThumbWidth/2,mThumbMarginTop,(int)mThumbOffset + mThumbWidth/2,mThumbMarginTop+mThumbHeight); mThumb.draw(canvas); double progress = formatDouble((mThumbOffset - mThumbWidth/2) * 200 / mDistance); //progress初始值为100 if((int)progress == 100){ progress = 0; }else if((int)progress > 100){ progress -= 100; }else if((int)progress < 100){ progress -=100; } Log.d(tag, "progress:"+progress); canvas.drawText((int)progress+"", (int) mThumbOffset - 2 - 2, 50, text_Paint); if(mSeekBarChangeListener != null){ mSeekBarChangeListener.onProgressChanged(this, progress); } } @SuppressLint("ClickableViewAccessibility") @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: if(mSeekBarChangeListener != null){ } mFlag = getAreaFlag(event); if(mFlag == CLICK_ON_PRESS){ mThumb.setState(STATE_PRESSED); mSeekBarChangeListener.onProgressBefore(); } break; case MotionEvent.ACTION_MOVE: if(mFlag == CLICK_ON_PRESS){ if(event.getX() < 0 || event.getX() <= mThumbWidth/2){ mThumbOffset = mThumbWidth/2; }else if(event.getX() >= mSeekBarWidth - mThumbWidth/2){ mThumbOffset = mDistance + mThumbWidth/2; }else{ mThumbOffset = formatDouble(event.getX()); } } refresh(); break; case MotionEvent.ACTION_UP: mThumb.setState(STATE_NORMAL); if(mSeekBarChangeListener != null){ mSeekBarChangeListener.onProgressAfter(); } break; default: break; } return true; } public int getAreaFlag(MotionEvent e){ int top = mThumbMarginTop; int bottom = mThumbMarginTop + mThumbHeight; if(e.getY() >= top && e.getY() <= bottom && e.getX() >= (mThumbOffset - mThumbWidth/2) && e.getX() <= (mThumbOffset + mThumbWidth/2)){ return CLICK_ON_PRESS; }else{ return CLICK_INVAILD; } } private void refresh(){ invalidate(); } //设置进度 public void setProgress(double progress){ this.mDefaultThumbOffSet = progress; /*if(progress == 0){ mThumbOffset = formatDouble(100/200*(mDistance))+mThumbWidth/2; }else */if(progress >= 0){ mThumbOffset = formatDouble((100 + progress)/200*(mDistance))+mThumbWidth/2; }else if(progress < 0){ mThumbOffset = formatDouble((100 + progress)/200*(mDistance))+mThumbWidth/2; } refresh(); } public void setOnSeekBarChangeListener(OnSeekBarChangeListener mListener){ this.mSeekBarChangeListener = mListener; } public interface OnSeekBarChangeListener { //滑动前 public void onProgressBefore(); //滑动中 public void onProgressChanged(TwoWaysSeekBar seekBar, double progress); //滑动后 public void onProgressAfter(); } public static double formatDouble(double mDouble){ BigDecimal bd = new BigDecimal(mDouble); BigDecimal bd1 = bd.setScale(2,BigDecimal.ROUND_HALF_UP); mDouble = bd1.doubleValue(); return mDouble; }}
怎样引用在这里就不多赘述了,包名+类名就可以了,监听器也有,在activity中可以直接用。不足之处还望大家多给建议。参考文献:[](http://lanaiver6291.blog.163.com/blog/static/17779831020153131432393/)
1 0
- Android自定义正负双向SeekBar
- Android 自定义双向滑动SeekBar
- Android_自定义双向SeekBar
- 自定义双向滑动SeekBar
- Android双向seekbar
- 自定义SeekBar使用双向滑块选择
- android中自定义SeekBar
- android 自定义SeekBar
- android 自定义SeekBar
- Android SeekBar自定义UI
- Android - 自定义SeekBar
- 【Android】自定义seekbar样式
- android 自定义SeekBar 问题
- Android 自定义SeekBar控件
- android,自定义seekbar,样式
- Android:自定义SeekBar样式
- Android SeekBar自定义UI
- Android 自定义seekbar样式
- apk获取资源文件及反编译方式
- Xcode和它的文档朋友们
- Swift学习笔记22——泛型(Generics)
- TCL脚本语言基础介绍
- Easyui如何实现combotree,输入文本及时筛选功能
- Android自定义正负双向SeekBar
- iOS调用系统发短信功能详解
- Mahout学习路线图
- 【IOS 开发学习总结-OC-45】★★ios开发之UI控件——UISegmentedControl与UIImageView
- 【C#高效编程50例】条目3:使用is 或 as 操作符而不是强制类型转换
- Jodd DB上手指南
- C语言数据的表现形式
- 从一个简单的WEB项目入手来简单地了解一下什么是Spring之持久层(Dao)
- 使用complete属性判断图片是否加载完成