android 双向滑动 seekbar
生活随笔
收集整理的這篇文章主要介紹了
android 双向滑动 seekbar
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
實現(xiàn)原理: 1、自定義View,在onDraw(Canvas canvas)中,畫出2個Drawable滑動塊,2個Drawable滑動條,2個Paint(text) 2、監(jiān)聽onTouchEvent()事件,修改滑塊和滑動條的坐標(biāo),調(diào)用invalidate()來更新界面 使用方法 1、自定義View ??SeekBarPressure.class package xxxxxxxxximport 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; //前滑塊中心坐標(biāo)private double mOffsetHigh = 0; //后滑塊中心坐標(biāo)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();}//默認執(zhí)行,計算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_contentif (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_contentif (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);}}}@Overridepublic 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坐標(biāo)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;
// }
}}//設(shè)置進度條
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;}}}//設(shè)置進度條
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循環(huán) 是用來自動對齊刻度的,注釋后,就可以自由滑動到任意位置
// 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();}//設(shè)置前滑塊的值 public void setProgressLow(double progressLow) {this.defaultScreenLow = progressLow;mOffsetLow = formatDouble(progressLow / 100 * (mDistance ))+ mThumbWidth / 2;isEdit = true;refresh();}//設(shè)置后滑塊的值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;}//回調(diào)函數(shù),在滑動時實時調(diào)用,改變輸入框的值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、布局調(diào)用 xxx.xml
<com.xxx.SeekBarPressureandroid: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中實現(xiàn)XxxActivity.class
seekBarPressures = (SeekBarPressure) findViewById(R.id.seekBar_tg2);seekBarPressures.setOnSeekBarChangeListener(new SeekBarPressure.OnSeekBarChangeListener() {@Overridepublic void onProgressBefore() {isScreen = true;}@Overridepublic void onProgressChanged(SeekBarPressure seekBar, double progressLow, double progressHigh) {editTexts_min.setText((int) progressLow + "");editTexts_max.setText((int) progressHigh + "");}@Overridepublic void onProgressAfter() {isScreen = false;}});注意:seekBar的父容器必須LinearLayout,別問我為什么,我也不知道。反正如果是Rinearlayout的話,滑動會不正常,我曹了,為這問題搞了整整3個小時
總結(jié)
以上是生活随笔為你收集整理的android 双向滑动 seekbar的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。