android 双向滑动 seekbar
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 = ; //点击在前滑块上
private static final int CLICK_ON_HIGH = ; //点击在后滑块上
private static final int CLICK_IN_LOW_AREA = ;
private static final int CLICK_IN_HIGH_AREA = ;
private static final int CLICK_OUT_AREA = ;
private static final int CLICK_INVAILD = ;
/*
* 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 = ; //前滑块中心坐标
private double mOffsetHigh = ; //后滑块中心坐标
private int mDistance = ; //总刻度是固定距离 两边各去掉半个滑块距离 private int mThumbMarginTop = ; //滑动块顶部距离上边框距离,也就是距离字体顶部的距离 private int mFlag = CLICK_INVAILD;
private OnSeekBarChangeListener mBarChangeListener; private double defaultScreenLow = ; //默认前滑块位置百分比
private double defaultScreenHigh = ; //默认后滑块位置百分比 private boolean isEdit = false; //输入框是否正在输入 public SeekBarPressure(Context context) {
this(context, null);
} public SeekBarPressure(Context context, AttributeSet attrs) {
this(context, attrs, );
} 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 / ;
mOffsetLow = mThumbWidth / ;
mDistance = width - mThumbWidth; mOffsetLow = formatDouble(defaultScreenLow / * (mDistance ))+ mThumbWidth / ;
mOffsetHigh = formatDouble(defaultScreenHigh / * (mDistance)) + mThumbWidth / ;
setMeasuredDimension(width, mThumbHeight + mThumbMarginTop+);
} 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 = ;
//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(); int aaa = mThumbMarginTop + mThumbHeight / - mScollBarHeight / ;
int bbb = aaa + mScollBarHeight; //白色,不会动
notScrollBarBg.setBounds(mThumbWidth / , aaa, mScollBarWidth - mThumbWidth / , bbb);
notScrollBarBg.draw(canvas); //蓝色,中间部分会动
hasScrollBarBg.setBounds((int)mOffsetLow, aaa, (int)mOffsetHigh, bbb);
hasScrollBarBg.draw(canvas); //前滑块
mThumbLow.setBounds((int)(mOffsetLow - mThumbWidth / ), mThumbMarginTop, (int)(mOffsetLow + mThumbWidth / ), mThumbHeight + mThumbMarginTop);
mThumbLow.draw(canvas); //后滑块
mThumbHigh.setBounds((int)(mOffsetHigh - mThumbWidth / ), mThumbMarginTop, (int)(mOffsetHigh + mThumbWidth / ), mThumbHeight + mThumbMarginTop);
mThumbHigh.draw(canvas); double progressLow = formatDouble((mOffsetLow - mThumbWidth / ) * / mDistance);
double progressHigh = formatDouble((mOffsetHigh - mThumbWidth / ) * / mDistance);
// Log.d(TAG, "onDraw-->mOffsetLow: " + mOffsetLow + " mOffsetHigh: " + mOffsetHigh + " progressLow: " + progressLow + " progressHigh: " + progressHigh);
canvas.drawText((int) progressLow + "", (int)mOffsetLow - - , , text_Paint);
canvas.drawText((int) progressHigh + "", (int)mOffsetHigh - , , 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() < || e.getX() <= mThumbWidth/) {
mOffsetLow = mThumbWidth/;
} else if (e.getX() > mScollBarWidth - mThumbWidth/) {
// mOffsetLow = mDistance - mDuration;
mOffsetLow = mThumbWidth/ + 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/) {
mOffsetHigh = mDistance + mThumbWidth/;
} 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() < || e.getX() <= mThumbWidth/) {
mOffsetLow = mThumbWidth/;
} else if (e.getX() >= mScollBarWidth - mThumbWidth/) {
mOffsetLow = mThumbWidth/ + mDistance;
mOffsetHigh = mOffsetLow;
} else {
mOffsetLow = formatDouble(e.getX());
if (mOffsetHigh - mOffsetLow <= ) {
mOffsetHigh = (mOffsetLow <= mDistance+mThumbWidth/) ? (mOffsetLow) : (mDistance+mThumbWidth/);
}
}
} else if (mFlag == CLICK_ON_HIGH) {
if (e.getX() < mThumbWidth/) {
mOffsetHigh = mThumbWidth/;
mOffsetLow = mThumbWidth/;
} else if (e.getX() > mScollBarWidth - mThumbWidth/) {
mOffsetHigh = mThumbWidth/ + mDistance;
} else {
mOffsetHigh = formatDouble(e.getX());
if (mOffsetHigh - mOffsetLow <= ) {
mOffsetLow = (mOffsetHigh >= mThumbWidth/) ? (mOffsetHigh) : mThumbWidth/;
}
}
}
//设置进度条
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 / ) && e.getX() <= mOffsetLow + mThumbWidth / ) {
return CLICK_ON_LOW;
} else if (e.getY() >= top && e.getY() <= bottom && e.getX() >= (mOffsetHigh - mThumbWidth / ) && e.getX() <= (mOffsetHigh + mThumbWidth / )) {
return CLICK_ON_HIGH;
} else if (e.getY() >= top
&& e.getY() <= bottom
&& ((e.getX() >= && e.getX() < (mOffsetLow - mThumbWidth / )) || ((e.getX() > (mOffsetLow + mThumbWidth / ))
&& e.getX() <= ((double) mOffsetHigh + mOffsetLow) / ))) {
return CLICK_IN_LOW_AREA;
} else if (e.getY() >= top
&& e.getY() <= bottom
&& (((e.getX() > ((double) mOffsetHigh + mOffsetLow) / ) && e.getX() < (mOffsetHigh - mThumbWidth / )) || (e
.getX() > (mOffsetHigh + mThumbWidth/) && e.getX() <= mScollBarWidth))) {
return CLICK_IN_HIGH_AREA;
} else if (!(e.getX() >= && 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 / * (mDistance ))+ mThumbWidth / ;
isEdit = true;
refresh();
} //设置后滑块的值
public void setProgressHigh(double progressHigh) {
this.defaultScreenHigh = progressHigh;
mOffsetHigh = formatDouble(progressHigh / * (mDistance)) + mThumbWidth / ;
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(, 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个小时
android 双向滑动 seekbar的更多相关文章
- Android双向滑动菜单完全解析,教你如何一分钟实现双向滑动特效
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/9671609 记得在很早之前,我写了一篇关于Android滑动菜单的文章,其中有一个 ...
- 【转】Android双向滑动菜单完全解析,教你如何一分钟实现双向滑动特效
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/9671609 记得在很早之前,我写了一篇关于Android滑动菜单的文章,其中有一个 ...
- Android 侧滑(双向滑动菜单)效果
下面看看我们如何使用它,达到我们想要的效果 public class MainActivity extends Activity { /** * 双向滑动菜单布局 */ private SliderM ...
- 超酷的Android 侧滑(双向滑动菜单)效果
下面看看我们如何使用它,达到我们想要的效果 public class MainActivity extends Activity { /** * 双向滑动菜单布局 */ private SliderM ...
- android之SlideMenu双向滑动
开始动手之前先来讲一下实现原理,在一个Activity的布局中需要有三部分,一个是左侧菜单的布局,一个是右侧菜单的布局,一个是内容布局.左侧菜单居屏幕左边缘对齐,右侧菜单居屏幕右边缘对齐,然后内容布局 ...
- [Android学习笔记]SeekBar的使用
一.SeekBar滑动条的使用 xml声明: <SeekBar android:id="@+id/seekbar" android:layout_width="20 ...
- android去掉滑动到顶部和底部的阴影
android去掉滑动到顶部和底部的阴影 <ListView android:id="@+id/listView" android:layout_width="ma ...
- Android ListView滑动过程中图片显示重复错乱闪烁问题解决
最新内容建议直接访问原文:Android ListView滑动过程中图片显示重复错乱闪烁问题解决 主要分析Android ListView滚动过程中图片显示重复.错乱.闪烁的原因及解决方法,顺带提及L ...
- Android——拖动条SeekBar
1.activity_seekbar.xml <?xml version="1.0" encoding="utf-8"?><LinearLay ...
随机推荐
- js数组&&字符串&&定时器2
一.系统时间对象Date 方法 描述 Date() 返回当日的日期和时间. getDate() 从 Date 对象返回一个月中的某一天 (1 ~ 31). getDay() 从 Date 对象返回一周 ...
- 通过修改ajaxFileUpload.js实现多图片动态上传并实现预览
参考:http://smotive.iteye.com/blog/1903606 大部分我也是根据他的方法修改的,我也要根据name实现动态的多文件上传功能,但是有个问题使我一直无法实现多文件上传. ...
- TransactionScope事务
一个错误的理解就是Complete()方法是提交事务的,这是错误的,事实上,它的作用的表示本事务完成,它一般放在try{}的结尾处,不用判断前台操作是否成功,如果不成功,它会自己回滚. #region ...
- PHP session 失效不传递的解决办法
PHP中,session不能传递到下一个页面去,一般有两种情况: 我们先写个php文件:<?=phpinfo()?>, 传到服务器去看看服务器的参数配置. 转到session部分,看到se ...
- Ext.Net学习笔记02:Ext.Net用法概览
这两天越来越觉得Ext.Net很强大,如果运用熟练可以极大的提高编程效率.如果你也要学习Ext.Net,推荐你看一下<Ext.Net Web 应用程序开发教程>. Ext.Net与ExtJ ...
- 数位DP入门Ural1057
CF一战让我觉得很疲倦,所以今天感觉很慢. 昨天解D题时候,因为太累,根本连题目都没看,今天看了之后感觉不会做,听闻是数位DP问题. 有某神说过,DP的功力建立在刷过的题上,我真的毫无功力可言. 介绍 ...
- python 在调用时计算默认值
大家都知道python的默认值是在函数定义时计算出来的, 也就是说默认值只会计算一次, 之后函数调用时, 如果参数没有给出,同一个值会赋值给变量, 这会导致, 如果我们想要一个list默认值, 新手通 ...
- 关于Navicat导入MySQL数据库遇到的一些问题
今天本想将之前的一个数据库easy.sql用图形化工具Navicat导入的,开始是用“运行SQL文件”导入,结果是“queries successfully”啥的,去查是否导表成功,一看并没有. 结果 ...
- Socket 死连接详解
Socket 死连接详解 当使用 Socket 进行通信时,由于各种不同的因素,都有可能导致死连接停留在服务器端,假如服务端需要处理的连接较多,就有可能造成服务器资源严重浪费,对此,本文将阐述其原理以 ...
- 【原创】Linux opensource-src-4.3.2.tar.gz的安装。
下载好opensource-src-4.3.2.tar.gz 安装G++等必备库: sudo apt-get install make gcc g++ sudo apt-get install bui ...