ScrollView中嵌套ViewPager,ViewPager中使用FlowLayout

来源:互联网 发布:python多线程加锁 编辑:程序博客网 时间:2024/04/30 04:12

之前做过一个viewpager嵌套页面:可上下滑动的Layout中嵌套一个自定义的ViewPager,viewPager中嵌套FlowLayout。

整体效果如下图1所示。


上滑到顶部效果如图2:


代码清单文件如下:

1.ScrollableLayout.java

import android.annotation.TargetApi;import android.content.Context;import android.os.Build;import android.support.v4.view.ViewPager;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.VelocityTracker;import android.view.View;import android.view.ViewConfiguration;import android.widget.LinearLayout;import android.widget.Scroller;public class ScrollableLayout extends LinearLayout {    private final String tag = "cp:scrollableLayout";    private float mDownX;    private float mDownY;    private float mLastY;    private int minY = 0;    private int maxY = 0;    private int mHeadHeight;    private int mExpandHeight;    private int mTouchSlop;    private int mMinimumVelocity;    private int mMaximumVelocity;    // 方向    private DIRECTION mDirection;    private int mCurY;    private int mLastScrollerY;    private boolean needCheckUpdown;    private boolean updown;    private boolean mDisallowIntercept;    private boolean isClickHead;    private boolean isClickHeadExpand;    private View mHeadView;    private ViewPager childViewPager;    private Scroller mScroller;    private VelocityTracker mVelocityTracker;    /**     * 滑动方向 *     */    enum DIRECTION {        UP,// 向上划        DOWN// 向下划    }    public interface OnScrollListener {        void onScroll(int currentY, int maxY);    }    private OnScrollListener onScrollListener;    public void setOnScrollListener(OnScrollListener onScrollListener) {        this.onScrollListener = onScrollListener;    }    private ScrollableHelper mHelper;    public ScrollableHelper getHelper() {        return mHelper;    }    public ScrollableLayout(Context context) {        super(context);        init(context);    }    public ScrollableLayout(Context context, AttributeSet attrs) {        super(context, attrs);        init(context);    }    @TargetApi(Build.VERSION_CODES.HONEYCOMB)    public ScrollableLayout(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init(context);    }    @TargetApi(Build.VERSION_CODES.LOLLIPOP)    public ScrollableLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {        super(context, attrs, defStyleAttr, defStyleRes);        init(context);    }    private void init(Context context) {        mHelper = new ScrollableHelper();        mScroller = new Scroller(context);        final ViewConfiguration configuration = ViewConfiguration.get(context);        mTouchSlop = configuration.getScaledTouchSlop();        mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();        mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();    }    public boolean isSticked() {        return mCurY == maxY;    }    /**     * 扩大头部点击滑动范围     *     * @param expandHeight     */    public void setClickHeadExpand(int expandHeight) {        mExpandHeight = expandHeight;    }    public int getMaxY() {        return maxY;    }    public boolean isHeadTop() {        return mCurY == minY;    }    public boolean canPtr() {        return updown && mCurY == minY && mHelper.isTop();    }    public void requestScrollableLayoutDisallowInterceptTouchEvent(boolean disallowIntercept) {        super.requestDisallowInterceptTouchEvent(disallowIntercept);        mDisallowIntercept = disallowIntercept;    }    @Override    public boolean dispatchTouchEvent(MotionEvent ev) {        float currentX = ev.getX();        float currentY = ev.getY();        float deltaY;        int shiftX = (int) Math.abs(currentX - mDownX);        int shiftY = (int) Math.abs(currentY - mDownY);        switch (ev.getAction()) {            case MotionEvent.ACTION_DOWN:                mDisallowIntercept = false;                needCheckUpdown = true;                updown = true;                mDownX = currentX;                mDownY = currentY;                mLastY = currentY;                checkIsClickHead((int) currentY, mHeadHeight, getScrollY());                checkIsClickHeadExpand((int) currentY, mHeadHeight, getScrollY());                initOrResetVelocityTracker();                mVelocityTracker.addMovement(ev);                mScroller.forceFinished(true);                break;            case MotionEvent.ACTION_MOVE:                if (mDisallowIntercept) {                    break;                }                initVelocityTrackerIfNotExists();                mVelocityTracker.addMovement(ev);                deltaY = mLastY - currentY;                if (needCheckUpdown) {                    if (shiftX > mTouchSlop && shiftX > shiftY) {                        needCheckUpdown = false;                        updown = false;                    } else if (shiftY > mTouchSlop && shiftY > shiftX) {                        needCheckUpdown = false;                        updown = true;                    }                }                if (updown && shiftY > mTouchSlop && shiftY > shiftX &&                        (!isSticked() || mHelper.isTop() || isClickHeadExpand)) {                    if (childViewPager != null) {                        childViewPager.requestDisallowInterceptTouchEvent(true);                    }                    scrollBy(0, (int) (deltaY + 0.5));                }                mLastY = currentY;                break;            case MotionEvent.ACTION_UP:                if (updown && shiftY > shiftX && shiftY > mTouchSlop) {                    mVelocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);                    float yVelocity = -mVelocityTracker.getYVelocity();                    boolean dislowChild = false;                    if (Math.abs(yVelocity) > mMinimumVelocity) {                        mDirection = yVelocity > 0 ? DIRECTION.UP : DIRECTION.DOWN;                        if ((mDirection == DIRECTION.UP && isSticked()) || (!isSticked() && getScrollY() == 0 && mDirection == DIRECTION.DOWN)) {                            dislowChild = true;                        } else {                            mScroller.fling(0, getScrollY(), 0, (int) yVelocity, 0, 0, -Integer.MAX_VALUE, Integer.MAX_VALUE);                            mScroller.computeScrollOffset();                            mLastScrollerY = getScrollY();                            invalidate();                        }                    }                    if (!dislowChild && (isClickHead || !isSticked())) {                        int action = ev.getAction();                        ev.setAction(MotionEvent.ACTION_CANCEL);                        boolean dispathResult = super.dispatchTouchEvent(ev);                        ev.setAction(action);                        return dispathResult;                    }                }                break;            default:                break;        }        super.dispatchTouchEvent(ev);        return true;    }    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)    private int getScrollerVelocity(int distance, int duration) {        if (mScroller == null) {            return 0;        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {            return (int) mScroller.getCurrVelocity();        } else {            return distance / duration;        }    }    @Override    public void computeScroll() {        if (mScroller.computeScrollOffset()) {            final int currY = mScroller.getCurrY();            if (mDirection == DIRECTION.UP) {                // 手势向上划                if (isSticked()) {                    int distance = mScroller.getFinalY() - currY;                    int duration = calcDuration(mScroller.getDuration(), mScroller.timePassed());                    mHelper.smoothScrollBy(getScrollerVelocity(distance, duration), distance, duration);                    mScroller.forceFinished(true);                    return;                } else {                    scrollTo(0, currY);                }            } else {                // 手势向下划                if (mHelper.isTop() || isClickHeadExpand) {                    int deltaY = (currY - mLastScrollerY);                    int toY = getScrollY() + deltaY;                    scrollTo(0, toY);                    if (mCurY <= minY) {                        mScroller.forceFinished(true);                        return;                    }                }                invalidate();            }            mLastScrollerY = currY;        }    }    @Override    public void scrollBy(int x, int y) {        int scrollY = getScrollY();        int toY = scrollY + y;        if (toY >= maxY) {            toY = maxY;        } else if (toY <= minY) {            toY = minY;        }        y = toY - scrollY;        super.scrollBy(x, y);    }    @Override    public void scrollTo(int x, int y) {        if (y >= maxY) {            y = maxY;        } else if (y <= minY) {            y = minY;        }        mCurY = y;        if (onScrollListener != null) {            onScrollListener.onScroll(y, maxY);        }        super.scrollTo(x, y);    }    private void initOrResetVelocityTracker() {        if (mVelocityTracker == null) {            mVelocityTracker = VelocityTracker.obtain();        } else {            mVelocityTracker.clear();        }    }    private void initVelocityTrackerIfNotExists() {        if (mVelocityTracker == null) {            mVelocityTracker = VelocityTracker.obtain();        }    }    private void recycleVelocityTracker() {        if (mVelocityTracker != null) {            mVelocityTracker.recycle();            mVelocityTracker = null;        }    }    private void checkIsClickHead(int downY, int headHeight, int scrollY) {        isClickHead = downY + scrollY <= headHeight;    }    private void checkIsClickHeadExpand(int downY, int headHeight, int scrollY) {        if (mExpandHeight <= 0) {            isClickHeadExpand = false;        }        isClickHeadExpand = downY + scrollY <= headHeight + mExpandHeight;    }    private int calcDuration(int duration, int timepass) {        return duration - timepass;    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        mHeadView = getChildAt(0);        measureChildWithMargins(mHeadView, widthMeasureSpec, 0, MeasureSpec.UNSPECIFIED, 0);        maxY = mHeadView.getMeasuredHeight();        mHeadHeight = mHeadView.getMeasuredHeight();        super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec) + maxY, MeasureSpec.EXACTLY));    }    @Override    protected void onFinishInflate() {        if (mHeadView != null && !mHeadView.isClickable()) {            mHeadView.setClickable(true);        }        int childCount = getChildCount();        for (int i = 0; i < childCount; i++) {            View childAt = getChildAt(i);            if (childAt != null && childAt instanceof ViewPager) {                childViewPager = (ViewPager) childAt;            }        }        super.onFinishInflate();    }}


2.DetailFragment.java

计算ViewPager高度。

mCustomViewPager.getViewTreeObserver().addOnGlobalLayoutListener(                new ViewTreeObserver.OnGlobalLayoutListener() {                    @Override                    public void onGlobalLayout() {                        if (mCustomViewPager.getHeight() > 0)                            mCustomViewPager.getViewTreeObserver().removeGlobalOnLayoutListener(this);                        FlowLayout flow = null;                        for (int i = 0; i < mCustomViewPager.getChildCount(); i++) {                            flow = (FlowLayout) mCustomViewPager.getChildAt(i);                            if (null != flow && mFlowLayoutHeight < (flow.getChildHeights() + flow.getTotalLines() * 14)) {                                mFlowLayoutHeight = flow.getChildHeights() + flow.getTotalLines() * 14;                                ViewGroup.LayoutParams lp = mCustomViewPager.getLayoutParams();                                lp.height = LocalDisplay.dp2px(mFlowLayoutHeight);                                mCustomViewPager.setLayoutParams(lp);                            }                        }                    }                });

标题栏滑动渐变

mScrollLayout.setOnScrollListener(new ScrollableLayout.OnScrollListener() {            @Override            public void onScroll(int currentY, int maxY) {                ViewHelper.setTranslationY(mRlhead, (float) (currentY * 0.5));                if (currentY <= 0) {                    mTvBarTitle.setTextColor(Color.argb((int) 0, 66, 66, 66));//AGB由相关工具获得,或者美工提供或者美工提供                    mLine.setBackgroundColor(Color.argb((int) 0, 217, 217, 217));                    mTitleWholeArea.setBackgroundColor(Color.argb((int) 0, 251, 251, 251));                } else if (currentY > 0 && currentY <= mHeight) {                    float scale = (float) currentY / mHeight;                    float alpha = (255 * scale);                    // 只是layout背景透明(仿知乎滑动效果)                    mTvBarTitle.setTextColor(Color.argb((int) alpha, 66, 66, 66));                    mLine.setBackgroundColor(Color.argb((int) alpha, 217, 217, 217));                    mTitleWholeArea.setBackgroundColor(Color.argb((int) alpha, 251, 251, 251));                } else {                    mTvBarTitle.setTextColor(Color.argb((int) 255, 66, 66, 66));                    mLine.setBackgroundColor(Color.argb((int) 255, 217, 217, 217));                    mTitleWholeArea.setBackgroundColor(Color.argb((int) 255, 251, 251, 251));                }            }        });

布局文件如下

<com.xw.merchant.widget.scrollable.ScrollableLayout        android:id="@+id/scrollableLayout"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:layout_alignParentLeft="true"        android:layout_alignParentStart="true"        android:layout_below="@+id/ll_title_bar"        android:orientation="vertical">        <RelativeLayout            android:id="@+id/rl_head"            android:layout_width="match_parent"            android:layout_height="wrap_content">            <LinearLayout                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:background="@color/_white"                android:orientation="vertical">                <TextView                    android:id="@+id/tv_customer_name"                    android:layout_width="wrap_content"                    android:layout_height="wrap_content"                    android:layout_gravity="center"                    android:layout_marginTop="@dimen/_gap_large"                    android:text="黑手未入党"                    android:textColor="@color/_color_gray5"                    android:textSize="@dimen/_space_xxxlarge"                    android:textStyle="bold" />                <LinearLayout                    android:layout_width="match_parent"                    android:layout_height="wrap_content"                    android:layout_marginTop="@dimen/_space_small"                    android:gravity="center"                    android:orientation="horizontal">                    <View                        android:layout_width="@dimen/xw_gap_team_item_xxxlarge"                        android:layout_height="@dimen/_line_thin"                        android:layout_gravity="center"                        android:layout_marginRight="@dimen/_gap_small"                        android:background="@color/_textcolorHint" />                    <TextView                        android:id="@+id/tv_customer_mobile"                        android:layout_width="wrap_content"                        android:layout_height="wrap_content"                        android:layout_gravity="center"                        android:gravity="center_horizontal"                        android:text="18617080737"                        android:textColor="@color/_color_gray5"                        android:textSize="@dimen/_text_size_medium" />                    <View                        android:layout_width="@dimen/_gap_team_item_xxxlarge"                        android:layout_height="@dimen/_line_thin"                        android:layout_gravity="center"                        android:layout_marginLeft="@dimen/_gap_small"                        android:background="@color/_textcolorHint" />                </LinearLayout>                <LinearLayout                    android:layout_width="match_parent"                    android:layout_height="wrap_content"                    android:layout_marginTop="@dimen/_space_small"                    android:gravity="center"                    android:orientation="horizontal">                    <TextView                        android:id="@+id/tv_my_customer_state"                        android:layout_width="wrap_content"                        android:layout_height="@dimen/_text_size_large"                        android:background="@drawable/_sl_not_assign_customer"                        android:gravity="center"                        android:paddingLeft="@dimen/_space_small"                        android:paddingRight="@dimen/_space_small"                        android:text="@string/_consumption_un_assign"                        android:textColor="@color/_white"                        android:textSize="@dimen/_space_small_nine" />                    <TextView                        android:id="@+id/tv_staff_state"                        android:layout_width="wrap_content"                        android:layout_height="wrap_content"                        android:layout_marginLeft="@dimen/_space_tiny"                        android:gravity="center"                        android:text="@string/_customer_distribution_status2"                        android:textColor="@color/_color_yellow"                        android:textSize="@dimen/_gap_small"                        android:visibility="gone" />                </LinearLayout>                <LinearLayout                    android:layout_width="wrap_content"                    android:layout_height="wrap_content"                    android:layout_gravity="center"                    android:layout_marginLeft="@dimen/_gap_team_item_xxxlarge"                    android:layout_marginRight="@dimen/_gap_team_item_xxxlarge"                    android:orientation="vertical">                    <TextView                        android:id="@+id/tv_hd_empty"                        android:layout_width="1dp"                        android:layout_height="@dimen/_gap_medium"                        android:background="@color/_white"                        android:gravity="center"                        android:visibility="invisible" />                    <com.xw.merchant.widget.CustomViewPager                        android:id="@+id/customViewPager"                        android:layout_width="wrap_content"                        android:layout_height="1dp"                        android:gravity="center" />                    <com.xw.merchant.widget.indicator.CirclePageIndicator                        android:id="@+id/indicator"                        android:layout_width="match_parent"                        android:layout_height="wrap_content"                        android:layout_gravity="bottom"                        android:visibility="gone"                        app:fillColor="@color/_textcolor_assist"                        app:pageColor="#32000000"                        app:strokeWidth="0dp" />                </LinearLayout>            </LinearLayout>        </RelativeLayout>        <LinearLayout            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:background="@color/_white"            android:gravity="center"            android:orientation="horizontal"            android:paddingBottom="@dimen/_xxxlarge"            android:paddingTop="@dimen/_xxxlarge">            <ImageView                android:id="@+id/iv_btn_phone"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:layout_gravity="center_horizontal"                android:src="@drawable/_phone" />            <ImageView                android:id="@+id/iv_btn_send_msg"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:layout_gravity="center_horizontal"                android:layout_marginLeft="@dimen/_xxxlarge"                android:src="@drawable/_sms" />            <ImageView                android:id="@+id/iv_btn_upd"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:layout_gravity="center_horizontal"                android:layout_marginLeft="@dimen/_xxxlarge"                android:src="@drawable/_upd" />            <ImageView                android:id="@+id/iv_btn_del"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:layout_gravity="center_horizontal"                android:layout_marginLeft="@dimen/_xxxlarge"                android:src="@drawable/_del" />        </LinearLayout>        <LinearLayout            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:background="@drawable/tab_sliding_back"            android:gravity="center">            <com.xw.merchant.widget.scrollable.CustomPagerSlidingTabStrip                android:id="@+id/pagerStrip"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:layout_alignParentBottom="true"                android:layout_gravity="center_horizontal"                android:background="@color/transparent"></com.xw.merchant.widget.scrollable.CustomPagerSlidingTabStrip>        </LinearLayout>        <android.support.v4.view.ViewPager            android:id="@+id/viewpager"            android:layout_width="match_parent"            android:layout_height="match_parent" />    </com.xw.merchant.widget.scrollable.ScrollableLayout>



1 0
原创粉丝点击