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
- ScrollView中嵌套ViewPager,ViewPager中使用FlowLayout
- scrollview中嵌套ViewPager
- android中viewpager,scrollview的嵌套问题
- android中viewpager,scrollview的嵌套问题
- android中viewpager,scrollview的嵌套问题
- scrollview中嵌套viewpager出现的兼容问题
- android---在ScrollView中嵌套ViewPager
- 在ScrollView中嵌套ViewPager,ViewPager不能显示的解决办法
- Android中Viewpager,ScrollView嵌套ViewPager滑动冲突解决
- GridView嵌套在ViewPager中,ViewPager嵌套在ScrollView中不显示
- GridView嵌套在ViewPager中,ViewPager嵌套在ScrollView中,GridView显示不全问题
- Viewpager中嵌套ListView
- ScrollView或者ListView中嵌套ViewPager,展示不出来问题。
- android中viewpager,scrollview、listview的嵌套问题
- ScrollView或者ListView中嵌套ViewPager,展示不出来问题。
- Android笔记 android中viewpager,scrollview的嵌套问题
- 关于ScrollView中嵌套ListView和Viewpager问题
- Android:ScrollView中嵌套ViewPager和ListView示例
- 【算法】:求Fibonacci的多种思路和算法
- CakePHP命名约定
- Ubuntu16.04配置TensorFlow
- VoLTE的前世今生...说清楚VoIP、VoLTE、CSFB、VoWiFi、SIP、IMS那些事...
- 从NV中读取之前保存的网络信息
- ScrollView中嵌套ViewPager,ViewPager中使用FlowLayout
- 1118. Birds in Forest (25)
- 初来乍到,请多关照
- Poj 3661 Running(DP)
- Linux服务器性能检测常用工具
- 每日170227-29
- 前端之路——张根根篇
- Android下拉/上拉刷新ListView之Android-PullToRefresh
- 数据结构实验之栈六:下一较大值(二)