Android开发EQ音效设置之如何实现跟随手指的小球

由于个人工作中需要负责维护车载导航系统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枚举类是在执行长按操作时的一些变量设置,其它也是没什么难的地方了。

源码点击下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值