由于个人工作中需要负责维护车载导航系统EQ音效设置项目,这其中有一个界面是用来设置系统音效值的,觉得这个界面挺有意思的,现将其使用实现方式总结下来。
效果图,如下:
java代码实现如下:
EqBalanceDrag.java:
package com.asir.balanceview.view;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Point;
public class EqBalanceDrag {
private Paint mPaint = null;
private Matrix mThumbMatrix = null;
private Bitmap mBmpThumb = null;
private float mCurrentX = 0.0F;
private float mCurrentY = 0.0F;
private float mCurTargetX = 0.0F;
private float mCurTargetY = 0.0F;
private float mMoveDistance = 0.0F;
private boolean mMotionFlag = false;
private boolean mSettingFlag = true;
private boolean mResetBalance = true;
private EqBalanceView mEqBalanceView;
public EqBalanceDrag(EqBalanceView view, Bitmap bitmap) {
mBmpThumb = bitmap;
mEqBalanceView = view;
mPaint = new Paint();
mPaint.setAntiAlias(true); // 抗锯齿
mPaint.setColor(Color.WHITE);
mPaint.setTextAlign(Paint.Align.CENTER);
mPaint.setTextSize(18.0F);
mPaint.setDither(true); // 抗抖动
mThumbMatrix = new Matrix();
}
public void drawDragThumb(Canvas canvas) {
canvas.drawBitmap(mBmpThumb, mThumbMatrix, mPaint);
}
public void buildDrawParameter() {
float interpolator = 2.9F;
mMoveDistance = getMoveDistance();
if (mMoveDistance > 0.001D) {
interpolator = (float) (Math.random()) * 1.6F + 1.6F;
interpolator = interpolator < 2.9F ? 2.9F : interpolator;
float moveOffset = (mMoveDistance) / interpolator;
float xOffset = Math.abs(mCurTargetX - mCurrentX) * moveOffset
/ mMoveDistance;
float yOffset = Math.abs(mCurTargetY - mCurrentY) * moveOffset
/ mMoveDistance;
mMoveDistance = mMoveDistance - moveOffset;
mCurrentX = (mCurTargetX-mCurrentX)>0? mCurrentX+xOffset: mCurrentX-xOffset;
mCurrentY = (mCurTargetY-mCurrentY)>0? mCurrentY+yOffset: mCurrentY-yOffset;
if (!mMotionFlag) {
mMotionFlag = true;
if (null != mEqBalanceView){
mEqBalanceView.setDragMotionBegin();
}
}
}
mThumbMatrix.reset();
mThumbMatrix.postTranslate(-mBmpThumb.getWidth() / 2,
-mBmpThumb.getHeight() / 2);
mThumbMatrix.postTranslate(mCurrentX, mCurrentY);
if (null != mEqBalanceView) {
Point point = mEqBalanceView.getBalanceLevel(mCurrentX,
mCurrentY);
mEqBalanceView.setDragMotionChanged(point.x, point.y, mSettingFlag);
}
if (mMotionFlag && mMoveDistance < 0.001D) {
mMotionFlag = false;
mMoveDistance = 0.0F;
mCurrentX = mCurTargetX;
mCurrentY = mCurTargetY;
if (null != mEqBalanceView){
mEqBalanceView.setDragMotionFinished();
}
}
}
public float getMoveDistance() {
double _x = Math.abs(mCurTargetX - mCurrentX);
double _y = Math.abs(mCurTargetY - mCurrentY);
return (float) Math.sqrt(_x * _x + _y * _y);
}
public void resetBalance() {
mResetBalance = true;
mMotionFlag = false;
mMoveDistance = 0.0F;
setThumbLocation((int)mCurrentX, (int)mCurrentY);
if (null != mEqBalanceView){
mEqBalanceView.setDragMotionFinished();
}
}
public void setThumbLocation(int x, int y) {
mCurTargetX = x;
mCurTargetY = y;
mSettingFlag = false;
if (mResetBalance) {
mCurrentX = x;
mCurrentY = y;
mResetBalance = false;
}
}
public void gotoThumbLocation(int x, int y){
mCurTargetX = x;
mCurTargetY = y;
mSettingFlag = true;
if (mResetBalance) {
mCurrentX = x;
mCurrentY = y;
mResetBalance = false;
}
}
public void recycle() {
if ((null != mBmpThumb) && (!mBmpThumb.isRecycled())) {
mBmpThumb.recycle();
mBmpThumb = null;
}
}
}
EqBalanceView.java:
package com.asir.balanceview.view;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.ImageView;
import android.view.MotionEvent;
import android.view.View;
public class EqBalanceView extends ImageView implements View.OnTouchListener, Runnable {
public static final int mBalanceDepth = 21;
private float mCurrentX = 0.0F;
private float mCurrentY = 0.0F;
private Point mCurrLevel = new Point(-1, -1);
private Point mTempLevel = new Point(-1, -1);
private Bitmap mThumbBitmap = null;
private Drawable mThumbDrawable = null;
private boolean mIsMoveBalance = false;
private boolean mHavePresetValue = false; // 有预设值
private PaintFlagsDrawFilter mDrawFilter = null;
private EqBalanceDrag mEqBalanceDrag = null;
private long mLastTime = 0;
private boolean mAnimationFlag = false;
private Thread mAnimationThread = null;
private Context mContext = null;
private RedrawHandle mRedrawHandle = null;
private EqBalanceListener mEqBalanceListener = null;
private int mInitBalanceX = 0;
private int mInitBalanceY = 0;
private int mThumbWidth = 0;
private int mThumbHeight = 0;
private float mThumbUnitGapX = 0.0F;
private float mThumbUnitGapY = 0.0F;
private int mBalanceMax = 0;
private int mBalanceMin = 0;
public EqBalanceView(Context context) {
super(context);
}
public EqBalanceView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public EqBalanceView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mContext = context;
mRedrawHandle = new RedrawHandle();
mDrawFilter = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
TypedArray typedArray = context.obtainStyledAttributes(attrs, EqRes.styleable.EqScroll, defStyle, 0);
mThumbDrawable = typedArray.getDrawable(EqRes.styleable.scroll_item);
mThumbBitmap = EqBitmapUnit.drawableToBitmap(mThumbDrawable);
typedArray.recycle();
if (null != mThumbBitmap) {
mThumbWidth = mThumbBitmap.getWidth();
mThumbHeight = mThumbBitmap.getHeight();
}
mBalanceMax = (mBalanceDepth - 1) / 2;
mBalanceMin = -1 * mBalanceMax;
setOnTouchListener(this);
}
@Override
public void run() {
long currTime = 0;
long diffTime = 0;
while ((!Thread.currentThread().isInterrupted() && mAnimationFlag) && (this.mAnimationFlag)) {
if (null != mEqBalanceDrag) {
if (mIsMoveBalance) {
currTime = System.currentTimeMillis();
diffTime = currTime - mLastTime;
if (diffTime >= 50L) {
mLastTime = currTime;
mRedrawHandle.sendEmptyMessage(RedrawHandle.WM_UPDATE_BALANCE);
} else {
try {
Thread.sleep(25L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} else {
try {
Thread.sleep(50L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} else {
try {
Thread.sleep(50L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public void monitorThreadStop() {
mAnimationFlag = false;
}
public void monitorThreadStart() {
mAnimationFlag = true;
// if 语句的条件执行顺序是 从左到右
if ((mAnimationThread == null) || (!mAnimationThread.isAlive())) {
mAnimationThread = new Thread(this);
mAnimationThread.start();
}
}
public void setEqBalanceListener(EqBalanceListener eqBalanceListener) {
if (null != eqBalanceListener) {
mEqBalanceListener = eqBalanceListener;
}
}
// 取相对坐标
public Point getBalanceThumbXY(Point level) {
Point thumbPoint = new Point(0, 0);
thumbPoint.x = mThumbWidth / 2 + (int) (level.x * mThumbUnitGapX * 1.0F);
thumbPoint.y = mThumbHeight / 2 + (int) (level.y * mThumbUnitGapY * 1.0F);
return thumbPoint;
}
// 取绝对等级 (左-->右 上-->下)
public Point getBalanceLevel(float fx, float fy) {
Point pointLevel = new Point(0, 0);
int x = Math.round(fx);
int y = Math.round(fy);
int nDragRangeW = (getWidth() - mThumbWidth) + (int) mThumbUnitGapX;
int nDragRangeH = (getHeight() - mThumbHeight) + (int) mThumbUnitGapY;
int nMarginW = (getWidth() - nDragRangeW) / 2;
int nMarginH = (getHeight() - nDragRangeH) / 2;
x = (x < nMarginW) ? nMarginW : x;
x = (x > nMarginW + nDragRangeW) ? nMarginW + nDragRangeW : x;
y = (y < nMarginH) ? nMarginH : y;
y = (y > nMarginH + nDragRangeH) ? nMarginH + nDragRangeH : y;
x = x - nMarginW;
y = y - nMarginH;
double dLevelX = x / mThumbUnitGapX;
double dLevelY = y / mThumbUnitGapY;
pointLevel.x = (int) (dLevelX); // (0-20)
pointLevel.y = (int) (dLevelY);
return pointLevel;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
if (null != mEqBalanceListener) {
mEqBalanceListener.onMotionBegin();
}
mCurrentX = event.getX();
mCurrentY = event.getY();
mCurrentX = (mCurrentX < mThumbWidth / 2) ? mThumbWidth / 2 : mCurrentX;
mCurrentY = (mCurrentY < mThumbHeight / 2) ? mThumbHeight / 2 : mCurrentY;
mCurrentX = (mCurrentX > getWidth() - mThumbWidth / 2) ? getWidth() - mThumbWidth / 2 : mCurrentX;
mCurrentY = (mCurrentY > getHeight() - mThumbHeight / 2) ? getHeight() - mThumbHeight / 2 : mCurrentY;
int nAction = event.getAction();
switch (nAction) {
case MotionEvent.ACTION_DOWN:
mIsMoveBalance = true;
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
break;
}
return true;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (null != mEqBalanceDrag) {
canvas.setDrawFilter(mDrawFilter);
mEqBalanceDrag.drawDragThumb(canvas);
}
}
public void setDragMotionBegin() {
if (null != mEqBalanceListener) {
if (!mIsMoveBalance) {
mEqBalanceListener.onMotionBegin();
mIsMoveBalance = true;
}
}
}
public void setDragMotionChanged(int x, int y, boolean bUpdate) {
if (null != mEqBalanceListener) {
// 避免重复Set
if (mCurrLevel.x != x || mCurrLevel.y != y) {
mCurrLevel.x = x;
mCurrLevel.y = y;
mEqBalanceListener.onMotionChanged(x, y, bUpdate);
}
}
}
public void setDragMotionFinished() {
if (null != mEqBalanceListener) {
mEqBalanceListener.onMotionFinished();
mIsMoveBalance = false;
}
}
private void updataBalanceView() {
if (null != mEqBalanceDrag) {
mEqBalanceDrag.gotoThumbLocation((int) mCurrentX, (int) mCurrentY);
mEqBalanceDrag.buildDrawParameter();
invalidate();
}
}
public void setInitBalanceValue(int[] arrayOfInt) {
mCurrentX = arrayOfInt[0];
mCurrentY = arrayOfInt[1];
mInitBalanceX = arrayOfInt[0];
mInitBalanceY = arrayOfInt[1];
if (null != mEqBalanceDrag) {
mEqBalanceDrag.setThumbLocation((int) mInitBalanceX, (int) mInitBalanceY);
}
updataBalanceView();
}
private void initEqBalanceDrag() {
if (null == mEqBalanceDrag) {
mThumbUnitGapX = (getWidth() - mThumbWidth) / ((mBalanceDepth - 1) * 1.0F);
mThumbUnitGapY = (getHeight() - mThumbHeight) / ((mBalanceDepth - 1) * 1.0F);
if (mHavePresetValue) {
mInitBalanceX = getBalanceThumbXY(mTempLevel).x;
mInitBalanceY = getBalanceThumbXY(mTempLevel).y;
} else {
mInitBalanceX = getWidth() / 2;
mInitBalanceY = getHeight() / 2;
}
mCurrentX = mInitBalanceX;
mCurrentY = mInitBalanceY;
mEqBalanceDrag = new EqBalanceDrag(this, mThumbBitmap);
// 第一次只做动画,不做设置效果 因为服务已经做了 用set 不用goto
mEqBalanceDrag.setThumbLocation(mInitBalanceX, mInitBalanceY);
mEqBalanceDrag.buildDrawParameter();
}
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
initEqBalanceDrag();
}
public void reset() {
if (null != mEqBalanceDrag) {
mEqBalanceDrag.resetBalance();
mTempLevel.x = (mBalanceDepth - 1) / 2;
mTempLevel.y = (mBalanceDepth - 1) / 2;
Point point = getBalanceThumbXY(mTempLevel);
mCurrentX = point.x;
mCurrentY = point.y;
updataBalanceView();
}
}
public void setBalanceLevel(int x, int y) {
if (x >= 0 && mBalanceDepth > x) {
if (y >= 0 && mBalanceDepth > y) {
if (null != mEqBalanceDrag) {
mEqBalanceDrag.resetBalance();
mTempLevel.x = x;
mTempLevel.y = y;
Point point = getBalanceThumbXY(mTempLevel);
mCurrentX = point.x;
mCurrentY = point.y;
} else {
// 这里是初始化
mTempLevel.x = x;
mTempLevel.y = y;
mHavePresetValue = true; // 第一次设置必须在onLayout调用前 把握调用时机
}
}
}
}
public void moveLeft() {
if (null != mEqBalanceDrag) {
mEqBalanceDrag.resetBalance();
if (mCurrLevel.x > 0) {
mTempLevel.set(mCurrLevel.x, mCurrLevel.y);
mTempLevel.x -= 1;
Point point = getBalanceThumbXY(mTempLevel);
mCurrentX = point.x;
mCurrentY = point.y;
updataBalanceView();
}
}
}
public void moveRight() {
if (null != mEqBalanceDrag) {
mEqBalanceDrag.resetBalance();
if (mCurrLevel.x < (mBalanceDepth - 1)) {
mTempLevel.set(mCurrLevel.x, mCurrLevel.y);
mTempLevel.x += 1;
Point point = getBalanceThumbXY(mTempLevel);
mCurrentX = point.x;
mCurrentY = point.y;
updataBalanceView();
}
}
}
public void moveFront() {
if (null != mEqBalanceDrag) {
mEqBalanceDrag.resetBalance();
if (mCurrLevel.y > 0) {
mTempLevel.set(mCurrLevel.x, mCurrLevel.y);
mTempLevel.y -= 1;
Point point = getBalanceThumbXY(mTempLevel);
mCurrentX = point.x;
mCurrentY = point.y;
updataBalanceView();
}
}
}
public void moveRear() {
if (null != mEqBalanceDrag) {
mEqBalanceDrag.resetBalance();
if (mCurrLevel.y < (mBalanceDepth - 1)) {
mTempLevel.set(mCurrLevel.x, mCurrLevel.y);
mTempLevel.y += 1;
Point point = getBalanceThumbXY(mTempLevel);
mCurrentX = point.x;
mCurrentY = point.y;
updataBalanceView();
}
}
}
public void moveFrontLeft() {
if (null != mEqBalanceDrag) {
mEqBalanceDrag.resetBalance();
if (mCurrLevel.y > 0 || mCurrLevel.x > 0) {
mTempLevel.set(mCurrLevel.x, mCurrLevel.y);
if (mCurrLevel.y > 0) {
mTempLevel.y -= 1;
}
if (mCurrLevel.x > 0) {
mTempLevel.x -= 1;
}
Point point = getBalanceThumbXY(mTempLevel);
mCurrentX = point.x;
mCurrentY = point.y;
updataBalanceView();
}
}
}
public void moveFrontRight() {
if (null != mEqBalanceDrag) {
mEqBalanceDrag.resetBalance();
if (mCurrLevel.y > 0 || mCurrLevel.x < (mBalanceDepth - 1)) {
mTempLevel.set(mCurrLevel.x, mCurrLevel.y);
if (mCurrLevel.y > 0) {
mTempLevel.y -= 1;
}
if (mCurrLevel.x < (mBalanceDepth - 1)) {
mTempLevel.x += 1;
}
Point point = getBalanceThumbXY(mTempLevel);
mCurrentX = point.x;
mCurrentY = point.y;
updataBalanceView();
}
}
}
public void moveRearLeft() {
if (null != mEqBalanceDrag) {
mEqBalanceDrag.resetBalance();
if (mCurrLevel.y < (mBalanceDepth - 1) || mCurrLevel.x > 0) {
mTempLevel.set(mCurrLevel.x, mCurrLevel.y);
if (mCurrLevel.y < (mBalanceDepth - 1)) {
mTempLevel.y += 1;
}
if (mCurrLevel.x > 0) {
mTempLevel.x -= 1;
}
Point point = getBalanceThumbXY(mTempLevel);
mCurrentX = point.x;
mCurrentY = point.y;
updataBalanceView();
}
}
}
public void moveRearRight() {
if (null != mEqBalanceDrag) {
mEqBalanceDrag.resetBalance();
if (mCurrLevel.y < (mBalanceDepth - 1) || mCurrLevel.x < (mBalanceDepth - 1)) {
mTempLevel.set(mCurrLevel.x, mCurrLevel.y);
if (mCurrLevel.y < (mBalanceDepth - 1)) {
mTempLevel.y += 1;
}
if (mCurrLevel.x < (mBalanceDepth - 1)) {
mTempLevel.x += 1;
}
Point point = getBalanceThumbXY(mTempLevel);
mCurrentX = point.x;
mCurrentY = point.y;
updataBalanceView();
}
}
}
// 价值
public Point getCurrentLevel() {
return mCurrLevel;
}
public void recycle() {
if ((mThumbBitmap != null) && (!mThumbBitmap.isRecycled())) {
mThumbBitmap.recycle();
}
if (mEqBalanceDrag != null) {
mEqBalanceDrag.recycle();
}
}
@SuppressLint("HandlerLeak")
private class RedrawHandle extends Handler {
public static final int WM_UPDATE_BALANCE = 200;
public void handleMessage(Message message) {
super.handleMessage(message);
switch (message.what) {
case WM_UPDATE_BALANCE:
EqBalanceView.this.updataBalanceView();
break;
default:
break;
}
}
}
}
逻辑分析:一些绘制,滚动等操作都被封装在EqBalanceDrag.java中去实现,大家有兴趣的认真看看就懂了
那么使用方式如下:
MainActivity.java部分:
mEqBalance = (EqBalanceView) this.findViewById(R.id.id_eq_balance);
mEqBalance.setEqBalanceListener(mEqBalanceListener);
mEqBalanceButts = new EqBalanceButts(mEqBalance);
mEqBalanceButts.initEqModeButton(this);
mEqBalanceText = (EqBalanceText) this.findViewById(R.id.id_balance_xy);
// Eq Balance Changed
private final class AutoEqBalanceListener implements EqBalanceListener {
@Override
public void onMotionBegin() {
}
@Override
public void onMotionChanged(int x, int y, boolean bUpdate) {
if (null != mEqBalanceText) {
mEqBalanceText.setBanlanceText(new Point(x, y));
if (bUpdate) {
/**
* 这边向底层设置当前值
*/
// mEqApp.mEqACSetting.setBalanceValue(x, y);
}
}
}
@Override
public void onMotionFinished() {
}
@Override
public void onSetBalanceValue(Object object, boolean bUpdate) {
}
}
public static final class EqBalanceButtsClickChange implements OnClickListener {
private Context mContext = null;
public EqBalanceButtsClickChange(Context context) {
if (null != context) {
mContext = context;
}
}
@Override
public void onClick(View v) {
MainActivity eqUI = (MainActivity) (mContext);
eqUI.onEqBalanceClick(v.getId());
}
}
// Balance Left Right Front Rear
private void onEqBalanceClick(int clickId) {
if (null == mEqBalance) {
return;
}
switch (clickId) {
case R.id.id_eqbalance_left:
mEqBalanceButts.onEqBalanceLeft();
break;
case R.id.id_eqbalance_right:
mEqBalanceButts.onEqBalanceRight();
break;
case R.id.id_eqbalance_front:
mEqBalanceButts.onEqBalanceFront();
break;
case R.id.id_eqbalance_rear:
mEqBalanceButts.onEqBalanceRear();
break;
default:
break;
}
}
public static final class EqBalanceButtsLongClickEvent implements OnLongClickListener {
private Context mContext = null;
public EqBalanceButtsLongClickEvent(Context context) {
if (null != context) {
mContext = context;
}
}
@Override
public boolean onLongClick(View v) {
MainActivity eqUI = (MainActivity) (mContext);
eqUI.onEqBalanceLongClick(v.getId());
return true;
}
}
// Balance Left Right Front Rear
private void onEqBalanceLongClick(int clickId) {
if (null == mEqBalance) {
return;
}
switch (clickId) {
case R.id.id_eqbalance_left:
mEqBalanceButts.onLongEqBalanceLeft();
break;
case R.id.id_eqbalance_right:
mEqBalanceButts.onLongEqBalanceRight();
break;
case R.id.id_eqbalance_front:
mEqBalanceButts.onLongEqBalanceFront();
break;
case R.id.id_eqbalance_rear:
mEqBalanceButts.onLongEqBalanceRear();
break;
default:
break;
}
}
public static final class EqBalanceButtsTouchListener implements OnTouchListener {
private Context mContext = null;
public EqBalanceButtsTouchListener(Context context) {
if (null != context) {
mContext = context;
}
}
@Override
public boolean onTouch(View v, MotionEvent event) {
int eAction = event.getAction();
MainActivity eqUI = (MainActivity) (mContext);
switch (eAction) {
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
eqUI.onEqBalanceActionUp(v.getId());
break;
default:
break;
}
return false;
}
}
// Balance Left Right Front Rear
private void onEqBalanceActionUp(int clickId) {
if (null == mEqBalance) {
return;
}
switch (clickId) {
case R.id.id_eqbalance_left:
mEqBalanceButts.onActionUpEqBalanceLeft();
break;
case R.id.id_eqbalance_right:
mEqBalanceButts.onActionUpEqBalanceRight();
break;
case R.id.id_eqbalance_front:
mEqBalanceButts.onActionUpEqBalanceFront();
break;
case R.id.id_eqbalance_rear:
mEqBalanceButts.onActionUpEqBalanceRear();
break;
default:
break;
}
}
找到EqBalanceView并初始化一些数据,这边跟自定义EqBalanceView一样,view控件的查找及监听事件等操作都被封装到EqBalanceButts.java中
EqBalanceButts.java:
package com.asir.balanceview;
import java.util.Timer;
import java.util.TimerTask;
import com.asir.balanceview.MainActivity.EqBalanceButtsClickChange;
import com.asir.balanceview.MainActivity.EqBalanceButtsLongClickEvent;
import com.asir.balanceview.MainActivity.EqBalanceButtsTouchListener;
import com.asir.balanceview.view.EqBalanceView;
import android.annotation.SuppressLint;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.widget.Button;
import android.widget.RadioButton;
import android.widget.RadioGroup;
public class EqBalanceButts {
private static final String TAG = "EqBalanceButts";
private EqBalanceView mEqBalanceView = null;
private EqBalanceButtsClickChange mClickListener = null;
private EqBalanceButtsLongClickEvent mLongClickListener = null;
private EqBalanceButtsTouchListener mTouchListener = null;
private Timer mLongClickTimer = null;
private TimerTask mLcTimerTask = null;
private Handler mHandler = new EqBalanceButtsHandler();
private LCTask mCurrTask = LCTask.ACTION_CURR_TASK;
// button type
public static Button[] mBalanceButt = null;
public final static int eq_balance_left = 0;
public final static int eq_balance_right = 1;
public final static int eq_balance_front = 2;
public final static int eq_balance_rear = 3;
public final static int eq_balance_sizes = 4;
// move action
public final static int move_balance_none = 0;
public final static int move_balance_left = 1;
public final static int move_balance_righ = 2;
public final static int move_balance_fron = 4;
public final static int move_balance_rear = 8;
public final static int move_balance_mxfl = 5;
public final static int move_balance_mxfr = 6;
public final static int move_balance_mxrl = 9;
public final static int move_balance_mxrr = 10;
public enum LCTask {
ACTION_NONE_TASK(0), ACTION_LEFT_TASK(1), ACTION_RIGHT_TASK(2), ACTION_FRONT_TASK(
4), ACTION_REAR_TASK(8), ACTION_FL_TASK(5), ACTION_FR_TASK(6), ACTION_RL_TASK(
9), ACTION_RR_TASK(10), ACTION_CURR_TASK(0);
private int mTask;
private int mWeight;
private LCTask(int nTask) {
mTask = nTask;
mWeight = nTask;
}
private int value() {
return mTask;
}
private int weight() {
return mWeight;
}
// 这只是一个混合规则 使用者不用在意
public LCTask mixTask(LCTask task) {
switch (mTask) {
case 0: // none
System.out.println("--- mixTask = 0 ---"+mWeight);
switch (mWeight) {
case 0:
mTask = task.value();
mWeight = task.weight();
break;
case 3:
switch (task.value()) {
case 4:
mTask = 4;
mWeight = 7;
break;
case 8:
mTask = 8;
mWeight = 11;
break;
default:
break;
}
break;
case 12:
switch (task.value()) {
case 1:
mTask = 1;
mWeight = 13;
break;
case 2:
mTask = 2;
mWeight = 14;
break;
default:
break;
}
break;
default:
break;
}
break;
case 1: // left
switch (mWeight) {
case 1:
switch (task.value()) {
case 2: // right
mTask = 0;
mWeight = 3;
break;
case 4: // front
mTask = 5;
mWeight = 5;
break;
case 8: // rear
mTask = 9;
mWeight = 9;
break;
default:
break;
}
break;
case 13:
switch (task.value()) {
case 2:
mTask = 0;
mWeight = 15;
break;
default:
break;
}
break;
default:
break;
}
break;
case 2: // right
System.out.println("--- mixTask = 2 ---"+mWeight);
switch (mWeight) {
case 2:
switch (task.value()) {
case 1:
mTask = 0;
mWeight = 3;
break;
case 4:
mTask = 6;
mWeight = 6;
break;
case 8:
mTask = 10;
mWeight = 10;
break;
default:
break;
}
break;
case 14:
switch (task.value()) {
case 1:
mTask = 0;
mWeight = 15;
break;
default:
break;
}
break;
default:
break;
}
break;
case 4: // front
switch (mWeight) {
case 4:
switch (task.value()) {
case 1: // left
mTask = 5;
mWeight = 5;
break;
case 2: // right
mTask = 6;
mWeight = 6;
break;
case 8: // rear
mTask = 0;
mWeight = 12;
break;
default:
break;
}
break;
case 7:
switch (task.value()) {
case 8:
mTask = 0;
mWeight = 15;
break;
default:
break;
}
break;
default:
break;
}
break;
case 8: // rear
switch (mWeight) {
case 8:
switch (task.value()) {
case 1: // left
mTask = 9;
mWeight = 9;
break;
case 2: // right
mTask = 10;
mWeight = 10;
break;
case 4: // front
mTask = 0;
mWeight = 12;
break;
default:
break;
}
break;
case 11:
switch (task.value()) {
case 4:
mTask = 0;
mWeight = 15;
break;
default:
break;
}
break;
default:
break;
}
break;
case 5: // fl
switch (task.value()) {
case 2: // right
mTask = 4;
mWeight = 7;
break;
case 8: // rear
mTask = 1;
mWeight = 13;
break;
default:
break;
}
break;
case 6: // fr
switch (task.value()) {
case 1: // left
mTask = 4;
mWeight = 7;
break;
case 8: // rear
mTask = 2;
mWeight = 14;
break;
default:
break;
}
break;
case 9: // rl
switch (task.value()) {
case 2: // right
mTask = 8;
mWeight = 11;
break;
case 4: // front
mTask = 1;
mWeight = 13;
break;
default:
break;
}
break;
case 10: // rr
switch (task.value()) {
case 1: // left
mTask = 8;
mWeight = 11;
break;
case 4: // front
mTask = 2;
mWeight = 14;
break;
default:
break;
}
break;
default:
break;
}
return this;
}
// 这也是一个混合规则 使用者不用在意
public LCTask revokeTask(LCTask task) {
switch (mWeight) {
case 1:
switch (task.value()) {
case 1:
mTask = 0;
mWeight = 0;
break;
default:
break;
}
break;
case 2:
switch (task.value()) {
case 2:
mTask = 0;
mWeight = 0;
break;
default:
break;
}
break;
case 4:
switch (task.value()) {
case 4:
mTask = 0;
mWeight = 0;
break;
default:
break;
}
break;
case 8:
switch (task.value()) {
case 8:
mTask = 0;
mWeight = 0;
break;
default:
break;
}
break;
case 5:
switch (task.value()) {
case 1:
mTask = 4;
mWeight = 4;
break;
case 4:
mTask = 1;
mWeight = 1;
break;
default:
break;
}
break;
case 6:
switch (task.value()) {
case 2:
mTask = 4;
mWeight = 4;
break;
case 4:
mTask = 2;
mWeight = 2;
break;
default:
break;
}
break;
case 9:
switch (task.value()) {
case 1:
mTask = 8;
mWeight = 8;
break;
case 8:
mTask = 1;
mWeight = 1;
break;
default:
break;
}
break;
case 10:
switch (task.value()) {
case 2:
mTask = 8;
mWeight = 8;
break;
case 8:
mTask = 2;
mWeight = 2;
break;
default:
break;
}
break;
case 3:
switch (task.value()) {
case 1:
mTask = 2;
mWeight = 2;
break;
case 2:
mTask = 1;
mWeight = 1;
break;
default:
break;
}
break;
case 12:
switch (task.value()) {
case 4:
mTask = 8;
mWeight = 8;
break;
case 8:
mTask = 4;
mWeight = 4;
break;
default:
break;
}
break;
case 7:
switch (task.value()) {
case 1:
mTask = 6;
mWeight = 6;
break;
case 2:
mTask = 5;
mWeight = 5;
break;
case 4:
mTask = 0;
mWeight = 3;
break;
default:
break;
}
break;
case 14:
switch (task.value()) {
case 8:
mTask = 6;
mWeight = 6;
break;
case 2:
mTask = 0;
mWeight = 12;
break;
case 4:
mTask = 10;
mWeight = 10;
break;
default:
break;
}
break;
case 11:
switch (task.value()) {
case 1:
mTask = 10;
mWeight = 10;
break;
case 2:
mTask = 9;
mWeight = 9;
break;
case 8:
mTask = 0;
mWeight = 3;
break;
default:
break;
}
break;
case 13:
switch (task.value()) {
case 1:
mTask = 0;
mWeight = 12;
break;
case 4:
mTask = 9;
mWeight = 9;
break;
case 8:
mTask = 5;
mWeight = 5;
break;
default:
break;
}
break;
case 15:
switch (task.value()) {
case 1:
mTask = 2;
mWeight = 14;
break;
case 2:
mTask = 1;
mWeight = 13;
break;
case 4:
mTask = 8;
mWeight = 11;
break;
case 8:
mTask = 4;
mWeight = 7;
break;
default:
break;
}
break;
default:
break;
}
return this;
}
};
EqBalanceButts( EqBalanceView balanceView) {
mEqBalanceView = balanceView;
if (null == mBalanceButt) {
mBalanceButt = new Button[eq_balance_sizes];
}
}
public void initEqModeButton(MainActivity context) {
if (null != context) {
mBalanceButt[eq_balance_left] = (Button) context
.findViewById(R.id.id_eqbalance_left);
mBalanceButt[eq_balance_right] = (Button) context
.findViewById(R.id.id_eqbalance_right);
mBalanceButt[eq_balance_front] = (Button) context
.findViewById(R.id.id_eqbalance_front);
mBalanceButt[eq_balance_rear] = (Button) context
.findViewById(R.id.id_eqbalance_rear);
if (null == mClickListener) {
mClickListener = new EqBalanceButtsClickChange(context);
mBalanceButt[eq_balance_left]
.setOnClickListener(mClickListener);
mBalanceButt[eq_balance_right]
.setOnClickListener(mClickListener);
mBalanceButt[eq_balance_front]
.setOnClickListener(mClickListener);
mBalanceButt[eq_balance_rear]
.setOnClickListener(mClickListener);
mTouchListener = new EqBalanceButtsTouchListener(context);
mBalanceButt[eq_balance_left]
.setOnTouchListener(mTouchListener);
mBalanceButt[eq_balance_right]
.setOnTouchListener(mTouchListener);
mBalanceButt[eq_balance_front]
.setOnTouchListener(mTouchListener);
mBalanceButt[eq_balance_rear]
.setOnTouchListener(mTouchListener);
mLongClickListener = new EqBalanceButtsLongClickEvent(context);
mBalanceButt[eq_balance_left]
.setOnLongClickListener(mLongClickListener);
mBalanceButt[eq_balance_right]
.setOnLongClickListener(mLongClickListener);
mBalanceButt[eq_balance_front]
.setOnLongClickListener(mLongClickListener);
mBalanceButt[eq_balance_rear]
.setOnLongClickListener(mLongClickListener);
}
}
}
// 更新 Balance UI
// 1、服务连接上的时候调用一次
// 2、EqUIMain_Activity onResume()调用一次
public void updateBalanceDisplay(){
// BalancePos balancePos = mEqApp.mEqACSetting.getBalanceValue();
//
// if (null != balancePos){
// Log.v(TAG, balancePos.mX+","+balancePos.mY);
// mEqBalanceView.setBalanceLevel(balancePos.mX, balancePos.mY);
// }
}
// reset
public void onEqBalanceReset() {
if (null != mEqBalanceView) {
mEqBalanceView.reset();
}
}
// onClick
public void onEqBalanceLeft() {
if (null != mEqBalanceView) {
mEqBalanceView.moveLeft();
}
}
public void onEqBalanceRight() {
if (null != mEqBalanceView) {
mEqBalanceView.moveRight();
}
}
public void onEqBalanceFront() {
if (null != mEqBalanceView) {
mEqBalanceView.moveFront();
}
}
public void onEqBalanceRear() {
if (null != mEqBalanceView) {
mEqBalanceView.moveRear();
}
}
// hide method
private void onEqBalanceFLTask() {
if (null != mEqBalanceView) {
mEqBalanceView.moveFrontLeft();
}
}
private void onEqBalanceFRTask() {
if (null != mEqBalanceView) {
mEqBalanceView.moveFrontRight();
}
}
private void onEqBalanceRLTask() {
if (null != mEqBalanceView) {
mEqBalanceView.moveRearLeft();
}
}
private void onEqBalanceRRTask() {
if (null != mEqBalanceView) {
mEqBalanceView.moveRearRight();
}
}
// onLongClick
public void onLongEqBalanceLeft() {
mCurrTask.mixTask(LCTask.ACTION_LEFT_TASK);
startLongClickTask();
/*
* Log.v("EqBalance", "Left"); Log.v("EqBalance",
* "["+mCurrTask.mTask+","+mCurrTask.mWeight+"]");
*/
}
public void onLongEqBalanceRight() {
LCTask l= LCTask.ACTION_RIGHT_TASK;
System.out.println(l.mTask +" - "+l.weight());
mCurrTask.mixTask(LCTask.ACTION_RIGHT_TASK);
startLongClickTask();
/*
* Log.v("EqBalance", "Right"); Log.v("EqBalance",
* "["+mCurrTask.mTask+","+mCurrTask.mWeight+"]");
*/
}
public void onLongEqBalanceFront() {
mCurrTask.mixTask(LCTask.ACTION_FRONT_TASK);
startLongClickTask();
/*
* Log.v("EqBalance", "Front"); Log.v("EqBalance",
* "["+mCurrTask.mTask+","+mCurrTask.mWeight+"]");
*/
}
public void onLongEqBalanceRear() {
mCurrTask.mixTask(LCTask.ACTION_REAR_TASK);
startLongClickTask();
/*
* Log.v("EqBalance", "Rear"); Log.v("EqBalance",
* "["+mCurrTask.mTask+","+mCurrTask.mWeight+"]");
*/
}
// ActionUp
public void onActionUpEqBalanceLeft() {
mCurrTask.revokeTask(LCTask.ACTION_LEFT_TASK);
checkLongClickTask();
/*
* Log.v("EqBalance", "Left-up"); Log.v("EqBalance",
* "["+mCurrTask.mTask+","+mCurrTask.mWeight+"]");
*/
}
public void onActionUpEqBalanceRight() {
mCurrTask.revokeTask(LCTask.ACTION_RIGHT_TASK);
checkLongClickTask();
/*
* Log.v("EqBalance", "Right-up"); Log.v("EqBalance",
* "["+mCurrTask.mTask+","+mCurrTask.mWeight+"]");
*/
}
public void onActionUpEqBalanceFront() {
mCurrTask.revokeTask(LCTask.ACTION_FRONT_TASK);
checkLongClickTask();
/*
* Log.v("EqBalance", "Front-up"); Log.v("EqBalance",
* "["+mCurrTask.mTask+","+mCurrTask.mWeight+"]");
*/
}
public void onActionUpEqBalanceRear() {
mCurrTask.revokeTask(LCTask.ACTION_REAR_TASK);
checkLongClickTask();
/*
* Log.v("EqBalance", "Rear-up"); Log.v("EqBalance",
* "["+mCurrTask.mTask+","+mCurrTask.mWeight+"]");
*/
}
private void checkLongClickTask() {
System.out.println("checkLongClickTask");
if (move_balance_none == mCurrTask.value()) {
stopLongClickTask();
} else {
startLongClickTask();
}
}
private void startLongClickTask() {
if (null == mLongClickTimer) {
System.out.println("---startLongClickTask---");
mLongClickTimer = new Timer();
if (null == mLcTimerTask) {
mLcTimerTask = new EqBalanceButtsTimerTask();
}
mLongClickTimer.schedule(mLcTimerTask, 100, 300);
}
}
private void stopLongClickTask() {
System.out.println("stopLongClickTask");
if (null != mLongClickTimer) {
mLongClickTimer.cancel();
mLongClickTimer = null;
}
if (null != mLcTimerTask) {
mLcTimerTask.cancel();
mLcTimerTask = null;
}
}
private void handleLongClickTask() {
if (null == mLongClickTimer || null == mLcTimerTask) {
return; // 定时器退出了后 Hander队列还有消息
}
System.out.println("handleLongClickTask --- "+mCurrTask.value());
switch (mCurrTask.value()) {
case move_balance_none:
stopLongClickTask();
break;
case move_balance_left:
onEqBalanceLeft();
break;
case move_balance_righ:
onEqBalanceRight();
break;
case move_balance_fron:
onEqBalanceFront();
break;
case move_balance_rear:
onEqBalanceRear();
break;
case move_balance_mxfl:
onEqBalanceFLTask();
break;
case move_balance_mxfr:
onEqBalanceFRTask();
break;
case move_balance_mxrl:
onEqBalanceRLTask();
break;
case move_balance_mxrr:
onEqBalanceRRTask();
break;
default:
break;
}
}
private final class EqBalanceButtsTimerTask extends TimerTask {
@Override
public void run() {
if (null != mHandler) {
Message message = mHandler
.obtainMessage(EqBalanceButtsHandler.WM_LONGCLICK_TASK);
mHandler.sendMessage(message);
}
}
}
@SuppressLint("HandlerLeak")
private final class EqBalanceButtsHandler extends Handler {
public final static int WM_LONGCLICK_TASK = 1;
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case WM_LONGCLICK_TASK:
handleLongClickTask();
break;
default:
break;
}
super.handleMessage(msg);
};
};
}
在长安上下左右按钮移动thumb时执行startLongClickTask()方法
这个EqBalanceButts里面是通过一个TimerTask定时发送消息然后发送一个Handler消息执行handleLongClickTask()方法,再执行mEqBalanceView里面封装的相关方法,在手指抬起的时候执行checkLongClickTask再执行stopLongClickTask()方法进而实现长按操作。里面的enum LCTask枚举类是在执行长按操作时的一些变量设置,其它也是没什么难的地方了。