Android笔记(一):ViewDragHelper实现底部上滑同时底部下滑

来源:互联网 发布:淘宝代销图片实拍 编辑:程序博客网 时间:2024/05/16 17:20

先看看效果图:

仿哆点


自定义布局控件:

public class DragLayout extends FrameLayout {    private int title;    //限制上滑后的顶部标题高度大小    private Status mStatus = Status.Open;    //默认底部是不上滑的    private View mTopContent;    private View mMainContent;    private ViewDragHelper mDragHelper;    private int mDragRange,mMainTop,mWidth,mHeight;   //mDragRange为拖拽范围,mMainTop为底部面板离父布局顶部的长度    public DragLayout(@NonNull Context context) {        this(context,null);    }    public DragLayout(@NonNull Context context, @Nullable AttributeSet attrs) {        this(context, attrs,0);    }    public DragLayout(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {        super(context, attrs, defStyleAttr);        mDragHelper = ViewDragHelper.create(this,0.5f, mCallBack);    }    ViewDragHelper.Callback mCallBack=new ViewDragHelper.Callback() {        @Override        public boolean tryCaptureView(View child, int pointerId) {            boolean directionCheck=mDragHelper.checkTouchSlop(ViewDragHelper.DIRECTION_VERTICAL,pointerId);            return (child==mMainContent||child==mTopContent)&&directionCheck;        }        @Override        public int clampViewPositionVertical(View child, int top, int dy) {            if (mMainTop+dy<title){                return title;            }else if(mMainTop+dy>mDragRange+title){                return mDragRange+title;            }            return top;        }        @Override        public int getViewVerticalDragRange(View child) {            return mDragRange;        }        @Override        public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {            super.onViewPositionChanged(changedView, left, top, dx, dy);            if(changedView==mMainContent){                mMainTop=top;            }else{                mMainTop+=dy;            }            if (mMainTop < title) {                mMainTop = title;            } else if (mMainTop > mDragRange+title) {                mMainTop = mDragRange+title;            }            if (changedView == mTopContent) {                layoutContent();   //如果拖动的是顶部面板则进行强制布局移动            }            dispatchDragEvent(mMainTop);        }        @Override        public void onViewReleased(View releasedChild, float xvel, float yvel) {            super.onViewReleased(releasedChild, xvel, yvel);            if (yvel > 0) {                open();            } else if (yvel == 0 && mMainTop > mDragRange * 0.5f) {                open();            } else {                close();            }        }    };    public void close() {        mMainTop = title;        // 执行动画,返回true代表有未完成的动画, 需要继续执行        if (mDragHelper.smoothSlideViewTo(mMainContent, 0, mMainTop)) {            // 注意:参数传递根ViewGroup            ViewCompat.postInvalidateOnAnimation(this);        }    }    private void layoutContent() {        mMainContent.layout(0, mMainTop,  mWidth, mHeight+mMainTop);        mTopContent.layout(0, -mHeight/6, mWidth, mHeight);    }    public void open() {        mMainTop = mDragRange+title;        if (mDragHelper.smoothSlideViewTo(mMainContent, 0, mMainTop)) {            ViewCompat.postInvalidateOnAnimation(this);        }    }    protected void dispatchDragEvent(int mainTop) {        float percent = mainTop / (float)mDragRange;        ViewHelper.setTranslationY(mTopContent, mHeight / 8 - mHeight / 8 * percent);  //实现顶部下滑        if (mListener != null) {            mListener.onDraging(percent);        }        Status lastStatus = mStatus;        if (updateStatus(mainTop) != lastStatus) {            if (mListener == null) {                return;            }            if (lastStatus == Status.Draging) {                if (mStatus == Status.Close) {                    mListener.onClose();                } else if (mStatus == Status.Open) {                    mListener.onOpen();                }            }        }    }    public interface OnLayoutDragingListener {        void onOpen();        void onClose();        void onDraging(float percent);    }    private OnLayoutDragingListener mListener;    public void setOnLayoutDragingListener(OnLayoutDragingListener l) {        mListener = l;    }    private Status updateStatus(int mainTop) {        if (mainTop == title) {            mStatus = Status.Close;        } else if (mainTop == mDragRange+title) {            mStatus = Status.Open;        } else {            mStatus = Status.Draging;        }        return mStatus;    }    public enum Status {        Open, Close, Draging    }    public Status getStatus() {        return mStatus;    }    public void setStatus(Status mStatus) {        this.mStatus = mStatus;    }    @Override    public boolean onInterceptTouchEvent(android.view.MotionEvent ev) {        //将Touch事件传递给ViewDragHelper        return mDragHelper.shouldInterceptTouchEvent(ev);    };    @Override    public boolean onTouchEvent(MotionEvent event) {        try {            //将Touch事件传递给ViewDragHelper            mDragHelper.processTouchEvent(event);        } catch (Exception e) {        }        return true;    }    @Override    public void computeScroll() {        // 高频率调用,决定是否有下一个变动等待执行        if (mDragHelper.continueSettling(true)) {            ViewCompat.postInvalidateOnAnimation(this);        }    }    @Override    protected void onLayout(boolean changed, int left, int top, int right,                            int bottom) {        mMainContent.layout(0,mMainTop,  mWidth, mMainTop+mHeight);        mTopContent.layout(0, -mHeight/6, mWidth, mHeight);    }    @Override    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(w, h, oldw, oldh);        //拿到宽高        mWidth = getMeasuredWidth();        mHeight = getMeasuredHeight();        //设置拖动范围        mDragRange = (int)(mHeight*0.4);        mMainTop=(int)(mHeight*0.5);        title=mMainTop-mDragRange;    }    /**     * 填充结束时获得两个子布局的引用     */    @Override    protected void onFinishInflate() {        super.onFinishInflate();        int childCount = getChildCount();        // 必要的检验        if (childCount < 2) {            throw new IllegalStateException(                    "You need two childrens in your content");        }        if (!(getChildAt(0) instanceof ViewGroup)                || !(getChildAt(1) instanceof ViewGroup)) {            throw new IllegalArgumentException(                    "Your childrens must be an instance of ViewGroup");        }        mTopContent = getChildAt(0);        mMainContent = getChildAt(1);    }}

提示:可以在外部获得DragLayout对象后设置OnLayoutDragingListener来监听拖动过程


public class MainActivity extends AppCompatActivity {    private FragmentManager fragmentManager;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        fragmentManager=getSupportFragmentManager();        fragmentManager.beginTransaction().add(R.id.container,new FirstFragment()).commit();    }}

public class FirstFragment extends Fragment {    @Nullable    @Override    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {        View view=inflater.inflate(R.layout.first_fragment_layout,container,false);        return view;    }}



注意:DragLayout必须要有且只有两个子控件
<com.example.duodian.DragLayout xmlns:android="http://schemas.android.com/apk/res/android"     android:layout_width="match_parent"    android:layout_height="match_parent">    <LinearLayout        android:id="@+id/fl_menu"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:orientation="vertical"        android:paddingBottom="40dp"        android:paddingLeft="10dp"        android:paddingTop="45dp"        android:background="#f43">        <TextView            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:textSize="18sp"            android:text="这是顶面板" />    </LinearLayout>    <LinearLayout        android:id="@+id/main_content"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:orientation="vertical"        android:paddingBottom="40dp"        android:paddingLeft="10dp"        android:paddingTop="50dp"        android:background="#ae3">        <TextView            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:textSize="18sp"            android:text="这是主面板" />    </LinearLayout></com.example.duodian.DragLayout>


本文章如有地方需要修改请在下方评论中指出。



阅读全文
0 0