diff --git a/automotive/src/main/java/com/mixiaoxiao/library/splitlayout/SplitLayout.java b/automotive/src/main/java/com/mixiaoxiao/library/splitlayout/SplitLayout.java index 4edae31..a167b43 100644 --- a/automotive/src/main/java/com/mixiaoxiao/library/splitlayout/SplitLayout.java +++ b/automotive/src/main/java/com/mixiaoxiao/library/splitlayout/SplitLayout.java @@ -31,348 +31,348 @@ import com.hmi.autotest.R; /** * SplitLayout github/Mixiaoxiao - * + * * @author Mixiaoxiao 2016/08/18 */ public class SplitLayout extends ViewGroup { - static final String TAG = "SplitLayout"; - static final boolean DEBUG = true; - public static final int HORIZONTAL = 0; - public static final int VERTICAL = 1; + static final String TAG = "SplitLayout"; + static final boolean DEBUG = true; + public static final int HORIZONTAL = 0; + public static final int VERTICAL = 1; - private static final float INVAID_SPLITPOSITION = Float.MIN_VALUE; - private static final int DEFAULT_SPLIT_HANDLE_SIZE_DP = 16; - private static final int DEFAULT_CHILD_MIN_SIZE_DP = 32; - private static final int[] PRESSED_STATE_SET = { android.R.attr.state_pressed }; - private static final int[] EMPTY_STATE_SET = {}; + private static final float INVAID_SPLITPOSITION = Float.MIN_VALUE; + private static final int DEFAULT_SPLIT_HANDLE_SIZE_DP = 16; + private static final int DEFAULT_CHILD_MIN_SIZE_DP = 32; + private static final int[] PRESSED_STATE_SET = {android.R.attr.state_pressed}; + private static final int[] EMPTY_STATE_SET = {}; - private int mOrientation; + private int mOrientation; - private float mSplitFraction; - private float mSplitPosition = INVAID_SPLITPOSITION; + private float mSplitFraction; + private float mSplitPosition = INVAID_SPLITPOSITION; - private Drawable mHandleDrawable; - private int mHandleSize; - private boolean mHandleHapticFeedback; + private Drawable mHandleDrawable; + private int mHandleSize; + private boolean mHandleHapticFeedback; - private View mChild0, mChild1; - private float mLastMotionX, mLastMotionY; - private int mChildMinSize; - private int mWidth, mHeight; - private boolean mIsDragging = false/*是否拖动中间的分割线*/, mIsSwitchStart = false/*是否开始切换子View*/, mIsSwitching = false/*是否切换子View过程中*/; - private Bitmap[] cachedBitmapArray = new Bitmap[2]; - private Bitmap cachedBitmap; - private Canvas cachedCanvas; // 使用双缓冲方式绘制拖动中的View变化,提高效率 - private Paint mPaint = new Paint(); - private int dragForgroundColor = Color.argb(0.88f, 1f, 1f, 1f); // 默认的前景色 - private int splitDragTouchCount = 2; // 默认拖动切换左右两个子View时的点击个数 - private boolean splitIsShowSnapshotView = false; // 拖动过程中是否显示快照图片 - private long mChildLongPressTime; // 记录用户长按拖动子View的初始时间 - private View switchLongPressChildView = null; // 记录用户长按拖动的子View - private boolean hasSwitchChild = false; // 子View是否通过手势切换完成 - private long LONG_PRESS_TIME = 1200; - private Bitmap blurBitmap; // 毛玻璃效果的Bitmap - private Paint splitBgPaint = new Paint(); // 用于绘制分割线背景的画笔 - private Paint splitPressBgPaint = new Paint(); // 用于绘制分割线背景的画笔 + private View mChild0, mChild1; + private float mLastMotionX, mLastMotionY; + private int mChildMinSize; + private int mWidth, mHeight; + private boolean mIsDragging = false/*是否拖动中间的分割线*/, mIsSwitchStart = false/*是否开始切换子View*/, mIsSwitching = false/*是否切换子View过程中*/; + private Bitmap[] cachedBitmapArray = new Bitmap[2]; + private Bitmap cachedBitmap; + private Canvas cachedCanvas; // 使用双缓冲方式绘制拖动中的View变化,提高效率 + private Paint mPaint = new Paint(); + private int dragForgroundColor = Color.argb(0.88f, 1f, 1f, 1f); // 默认的前景色 + private int splitDragTouchCount = 2; // 默认拖动切换左右两个子View时的点击个数 + private boolean splitIsShowSnapshotView = false; // 拖动过程中是否显示快照图片 + private long mChildLongPressTime; // 记录用户长按拖动子View的初始时间 + private View switchLongPressChildView = null; // 记录用户长按拖动的子View + private boolean hasSwitchChild = false; // 子View是否通过手势切换完成 + private long LONG_PRESS_TIME = 1200; + private Bitmap blurBitmap; // 毛玻璃效果的Bitmap + private Paint splitBgPaint = new Paint(); // 用于绘制分割线背景的画笔 + private Paint splitPressBgPaint = new Paint(); // 用于绘制分割线背景的画笔 // private Vibrator vibrator; - public SplitLayout(Context context) { - this(context, null, 0); - } + public SplitLayout(Context context) { + this(context, null, 0); + } - public SplitLayout(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } + public SplitLayout(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } - public SplitLayout(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SplitLayout, defStyleAttr, 0); - mOrientation = a.getInteger(R.styleable.SplitLayout_splitOrientation, HORIZONTAL); - mChildMinSize = a.getDimensionPixelSize(R.styleable.SplitLayout_splitChildMinSize, - dp2px(DEFAULT_CHILD_MIN_SIZE_DP)); - mSplitFraction = a.getFloat(R.styleable.SplitLayout_splitFraction, 0.5f); - checkSplitFraction(); - mHandleDrawable = a.getDrawable(R.styleable.SplitLayout_splitHandleDrawable); - if (mHandleDrawable == null) { - StateListDrawable stateListDrawable = new StateListDrawable(); - stateListDrawable.addState(new int[] { android.R.attr.state_pressed }, new ColorDrawable(getResources().getColor(R.color.draw_progress_bg_color))); - stateListDrawable.addState(new int[] {}, new ColorDrawable(getResources().getColor(R.color.material_pink_500))); - stateListDrawable.setEnterFadeDuration(150); - stateListDrawable.setExitFadeDuration(150); - mHandleDrawable = stateListDrawable; - } - mHandleDrawable.setCallback(this); - mHandleSize = Math.round(a.getDimension(R.styleable.SplitLayout_splitHandleSize, 0f)); - if (mHandleSize <= 0) { - mHandleSize = mOrientation == HORIZONTAL ? mHandleDrawable.getIntrinsicWidth() : mHandleDrawable - .getIntrinsicHeight(); - } - if (mHandleSize <= 0) { - mHandleSize = dp2px(DEFAULT_SPLIT_HANDLE_SIZE_DP); - } - mHandleHapticFeedback = a.getBoolean(R.styleable.SplitLayout_splitHandleHapticFeedback, false); - // 拖动中间分隔条过程中的前景颜色 - dragForgroundColor = a.getColor(R.styleable.SplitLayout_splitDragForgroundColor, dragForgroundColor); - // 切换左右分割子View时手指的点击个数 - splitDragTouchCount = a.getInteger(R.styleable.SplitLayout_splitDragTouchCount, splitDragTouchCount); - splitIsShowSnapshotView = a.getBoolean(R.styleable.SplitLayout_splitIsShowSnapshotView, splitIsShowSnapshotView); - a.recycle(); + public SplitLayout(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SplitLayout, defStyleAttr, 0); + mOrientation = a.getInteger(R.styleable.SplitLayout_splitOrientation, HORIZONTAL); + mChildMinSize = a.getDimensionPixelSize(R.styleable.SplitLayout_splitChildMinSize, + dp2px(DEFAULT_CHILD_MIN_SIZE_DP)); + mSplitFraction = a.getFloat(R.styleable.SplitLayout_splitFraction, 0.5f); + checkSplitFraction(); + mHandleDrawable = a.getDrawable(R.styleable.SplitLayout_splitHandleDrawable); + if (mHandleDrawable == null) { + StateListDrawable stateListDrawable = new StateListDrawable(); + stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, new ColorDrawable(getResources().getColor(R.color.draw_progress_bg_color))); + stateListDrawable.addState(new int[]{}, new ColorDrawable(getResources().getColor(R.color.material_pink_500))); + stateListDrawable.setEnterFadeDuration(150); + stateListDrawable.setExitFadeDuration(150); + mHandleDrawable = stateListDrawable; + } + mHandleDrawable.setCallback(this); + mHandleSize = Math.round(a.getDimension(R.styleable.SplitLayout_splitHandleSize, 0f)); + if (mHandleSize <= 0) { + mHandleSize = mOrientation == HORIZONTAL ? mHandleDrawable.getIntrinsicWidth() : mHandleDrawable + .getIntrinsicHeight(); + } + if (mHandleSize <= 0) { + mHandleSize = dp2px(DEFAULT_SPLIT_HANDLE_SIZE_DP); + } + mHandleHapticFeedback = a.getBoolean(R.styleable.SplitLayout_splitHandleHapticFeedback, false); + // 拖动中间分隔条过程中的前景颜色 + dragForgroundColor = a.getColor(R.styleable.SplitLayout_splitDragForgroundColor, dragForgroundColor); + // 切换左右分割子View时手指的点击个数 + splitDragTouchCount = a.getInteger(R.styleable.SplitLayout_splitDragTouchCount, splitDragTouchCount); + splitIsShowSnapshotView = a.getBoolean(R.styleable.SplitLayout_splitIsShowSnapshotView, splitIsShowSnapshotView); + a.recycle(); - mPaint.setColor(dragForgroundColor); - splitBgPaint.setColor(getResources().getColor(R.color.material_pink_500)); - splitPressBgPaint.setColor(getResources().getColor(R.color.material_lightblue_500)); + mPaint.setColor(dragForgroundColor); + splitBgPaint.setColor(getResources().getColor(R.color.material_pink_500)); + splitPressBgPaint.setColor(getResources().getColor(R.color.material_lightblue_500)); // // 获取震动权限 // vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); // vibrator.vibrate(VibrationEffect.createOneShot(500, 125)); - } + } - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - // super.onMeasure(widthMeasureSpec, heightMeasureSpec); - checkChildren(); - int widthSize = MeasureSpec.getSize(widthMeasureSpec); - int heightSize = MeasureSpec.getSize(heightMeasureSpec); - // 重置子View的最小值 - if (mOrientation == VERTICAL) { - mChildMinSize = heightSize/3; - } else { - mChildMinSize = widthSize/3; - } - if (widthSize > 0 && heightSize > 0) { - mWidth = widthSize; - mHeight = heightSize; - setMeasuredDimension(widthSize, heightSize); - checkSplitPosition(); - final int splitPosition = Math.round(mSplitPosition); - if (mOrientation == VERTICAL) { - mChild0.measure(MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec(splitPosition - mHandleSize / 2, MeasureSpec.EXACTLY)); - mChild1.measure(MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec(heightSize - splitPosition - mHandleSize / 2, MeasureSpec.EXACTLY)); - } else { - mChild0.measure(MeasureSpec.makeMeasureSpec(splitPosition - mHandleSize / 2, MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY)); - mChild1.measure( - MeasureSpec.makeMeasureSpec(widthSize - splitPosition - mHandleSize / 2, MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY)); - } + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + // super.onMeasure(widthMeasureSpec, heightMeasureSpec); + checkChildren(); + int widthSize = MeasureSpec.getSize(widthMeasureSpec); + int heightSize = MeasureSpec.getSize(heightMeasureSpec); + // 重置子View的最小值 + if (mOrientation == VERTICAL) { + mChildMinSize = heightSize / 3; + } else { + mChildMinSize = widthSize / 3; + } + if (widthSize > 0 && heightSize > 0) { + mWidth = widthSize; + mHeight = heightSize; + setMeasuredDimension(widthSize, heightSize); + checkSplitPosition(); + final int splitPosition = Math.round(mSplitPosition); + if (mOrientation == VERTICAL) { + mChild0.measure(MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(splitPosition - mHandleSize / 2, MeasureSpec.EXACTLY)); + mChild1.measure(MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(heightSize - splitPosition - mHandleSize / 2, MeasureSpec.EXACTLY)); + } else { + mChild0.measure(MeasureSpec.makeMeasureSpec(splitPosition - mHandleSize / 2, MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY)); + mChild1.measure( + MeasureSpec.makeMeasureSpec(widthSize - splitPosition - mHandleSize / 2, MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY)); + } - // 初始化双缓冲对应的Bitmap和canvas - if (cachedBitmap == null) { - cachedBitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888); - } - if (cachedCanvas == null) { - cachedCanvas = new Canvas(cachedBitmap); - } - } else { - throw new IllegalStateException("SplitLayout with or height must not be MeasureSpec.UNSPECIFIED"); - } - } + // 初始化双缓冲对应的Bitmap和canvas + if (cachedBitmap == null) { + cachedBitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888); + } + if (cachedCanvas == null) { + cachedCanvas = new Canvas(cachedBitmap); + } + } else { + throw new IllegalStateException("SplitLayout with or height must not be MeasureSpec.UNSPECIFIED"); + } + } - @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) { - int w = r - l; - int h = b - t; - final int splitPosition = Math.round(mSplitPosition); - if (mOrientation == VERTICAL) { - mChild0.layout(0, 0, w, splitPosition - mHandleSize / 2); - mChild1.layout(0, splitPosition + mHandleSize / 2, w, h); - } else { - mChild0.layout(0, 0, splitPosition - mHandleSize / 2, h); - mChild1.layout(splitPosition + mHandleSize / 2, 0, w, h); - } - } + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + int w = r - l; + int h = b - t; + final int splitPosition = Math.round(mSplitPosition); + if (mOrientation == VERTICAL) { + mChild0.layout(0, 0, w, splitPosition - mHandleSize / 2); + mChild1.layout(0, splitPosition + mHandleSize / 2, w, h); + } else { + mChild0.layout(0, 0, splitPosition - mHandleSize / 2, h); + mChild1.layout(splitPosition + mHandleSize / 2, 0, w, h); + } + } - @Override - public boolean dispatchTouchEvent(MotionEvent ev) { - return super.dispatchTouchEvent(ev); - } + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + return super.dispatchTouchEvent(ev); + } - @Override - public boolean onInterceptTouchEvent(MotionEvent ev) { - return super.onInterceptTouchEvent(ev)||ev.getPointerCount() == splitDragTouchCount; - } + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + return super.onInterceptTouchEvent(ev) || ev.getPointerCount() == splitDragTouchCount; + } - @Override - public boolean performClick() { - return super.performClick(); - } + @Override + public boolean performClick() { + return super.performClick(); + } - @Override - public boolean onTouchEvent(MotionEvent ev) { - final int action = ev.getActionMasked(); - float x = ev.getX(); - float y = ev.getY(); - switch (action) { - case MotionEvent.ACTION_DOWN: - Log.d(TAG, "ACTION_DOWN"); - performClick(); - // 单个点击事件 - if (isUnderSplitHandle(x, y)) { - if (mHandleHapticFeedback) { - performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY); - } - mHandleDrawable.setState(PRESSED_STATE_SET); - mIsDragging = true; - getParent().requestDisallowInterceptTouchEvent(true); + @Override + public boolean onTouchEvent(MotionEvent ev) { + final int action = ev.getActionMasked(); + float x = ev.getX(); + float y = ev.getY(); + switch (action) { + case MotionEvent.ACTION_DOWN: + Log.d(TAG, "ACTION_DOWN"); + performClick(); + // 单个点击事件 + if (isUnderSplitHandle(x, y)) { + if (mHandleHapticFeedback) { + performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY); + } + mHandleDrawable.setState(PRESSED_STATE_SET); + mIsDragging = true; + getParent().requestDisallowInterceptTouchEvent(true); // getBitmapFromChildView(); // 截屏当前两个子View的图片,用于在拖动过程中的 - blurBitmap = getBlurBitmap(); - // 开始绘制蒙版图层 - cachedCanvas.drawColor(getContext().getColor(android.R.color.transparent), PorterDuff.Mode.CLEAR); - cachedCanvas.drawBitmap(blurBitmap, 0, 0, null); - invalidate(); - } else { - mIsDragging = false; - } - mLastMotionX = x; - mLastMotionY = y; - break; - case MotionEvent.ACTION_POINTER_DOWN: // 开始多点触控 - Log.d(TAG, "ACTION_POINTER_DOWN"); - if (ev.getPointerCount() == splitDragTouchCount) { // 如果是多指点击(点击个数可通过View的自定义属性定义) - // 首先判断所有的点击手指是否都在单个子View内,如果都在,则记录当前点击时间及子View,后续需要判断是否符合长按标准 - for (int i = 0; i < getChildCount(); i++) { - if (isEventAllInChildView(getChildAt(i), ev)) { // 判断当前手指点击是否都在某个子View内 - mChildLongPressTime = System.currentTimeMillis(); - switchLongPressChildView = getChildAt(i); - mIsSwitchStart = true; - } - } - } - break; - case MotionEvent.ACTION_MOVE: - Log.d(TAG, "ACTION_MOVE"); - if (ev.getPointerCount() == 1) { - if (mIsDragging) { - getParent().requestDisallowInterceptTouchEvent(true); - if (mOrientation == VERTICAL) { - float deltaY = y - mLastMotionY; - onlyUpdateSplitPosition(deltaY); - // updateSplitPositionWithDelta(deltaY); - postInvalidate(); // 使用子View的截图重绘界面 - } else { - float deltaX = x - mLastMotionX; - onlyUpdateSplitPosition(deltaX); - // updateSplitPositionWithDelta(deltaX); - postInvalidate(); - } - mLastMotionX = x; - mLastMotionY = y; - } - } else if (ev.getPointerCount() == splitDragTouchCount) { - if (mIsSwitching) { // 开始进入拖动切换子View流程 - // 分别记录当前两个子View的画面 - getBitmapFromChildView(); - // 判断所有手指是否都到了另外一个子View内 - View tmpView = (switchLongPressChildView == mChild0)? mChild1:mChild0; - if (isEventAllInChildView(tmpView, ev)) { - // 多个触控位置全部移动到另外的View中,并且此前状态不是已切换状态,开始切换快照图片 - if (!hasSwitchChild) { - // 震动提示用户 - performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY); - hasSwitchChild = true; + blurBitmap = getBlurBitmap(); + // 开始绘制蒙版图层 + cachedCanvas.drawColor(getContext().getColor(android.R.color.transparent), PorterDuff.Mode.CLEAR); + cachedCanvas.drawBitmap(blurBitmap, 0, 0, null); + invalidate(); + } else { + mIsDragging = false; + } + mLastMotionX = x; + mLastMotionY = y; + break; + case MotionEvent.ACTION_POINTER_DOWN: // 开始多点触控 + Log.d(TAG, "ACTION_POINTER_DOWN"); + if (ev.getPointerCount() == splitDragTouchCount) { // 如果是多指点击(点击个数可通过View的自定义属性定义) + // 首先判断所有的点击手指是否都在单个子View内,如果都在,则记录当前点击时间及子View,后续需要判断是否符合长按标准 + for (int i = 0; i < getChildCount(); i++) { + if (isEventAllInChildView(getChildAt(i), ev)) { // 判断当前手指点击是否都在某个子View内 + mChildLongPressTime = System.currentTimeMillis(); + switchLongPressChildView = getChildAt(i); + mIsSwitchStart = true; + } + } + } + break; + case MotionEvent.ACTION_MOVE: + Log.d(TAG, "ACTION_MOVE"); + if (ev.getPointerCount() == 1) { + if (mIsDragging) { + getParent().requestDisallowInterceptTouchEvent(true); + if (mOrientation == VERTICAL) { + float deltaY = y - mLastMotionY; + onlyUpdateSplitPosition(deltaY); + // updateSplitPositionWithDelta(deltaY); + postInvalidate(); // 使用子View的截图重绘界面 + } else { + float deltaX = x - mLastMotionX; + onlyUpdateSplitPosition(deltaX); + // updateSplitPositionWithDelta(deltaX); + postInvalidate(); + } + mLastMotionX = x; + mLastMotionY = y; + } + } else if (ev.getPointerCount() == splitDragTouchCount) { + if (mIsSwitching) { // 开始进入拖动切换子View流程 + // 分别记录当前两个子View的画面 + getBitmapFromChildView(); + // 判断所有手指是否都到了另外一个子View内 + View tmpView = (switchLongPressChildView == mChild0) ? mChild1 : mChild0; + if (isEventAllInChildView(tmpView, ev)) { + // 多个触控位置全部移动到另外的View中,并且此前状态不是已切换状态,开始切换快照图片 + if (!hasSwitchChild) { + // 震动提示用户 + performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY); + hasSwitchChild = true; // Toast.makeText(getContext(), "实现切换", Toast.LENGTH_SHORT).show(); - postInvalidate(); - } + postInvalidate(); + } } else { // 重新切换回原有状态 - if (hasSwitchChild) { - performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY); + if (hasSwitchChild) { + performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY); hasSwitchChild = false; // Toast.makeText(getContext(), "恢复状态", Toast.LENGTH_SHORT).show(); - postInvalidate(); - } - } - } else { // 尚未进入拖动切换流程 - // 用户使用多指点击,需要实时判断点击时间是否足够长按时间,满足时,再判断是否和按下时点击的View相同 - if (mChildLongPressTime>0 && System.currentTimeMillis() - mChildLongPressTime >= LONG_PRESS_TIME ) { - if (isEventAllInChildView(switchLongPressChildView, ev)) { - // 震动提示用户,开始支持拖动移动 - performHapticFeedback(HapticFeedbackConstants.DRAG_START); - mIsSwitching = true; - mIsSwitchStart = false; - postInvalidate(); // 开始进入切换左右位置的状态 - } else { // 划出当前View,则重置长按初始时间为0,且初始点按的childView也置为null - mChildLongPressTime = 0; - switchLongPressChildView = null; - } - } - } - } - break; - case MotionEvent.ACTION_POINTER_UP: - switchChildViewPosition(hasSwitchChild); - hasSwitchChild = false; - mIsSwitching = false; - mIsSwitchStart = false; - switchLongPressChildView = null; - mChildLongPressTime = 0; - break; - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_CANCEL: - if (mIsDragging) { - mHandleDrawable.setState(EMPTY_STATE_SET); - if (mOrientation == VERTICAL) { - float deltaY = y - mLastMotionY; - updateSplitPositionWithDelta(deltaY); - } else { - float deltaX = x - mLastMotionX; - updateSplitPositionWithDelta(deltaX); - } - mLastMotionX = x; - mLastMotionY = y; - mIsDragging = false; - postInvalidate(); - } - break; - } - return mIsDragging || mIsSwitchStart || mIsSwitching || ev.getActionMasked() == MotionEvent.ACTION_DOWN || ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN; - } + postInvalidate(); + } + } + } else { // 尚未进入拖动切换流程 + // 用户使用多指点击,需要实时判断点击时间是否足够长按时间,满足时,再判断是否和按下时点击的View相同 + if (mChildLongPressTime > 0 && System.currentTimeMillis() - mChildLongPressTime >= LONG_PRESS_TIME) { + if (isEventAllInChildView(switchLongPressChildView, ev)) { + // 震动提示用户,开始支持拖动移动 + performHapticFeedback(HapticFeedbackConstants.DRAG_START); + mIsSwitching = true; + mIsSwitchStart = false; + postInvalidate(); // 开始进入切换左右位置的状态 + } else { // 划出当前View,则重置长按初始时间为0,且初始点按的childView也置为null + mChildLongPressTime = 0; + switchLongPressChildView = null; + } + } + } + } + break; + case MotionEvent.ACTION_POINTER_UP: + switchChildViewPosition(hasSwitchChild); + hasSwitchChild = false; + mIsSwitching = false; + mIsSwitchStart = false; + switchLongPressChildView = null; + mChildLongPressTime = 0; + break; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + if (mIsDragging) { + mHandleDrawable.setState(EMPTY_STATE_SET); + if (mOrientation == VERTICAL) { + float deltaY = y - mLastMotionY; + updateSplitPositionWithDelta(deltaY); + } else { + float deltaX = x - mLastMotionX; + updateSplitPositionWithDelta(deltaX); + } + mLastMotionX = x; + mLastMotionY = y; + mIsDragging = false; + postInvalidate(); + } + break; + } + return mIsDragging || mIsSwitchStart || mIsSwitching || ev.getActionMasked() == MotionEvent.ACTION_DOWN || ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN; + } - public boolean isEventAllInChildView(View childView, MotionEvent event) { - if (childView == null || event == null) { + public boolean isEventAllInChildView(View childView, MotionEvent event) { + if (childView == null || event == null) { return false; } - int left = childView.getLeft(); - int top = childView.getTop(); - int right = childView.getRight(); - int bottom = childView.getBottom(); + int left = childView.getLeft(); + int top = childView.getTop(); + int right = childView.getRight(); + int bottom = childView.getBottom(); - for (int i = 0; i < event.getPointerCount(); i++) { - // 有任意一个点不在当前View内,则返回false - if (event.getX(i) < left || event.getX(i) > right || event.getY(i) < top || event.getY(i) > bottom) { - return false; - } - } - return true; - } + for (int i = 0; i < event.getPointerCount(); i++) { + // 有任意一个点不在当前View内,则返回false + if (event.getX(i) < left || event.getX(i) > right || event.getY(i) < top || event.getY(i) > bottom) { + return false; + } + } + return true; + } - private boolean isUnderSplitHandle(float x, float y) { - if (mOrientation == VERTICAL) { - return y >= (mSplitPosition - (mHandleSize*2)) && y <= (mSplitPosition + (mHandleSize*2)); - } else { - return x >= (mSplitPosition - (mHandleSize*20)) && x <= (mSplitPosition + (mHandleSize*20)); - } + private boolean isUnderSplitHandle(float x, float y) { + if (mOrientation == VERTICAL) { + return y >= (mSplitPosition - (mHandleSize * 2)) && y <= (mSplitPosition + (mHandleSize * 2)); + } else { + return x >= (mSplitPosition - (mHandleSize * 20)) && x <= (mSplitPosition + (mHandleSize * 20)); + } - } + } - private void updateSplitPositionWithDelta(float delta) { - mSplitPosition = mSplitPosition + delta; - checkSplitPosition(); - requestLayout(); - } + private void updateSplitPositionWithDelta(float delta) { + mSplitPosition = mSplitPosition + delta; + checkSplitPosition(); + requestLayout(); + } - private void onlyUpdateSplitPosition(float delta) { - mSplitPosition = mSplitPosition + delta; - checkSplitPosition(); - } + private void onlyUpdateSplitPosition(float delta) { + mSplitPosition = mSplitPosition + delta; + checkSplitPosition(); + } - @Override - protected void dispatchDraw(Canvas canvas) { - super.dispatchDraw(canvas); - Log.d("SplitLayout", "dispatchDraw"); - if (mIsDragging) { // 开始拖动 + @Override + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); + Log.d("SplitLayout", "dispatchDraw"); + if (mIsDragging) { // 开始拖动 // // 获取两个子View的截图Bitmap // cachedCanvas.drawColor(getContext().getColor(android.R.color.transparent), PorterDuff.Mode.CLEAR); // if (cachedBitmapArray != null) { @@ -401,200 +401,229 @@ public class SplitLayout extends ViewGroup { //// child1Rect.centerY() - (getContext().getDrawable(R.drawable.icon_app).getBounds().height()/2), null); // canvas.drawBitmap(cachedBitmap, 0, 0, null); // } - canvas.drawBitmap(cachedBitmap, 0, 0, null); - } else if (mIsSwitching) { // 开始拖动切换 - if (hasSwitchChild) { - resetChildSnapshotBitmap(canvas, true); - } else { - resetChildSnapshotBitmap(canvas, false); - } - } + canvas.drawBitmap(cachedBitmap, 0, 0, null); + } else if (mIsSwitching) { // 开始拖动切换 + if (hasSwitchChild) { + resetChildSnapshotBitmap(canvas, true); + } else { + resetChildSnapshotBitmap(canvas, false); + } + } - if (mSplitPosition != INVAID_SPLITPOSITION && mHandleDrawable != null) { - final int splitPosition = Math.round(mSplitPosition); - if (mOrientation == VERTICAL) { - mHandleDrawable.setBounds(0, splitPosition - mHandleSize / 2, mWidth, splitPosition + mHandleSize / 2); - } else { - mHandleDrawable.setBounds(splitPosition - mHandleSize / 2, 0, splitPosition + mHandleSize / 2, mHeight); - } - if (mIsDragging) { - canvas.drawRect(mHandleDrawable.getBounds(),splitPressBgPaint); - } else { - canvas.drawRect(mHandleDrawable.getBounds(),splitBgPaint); - } - mHandleDrawable.draw(canvas); - } - } + if (mSplitPosition != INVAID_SPLITPOSITION && mHandleDrawable != null) { + final int splitPosition = Math.round(mSplitPosition); + if (mOrientation == VERTICAL) { + mHandleDrawable.setBounds(0, splitPosition - mHandleSize / 2, mWidth, splitPosition + mHandleSize / 2); + } else { + mHandleDrawable.setBounds(splitPosition - mHandleSize / 2, 0, splitPosition + mHandleSize / 2, mHeight); + } + if (mIsDragging) { + canvas.drawRect(mHandleDrawable.getBounds(), splitPressBgPaint); + } else { + canvas.drawRect(mHandleDrawable.getBounds(), splitBgPaint); + } + mHandleDrawable.draw(canvas); + } + } - private void checkSplitFraction() { - if (mSplitFraction < 0) { - mSplitFraction = 0; - } else if (mSplitFraction > 1) { - mSplitFraction = 1; - } - } + private void checkSplitFraction() { + if (mSplitFraction < 0) { + mSplitFraction = 0; + } else if (mSplitFraction > 1) { + mSplitFraction = 1; + } + } - private void checkSplitPosition() { - if (mOrientation == VERTICAL) { - if (mSplitPosition == INVAID_SPLITPOSITION) { - mSplitPosition = mHeight * mSplitFraction; - } - final int min = mChildMinSize + mHandleSize / 2; - if (mSplitPosition < min) { - mSplitPosition = min; - } else { - final int max = mHeight - mChildMinSize - mHandleSize / 2; - if (mSplitPosition > max) { - mSplitPosition = max; - } - } - } else { - if (mSplitPosition == INVAID_SPLITPOSITION) { - mSplitPosition = mWidth * mSplitFraction; - } - final int min = mChildMinSize + mHandleSize / 2; - if (mSplitPosition < min) { - mSplitPosition = min; - } else { - final int max = mWidth - mChildMinSize - mHandleSize / 2; - if (mSplitPosition > max) { - mSplitPosition = max; - } - } - } - } + private void checkSplitPosition() { + if (mOrientation == VERTICAL) { + if (mSplitPosition == INVAID_SPLITPOSITION) { + mSplitPosition = mHeight * mSplitFraction; + } + final int min = mChildMinSize + mHandleSize / 2; + if (mSplitPosition < min) { + mSplitPosition = min; + } else { + final int max = mHeight - mChildMinSize - mHandleSize / 2; + if (mSplitPosition > max) { + mSplitPosition = max; + } + } + } else { + if (mSplitPosition == INVAID_SPLITPOSITION) { + mSplitPosition = mWidth * mSplitFraction; + } + final int min = mChildMinSize + mHandleSize / 2; + if (mSplitPosition < min) { + mSplitPosition = min; + } else { + final int max = mWidth - mChildMinSize - mHandleSize / 2; + if (mSplitPosition > max) { + mSplitPosition = max; + } + } + } + } - private void checkChildren() { - if (getChildCount() == 2) { - mChild0 = getChildAt(0); - mChild1 = getChildAt(1); - } else { - throw new IllegalStateException("SplitLayout ChildCount must be 2."); - } - } + private void checkChildren() { + if (getChildCount() == 2) { + mChild0 = getChildAt(0); + mChild1 = getChildAt(1); + } else { + throw new IllegalStateException("SplitLayout ChildCount must be 2."); + } + } - @Override - public void jumpDrawablesToCurrentState() { - super.jumpDrawablesToCurrentState(); - if (mHandleDrawable != null) { - mHandleDrawable.jumpToCurrentState(); - } + @Override + public void jumpDrawablesToCurrentState() { + super.jumpDrawablesToCurrentState(); + if (mHandleDrawable != null) { + mHandleDrawable.jumpToCurrentState(); + } - } + } - @Override - protected void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - updateSplitPositionWithDelta(0); - } + @Override + protected void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + updateSplitPositionWithDelta(0); + } - @Override - protected boolean verifyDrawable(Drawable who) { - return super.verifyDrawable(who) || who == mHandleDrawable; - } + @Override + protected boolean verifyDrawable(Drawable who) { + return super.verifyDrawable(who) || who == mHandleDrawable; + } - private int dp2px(float dp) { - return (int) (dp * getContext().getResources().getDisplayMetrics().density + 0.5f); - } + private int dp2px(float dp) { + return (int) (dp * getContext().getResources().getDisplayMetrics().density + 0.5f); + } - // 获取当前两个子View的Bitmap截图,用于在拖动过程中的实时绘制 - private void getBitmapFromChildView() { - if (mChild0!=null) { - cachedBitmapArray[0] = loadBitmapFromViewBySystem(mChild0); - } - if (mChild1!=null) { - cachedBitmapArray[1] = loadBitmapFromViewBySystem(mChild1); - } - } + // 获取当前两个子View的Bitmap截图,用于在拖动过程中的实时绘制 + private void getBitmapFromChildView() { + if (mChild0 != null) { + cachedBitmapArray[0] = loadBitmapFromViewBySystem(mChild0); + } + if (mChild1 != null) { + cachedBitmapArray[1] = loadBitmapFromViewBySystem(mChild1); + } + } - // 获取高斯模糊的bitmap图片 - private Bitmap getBlurBitmap() { - // 先获取当前界面的整体截图 - Bitmap currentBitmap = loadBitmapFromViewBySystem(this); - return UtilBitmap.blurBitmap(getContext(), currentBitmap, 20f); - } - - /** - *此方法直接截取屏幕指定view区域的内容 - * @param view 需要截取屏幕的图片view - * @return Bitmap - */ - public static Bitmap loadBitmapFromViewBySystem(View view) { - if (view == null) { - return null; - } - view.setDrawingCacheEnabled(true); - view.buildDrawingCache(); - Bitmap bitmap = view.getDrawingCache(); - return bitmap; - } - - // 设置拖动时前景图片的颜色值 - public void setDragForgroundColor(int dragForgroundColor) { - this.dragForgroundColor = dragForgroundColor; - mPaint.setColor(dragForgroundColor); - } - - public int getDragForgroundColor() { - return dragForgroundColor; - } - - // 切换两个子View的位置 - public void switchChildViewPosition(boolean isReverse) { - checkChildren(); - removeAllViews(); - if (isReverse) { - addView(mChild1); - addView(mChild0); - View tempView = mChild0; - mChild0 = mChild1; - mChild1 = tempView; - } else { - addView(mChild0); - addView(mChild1); - } - requestLayout(); - } - - // 设置两个子View的快照的显示,可反转 - public void resetChildSnapshotBitmap(Canvas canvas, boolean isReverse) { - if (cachedBitmapArray!= null&&cachedBitmapArray.length>1) { + // 获取高斯模糊的bitmap图片 + private Bitmap getBlurBitmap() { + // 先获取当前界面的整体截图 + getBitmapFromChildView(); // 先获取两个子View的截图 + // 将截图绘制到cachedCanvas上 + cachedCanvas.drawColor(getContext().getColor(android.R.color.transparent), PorterDuff.Mode.CLEAR); + if (cachedBitmapArray != null) { + Rect child0Rect = new Rect(); + Rect child1Rect = new Rect(); + if (mOrientation == VERTICAL) { + child0Rect.set(0, 0, getWidth(), (int) (mSplitPosition - mHandleSize / 2)); + child1Rect.set(0, (int) (mSplitPosition + mHandleSize / 2), getWidth(), getHeight()); + } else { + child0Rect.set(0, 0, (int) (mSplitPosition - mHandleSize / 2), getHeight()); + child1Rect.set((int) (mSplitPosition + mHandleSize / 2), 0, getWidth(), getHeight()); + } + cachedCanvas.drawBitmap(cachedBitmapArray[0], null, child0Rect, null); +// cachedCanvas.drawBitmap(((BitmapDrawable)getContext().getDrawable(R.drawable.icon_app)).getBitmap(), +// child0Rect.centerX() - (getContext().getDrawable(R.drawable.icon_app).getBounds().width()/2), +// child0Rect.centerY() - (getContext().getDrawable(R.drawable.icon_app).getBounds().height()/2), null); + cachedCanvas.drawBitmap(cachedBitmapArray[1], null, child1Rect, null); +// cachedCanvas.drawRect(child1Rect, mPaint); +// cachedCanvas.drawBitmap(((BitmapDrawable)getContext().getDrawable(R.drawable.icon_app)).getBitmap(), +// child1Rect.centerX() - (getContext().getDrawable(R.drawable.icon_app).getBounds().width()/2), +// child1Rect.centerY() - (getContext().getDrawable(R.drawable.icon_app).getBounds().height()/2), null); + Bitmap blurBitmap = UtilBitmap.blurBitmap(getContext(), cachedBitmap, 20f); cachedCanvas.drawColor(getContext().getColor(android.R.color.transparent), PorterDuff.Mode.CLEAR); - Rect child0Rect = new Rect(); - Rect child1Rect = new Rect(); - if (mOrientation == VERTICAL) { - if (!isReverse) { - child0Rect.set(0, 0, getWidth(), (int) (mSplitPosition - mHandleSize / 2)); - child1Rect.set(0, (int) (mSplitPosition + mHandleSize / 2), getWidth(), getHeight()); - } else { - child1Rect.set(0, 0, getWidth(), (int) (mSplitPosition - mHandleSize / 2)); - child0Rect.set(0, (int) (mSplitPosition + mHandleSize / 2), getWidth(), getHeight()); - } - } else { - if (!isReverse) { - child0Rect.set(0, 0, (int) (mSplitPosition - mHandleSize / 2), getHeight()); - child1Rect.set((int) (mSplitPosition + mHandleSize / 2), 0, getWidth(), getHeight()); - } else { - child1Rect.set(0, 0, (int) (mSplitPosition - mHandleSize / 2), getHeight()); - child0Rect.set((int) (mSplitPosition + mHandleSize / 2), 0, getWidth(), getHeight()); - } - } - cachedCanvas.drawBitmap(cachedBitmapArray[0], new Rect(0,0, cachedBitmapArray[0].getWidth(), cachedBitmapArray[0].getHeight()), child0Rect, mPaint); - cachedCanvas.drawRect(child0Rect, mPaint); - cachedCanvas.drawBitmap(cachedBitmapArray[1], new Rect(0,0, cachedBitmapArray[1].getWidth(), cachedBitmapArray[1].getHeight()), child1Rect, mPaint); - cachedCanvas.drawRect(child1Rect, mPaint); - canvas.drawBitmap(cachedBitmap, 0, 0, mPaint); - } - } + cachedCanvas.drawBitmap(blurBitmap, 0, 0, null); + return blurBitmap; + } else { + Bitmap currentBitmap = loadBitmapFromViewBySystem(this); + return UtilBitmap.blurBitmap(getContext(), currentBitmap, 20f); + } + } - /** - * 设置子View的最小宽度 - * */ - public int getmChildMinSize() { - return mChildMinSize; - } + /** + * 此方法直接截取屏幕指定view区域的内容 + * + * @param view 需要截取屏幕的图片view + * @return Bitmap + */ + public static Bitmap loadBitmapFromViewBySystem(View view) { + if (view == null) { + return null; + } + view.setDrawingCacheEnabled(true); + view.buildDrawingCache(); + Bitmap bitmap = view.getDrawingCache(); + return bitmap; + } - public void setmChildMinSize(int mChildMinSize) { - this.mChildMinSize = mChildMinSize; - } + // 设置拖动时前景图片的颜色值 + public void setDragForgroundColor(int dragForgroundColor) { + this.dragForgroundColor = dragForgroundColor; + mPaint.setColor(dragForgroundColor); + } + + public int getDragForgroundColor() { + return dragForgroundColor; + } + + // 切换两个子View的位置 + public void switchChildViewPosition(boolean isReverse) { + checkChildren(); + removeAllViews(); + if (isReverse) { + addView(mChild1); + addView(mChild0); + View tempView = mChild0; + mChild0 = mChild1; + mChild1 = tempView; + } else { + addView(mChild0); + addView(mChild1); + } + requestLayout(); + } + + // 设置两个子View的快照的显示,可反转 + public void resetChildSnapshotBitmap(Canvas canvas, boolean isReverse) { + if (cachedBitmapArray != null && cachedBitmapArray.length > 1) { + cachedCanvas.drawColor(getContext().getColor(android.R.color.transparent), PorterDuff.Mode.CLEAR); + Rect child0Rect = new Rect(); + Rect child1Rect = new Rect(); + if (mOrientation == VERTICAL) { + if (!isReverse) { + child0Rect.set(0, 0, getWidth(), (int) (mSplitPosition - mHandleSize / 2)); + child1Rect.set(0, (int) (mSplitPosition + mHandleSize / 2), getWidth(), getHeight()); + } else { + child1Rect.set(0, 0, getWidth(), (int) (mSplitPosition - mHandleSize / 2)); + child0Rect.set(0, (int) (mSplitPosition + mHandleSize / 2), getWidth(), getHeight()); + } + } else { + if (!isReverse) { + child0Rect.set(0, 0, (int) (mSplitPosition - mHandleSize / 2), getHeight()); + child1Rect.set((int) (mSplitPosition + mHandleSize / 2), 0, getWidth(), getHeight()); + } else { + child1Rect.set(0, 0, (int) (mSplitPosition - mHandleSize / 2), getHeight()); + child0Rect.set((int) (mSplitPosition + mHandleSize / 2), 0, getWidth(), getHeight()); + } + } + cachedCanvas.drawBitmap(cachedBitmapArray[0], new Rect(0, 0, cachedBitmapArray[0].getWidth(), cachedBitmapArray[0].getHeight()), child0Rect, mPaint); + cachedCanvas.drawRect(child0Rect, mPaint); + cachedCanvas.drawBitmap(cachedBitmapArray[1], new Rect(0, 0, cachedBitmapArray[1].getWidth(), cachedBitmapArray[1].getHeight()), child1Rect, mPaint); + cachedCanvas.drawRect(child1Rect, mPaint); + canvas.drawBitmap(cachedBitmap, 0, 0, mPaint); + } + } + + /** + * 设置子View的最小宽度 + */ + public int getmChildMinSize() { + return mChildMinSize; + } + + public void setmChildMinSize(int mChildMinSize) { + this.mChildMinSize = mChildMinSize; + } }