SlidingUpLayout
来源:互联网 发布:淘宝宝贝像素 编辑:程序博客网 时间:2024/06/08 05:15
效果如图:
代码如下:
public class SlidingUpLayout extends ViewGroup { private View mBelowView; private View mDragView; private View mAboveView; private ViewDragHelper mViewDragHelper; private float mAlpha; private float mSlideOffset; private float mAnchorPointer; private State mState = State.ANCHORED; private int mSettlePosition; public enum State { EXPANDED, COLLAPSED, ANCHORED } private OnStateChangedListener onStateChangedListener; public SlidingUpLayout(Context context) { this(context,null); } public SlidingUpLayout(Context context, AttributeSet attrs) { this(context, attrs,0); } public SlidingUpLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.SlidingUpLayout); mAnchorPointer = mTypedArray.getFloat(R.styleable.SlidingUpLayout_anchorPointer,0.44f); mTypedArray.recycle(); } @Override protected void onFinishInflate() { super.onFinishInflate(); mBelowView = getChildAt(0); mDragView = getChildAt(1); mAboveView = getChildAt(2); mViewDragHelper = ViewDragHelper.create(this,new SlidingUpViewDragHelper()); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int measureHeight = MeasureSpec.getSize(heightMeasureSpec); int belowHeight = MeasureSpec.makeMeasureSpec(measureHeight,MeasureSpec.EXACTLY); mBelowView.measure(widthMeasureSpec, belowHeight); LayoutParams dragViewLayoutParams = mDragView.getLayoutParams(); int dragViewWidth = MeasureSpec.makeMeasureSpec(dragViewLayoutParams.width,MeasureSpec.EXACTLY); int dragViewHeight = MeasureSpec.makeMeasureSpec(dragViewLayoutParams.height,MeasureSpec.EXACTLY); mDragView.measure(dragViewWidth,dragViewHeight); mAboveView.measure(widthMeasureSpec,heightMeasureSpec); setMeasuredDimension(widthMeasureSpec, heightMeasureSpec); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { switch (mState){ case EXPANDED: mAlpha = (float) 0.5; mSlideOffset = 1; break; case COLLAPSED: mAlpha = 0; mSlideOffset = 0; break; case ANCHORED: mAlpha = (float) (mAnchorPointer*0.5); mSlideOffset = mAnchorPointer; break; } int belowViewWidth = mBelowView.getMeasuredWidth(); int belowViewHeight = mBelowView.getMeasuredHeight(); mBelowView.layout(0,0,belowViewWidth,belowViewHeight); int dragViewWidth = mDragView.getMeasuredWidth(); int dragViewHeight = mDragView.getMeasuredHeight(); mDragView.layout(belowViewWidth/2-dragViewWidth/2, (int) (belowViewHeight-dragViewHeight-mSlideOffset*(belowViewHeight-dragViewHeight)), belowViewWidth/2+dragViewWidth/2, (int) (belowViewHeight-mSlideOffset*(belowViewHeight-dragViewHeight))); int aboveViewWidth = mAboveView.getMeasuredWidth(); int aboveViewHeight = mAboveView.getMeasuredHeight(); mAboveView.layout(0, (int) (belowViewHeight-mSlideOffset*(belowViewHeight-dragViewHeight)), aboveViewWidth, (int) (belowViewHeight+aboveViewHeight-mSlideOffset*(belowViewHeight-dragViewHeight))); } @Override protected boolean drawChild(Canvas canvas, View child, long drawingTime) { boolean result; final int save = canvas.save(Canvas.CLIP_SAVE_FLAG); if (child==mBelowView) { Rect mTmpRect = new Rect(); canvas.getClipBounds(mTmpRect); mTmpRect.bottom = mAboveView.getTop(); canvas.clipRect(mTmpRect); result = super.drawChild(canvas, child, drawingTime); Paint mCoveredFadePaint = new Paint(); final int baseAlpha = 0xff000000 >>> 24; final int imag = (int) (baseAlpha * mAlpha); final int color = imag << 24 ; mCoveredFadePaint.setColor(color); canvas.drawRect(mTmpRect, mCoveredFadePaint); } else { result = super.drawChild(canvas, child, drawingTime); } canvas.restoreToCount(save); return result; } @Override public void computeScroll() { if (mViewDragHelper.continueSettling(true)){ invalidate(); } } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { mViewDragHelper.processTouchEvent(ev); return mViewDragHelper.shouldInterceptTouchEvent(ev); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { return super.dispatchTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { mViewDragHelper.processTouchEvent(event); return true; } class SlidingUpViewDragHelper extends ViewDragHelper.Callback{ @Override public boolean tryCaptureView(View child, int pointerId) { return child==mDragView; } @Override public int clampViewPositionHorizontal(View child, int left, int dx) { if (child==mDragView){ return mBelowView.getWidth()/2-mDragView.getWidth()/2; } return super.clampViewPositionHorizontal(child, left, dx); } @Override public int clampViewPositionVertical(View child, int top, int dy) { if (top>mBelowView.getMeasuredHeight()-mDragView.getMeasuredHeight()){ mSettlePosition = mBelowView.getMeasuredHeight()-mDragView.getMeasuredHeight(); return mBelowView.getMeasuredHeight()-mDragView.getMeasuredHeight(); }else if (top<0){ mSettlePosition = 0; return 0; }else { mSettlePosition = top-mDragView.getMeasuredHeight(); mAlpha = (float) ((mBelowView.getHeight()-mDragView.getMeasuredHeight()-top)*0.5/(mBelowView.getHeight() -mDragView.getMeasuredHeight())); } return top; } @Override public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { if (changedView==mDragView){ mAboveView.layout(0, top+mDragView.getMeasuredHeight(), mAboveView.getMeasuredWidth(), mAboveView.getMeasuredHeight()+top+mDragView.getMeasuredHeight()); } super.onViewPositionChanged(changedView, left, top, dx, dy); } @Override public void onViewReleased(View releasedChild, float xvel, float yvel) { if (mSettlePosition>mBelowView.getMeasuredHeight()-mAnchorPointer*mBelowView.getMeasuredHeight()/2-mDragView.getMeasuredHeight()){ mDragView.layout(mBelowView.getMeasuredWidth()/2-mDragView.getMeasuredWidth()/2, mBelowView.getMeasuredHeight()-mDragView.getMeasuredHeight(), mBelowView.getMeasuredWidth()/2+mDragView.getMeasuredWidth()/2, mBelowView.getMeasuredHeight()); mAboveView.layout(0, mBelowView.getMeasuredHeight(), mAboveView.getMeasuredWidth(), mBelowView.getMeasuredHeight()+mAboveView.getMeasuredHeight()); mState = State.COLLAPSED; }else if (mSettlePosition<=mBelowView.getMeasuredHeight()-mAnchorPointer*mBelowView.getMeasuredHeight()/2-mDragView.getMeasuredHeight() &&mSettlePosition>mBelowView.getMeasuredHeight()-mAnchorPointer*mBelowView.getMeasuredHeight()*3/2-mDragView.getMeasuredHeight()){ mDragView.layout(mBelowView.getMeasuredWidth()/2-mDragView.getMeasuredWidth()/2, (int) (mBelowView.getMeasuredHeight()-mAnchorPointer*mBelowView.getMeasuredHeight()-mDragView.getMeasuredHeight()), mBelowView.getMeasuredWidth()/2+mDragView.getMeasuredWidth()/2, (int) (mBelowView.getMeasuredHeight()-mAnchorPointer*mBelowView.getMeasuredHeight())); mAboveView.layout(0, (int) (mBelowView.getMeasuredHeight()-mAnchorPointer*mBelowView.getMeasuredHeight()), mAboveView.getMeasuredWidth(), (int) (mBelowView.getMeasuredHeight()-mAnchorPointer*mBelowView.getMeasuredHeight()+mAboveView.getMeasuredHeight())); mState = State.ANCHORED; }else { mDragView.layout(mBelowView.getMeasuredWidth()/2-mDragView.getMeasuredWidth()/2, 0, mBelowView.getMeasuredWidth()/2+mDragView.getMeasuredWidth()/2, mDragView.getMeasuredHeight()); mAboveView.layout(0, mDragView.getMeasuredHeight(), mAboveView.getMeasuredWidth(), mDragView.getMeasuredHeight()+mAboveView.getMeasuredHeight()); mState = State.EXPANDED; } super.onViewReleased(releasedChild, xvel, yvel); } } public void setAnchorPointer(float anchorPointer) { this.mAnchorPointer = anchorPointer; postInvalidate(); } public void setState(State state) { this.mState = state; postInvalidate(); } public void setOnStateChangedListener(OnStateChangedListener onStateChangedListener){ this.onStateChangedListener = onStateChangedListener; } public interface OnStateChangedListener{ public void onStateChanged(State state); }}
implementation 'com.android.support:support-v4:26.0.1'
attrs.xml文件<?xml version="1.0" encoding="utf-8"?><resources> <declare-styleable name="SlidingUpLayout"> <attr name="anchorPointer" format="float"/> </declare-styleable></resources>
布局文件<?xml version="1.0" encoding="utf-8"?><com.example.a1qu212.myapplication.SlidingUpLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" app:anchorPointer="0.44"> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/holo_red_dark"/> <RelativeLayout android:layout_width="100dp" android:layout_height="50dp" android:background="@android:color/holo_green_dark"/> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/black"/></com.example.a1qu212.myapplication.SlidingUpLayout>
存在的问题:计算不够准确;
参考https://github.com/umano/AndroidSlidingUpPanel