Android--仿1号店继续拖动查看图文详情——一个自定义的ViewGroup
声明:源代码不是我写的,是网上的以为大神写的(地址给忘了),我拿过来以后呢,稍微改动了一下源码,使之符合了项目需求,再次特别感谢那位大牛,非常感谢。
是一个自定义布局,继承自ViewGroup
package com.storelibrary.ui.custom.widget; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.content.Context; import android.content.res.TypedArray; import android.os.Parcel; import android.os.Parcelable; import android.support.v4.view.MotionEventCompat; import android.support.v4.view.ViewCompat; import android.support.v4.view.ViewPager; import android.support.v7.widget.RecyclerView; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.widget.AbsListView; import android.widget.FrameLayout; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.ScrollView; import newair.com.storelibrary.R; import newair.com.storelibrary.utils.L; /** * ----仿京东、淘宝、一号店商品详情上拉显示图文详情------ */ @SuppressWarnings("unused") public class SlideDetailsLayout extends ViewGroup { public static final String TAG = "slide"; public static final boolean DEBUG = true; public boolean isTop = true; /** * Callback for panel OPEN-CLOSE status changed. */ public interface OnSlideDetailsListener { /** * Called after status changed. * * @param status {@link Status} */ void onStatusChanged(Status status); } public enum Status { /** * Panel is closed */ CLOSE, /** * Panel is opened */ OPEN; public static Status valueOf(int stats) { if (0 == stats) { return CLOSE; } else if (1 == stats) { return OPEN; } else { return CLOSE; } } } private static final float DEFAULT_PERCENT = 0.2f; private static final int DEFAULT_DURATION = 200; private View mFrontView; private View mBehindView; private float mTouchSlop; private float mInitMotionY; private float mInitMotionX; private View mTarget; private float mSlideOffset; private Status mStatus = Status.CLOSE; private boolean isFirstShowBehindView = true; private float mPercent = DEFAULT_PERCENT; private long mDuration = DEFAULT_DURATION; private int mDefaultPanel = 0; private OnSlideDetailsListener mOnSlideDetailsListener; public SlideDetailsLayout(Context context) { this(context, null); } public SlideDetailsLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } public SlideDetailsLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SlideDetailsLayout, defStyleAttr, 0); mPercent = a.getFloat(R.styleable.SlideDetailsLayout_percent, DEFAULT_PERCENT); mDuration = a.getInt(R.styleable.SlideDetailsLayout_duration, DEFAULT_DURATION); mDefaultPanel = a.getInt(R.styleable.SlideDetailsLayout_default_panel, 0); a.recycle(); mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); } /** * Set the callback of panel OPEN-CLOSE status. * * @param listener {@link OnSlideDetailsListener} */ public void setOnSlideDetailsListener(OnSlideDetailsListener listener) { this.mOnSlideDetailsListener = listener; } /** * Open pannel smoothly. * * @param smooth true, smoothly. false otherwise. */ public void smoothOpen(boolean smooth) { if (mStatus != Status.OPEN) { mStatus = Status.OPEN; final float height = -getMeasuredHeight(); animatorSwitch(0, height, true, smooth ? mDuration : 0); } } /** * Close pannel smoothly. * * @param smooth true, smoothly. false otherwise. */ public void smoothClose(boolean smooth) { if (mStatus != Status.CLOSE) { mStatus = Status.OPEN; final float height = -getMeasuredHeight(); animatorSwitch(height, 0, true, smooth ? mDuration : 0); } } /** * Set the float value for indicate the moment of switch panel * * @param percent (0.0, 1.0) */ public void setPercent(float percent) { this.mPercent = percent; } @Override protected LayoutParams generateDefaultLayoutParams() { return new MarginLayoutParams(MarginLayoutParams.WRAP_CONTENT, MarginLayoutParams.WRAP_CONTENT); } @Override public LayoutParams generateLayoutParams(AttributeSet attrs) { return new MarginLayoutParams(getContext(), attrs); } @Override protected LayoutParams generateLayoutParams(LayoutParams p) { return new MarginLayoutParams(p); } @Override protected void onFinishInflate() { super.onFinishInflate(); final int childCount = getChildCount(); if (1 >= childCount) { throw new RuntimeException("SlideDetailsLayout only accept childs more than 1!!"); } mFrontView = getChildAt(0); mBehindView = getChildAt(1); // set behindview's visibility to GONE before show. // mBehindView.setVisibility(GONE); if (mDefaultPanel == 1) { post(new Runnable() { @Override public void run() { smoothOpen(false); } }); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { final int pWidth = MeasureSpec.getSize(widthMeasureSpec); final int pHeight = MeasureSpec.getSize(heightMeasureSpec); final int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(pWidth, MeasureSpec.EXACTLY); final int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(pHeight, MeasureSpec.EXACTLY); View child; for (int i = 0; i < getChildCount(); i++) { child = getChildAt(i); // skip measure if gone if (child.getVisibility() == GONE) { continue; } measureChild(child, childWidthMeasureSpec, childHeightMeasureSpec); } setMeasuredDimension(pWidth, pHeight); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { final int left = l; final int right = r; int top; int bottom; final int offset = (int) mSlideOffset; View child; for (int i = 0; i < getChildCount(); i++) { child = getChildAt(i); // skip layout if (child.getVisibility() == GONE) { continue; } if (child == mBehindView) { top = b + offset; bottom = top + b - t; } else { top = t + offset; bottom = b + offset; } child.layout(left, top, right, bottom); } } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { ensureTarget(); if (null == mTarget) { return false; } if (!isEnabled()) { return false; } final int aciton = MotionEventCompat.getActionMasked(ev); boolean shouldIntercept = false; switch (aciton) { case MotionEvent.ACTION_DOWN: { mInitMotionX = ev.getX(); mInitMotionY = ev.getY(); shouldIntercept = false; break; } case MotionEvent.ACTION_MOVE: { final float x = ev.getX(); final float y = ev.getY(); final float xDiff = x - mInitMotionX; final float yDiff = y - mInitMotionY; if (canChildScrollVertically((int) yDiff)) { shouldIntercept = false; if (DEBUG) { Log.d(TAG, "intercept, child can scroll vertically, do not intercept"); } } else { final float xDiffabs = Math.abs(xDiff); final float yDiffabs = Math.abs(yDiff); // intercept rules: // 1. The vertical displacement is larger than the horizontal displacement; // 2. Panel stauts is CLOSE:slide up // 3. Panel status is OPEN:slide down if (yDiffabs > mTouchSlop && yDiffabs >= xDiffabs && !(mStatus == Status.CLOSE && yDiff > 0 || mStatus == Status.OPEN && yDiff < 0)) { shouldIntercept = true; if (DEBUG) { Log.d(TAG, "intercept, intercept events"); } } } break; } case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: { shouldIntercept = false; break; } } return shouldIntercept; } @Override public boolean onTouchEvent(MotionEvent ev) { ensureTarget(); if (null == mTarget) { return false; } if (!isEnabled()) { return false; } boolean wantTouch = true; final int action = MotionEventCompat.getActionMasked(ev); switch (action) { case MotionEvent.ACTION_DOWN: { // if target is a view, we want the DOWN action. if (mTarget instanceof View) { wantTouch = true; } break; } case MotionEvent.ACTION_MOVE: { final float y = ev.getY(); final float yDiff = y - mInitMotionY; if (canChildScrollVertically(((int) yDiff))) { wantTouch = false; } else { processTouchEvent(yDiff); wantTouch = true; } break; } case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: { finishTouchEvent(); wantTouch = false; break; } } return wantTouch; } /** * @param offset Displacement in vertically. */ private void processTouchEvent(final float offset) { if (Math.abs(offset) < mTouchSlop) { return; } final float oldOffset = mSlideOffset; // pull up to open if (mStatus == Status.CLOSE) { // reset if pull down if (offset >= 0) { mSlideOffset = 0; } else { mSlideOffset = offset; } if (mSlideOffset == oldOffset) { return; } // pull down to close } else if (mStatus == Status.OPEN) { final float pHeight = -getMeasuredHeight(); // reset if pull up if (offset <= 0) { mSlideOffset = pHeight; } else { final float newOffset = pHeight + offset; mSlideOffset = newOffset; } if (mSlideOffset == oldOffset) { return; } } if (DEBUG) { Log.v("slide", "process, offset: " + mSlideOffset); } // relayout requestLayout(); } /** * Called after gesture is ending. */ private void finishTouchEvent() { final int pHeight = getMeasuredHeight(); // final int percent = (int) (pHeight * mPercent); final int percent = 200; final float offset = mSlideOffset; if (DEBUG) { Log.d("slide", "finish, offset: " + offset + ", percent: " + percent); } boolean changed = false; if (Status.CLOSE == mStatus) { if (offset <= -percent) { mSlideOffset = -pHeight; mStatus = Status.OPEN; changed = true; } else { // keep panel closed mSlideOffset = 0; } } else if (Status.OPEN == mStatus) { if ((offset + pHeight) >= percent) { mSlideOffset = 0; mStatus = Status.CLOSE; changed = true; } else { // keep panel opened mSlideOffset = -pHeight; } } animatorSwitch(offset, mSlideOffset, changed); } private void animatorSwitch(final float start, final float end) { animatorSwitch(start, end, true, mDuration); } private void animatorSwitch(final float start, final float end, final long duration) { animatorSwitch(start, end, true, duration); } private void animatorSwitch(final float start, final float end, final boolean changed) { animatorSwitch(start, end, changed, mDuration); } private void animatorSwitch(final float start, final float end, final boolean changed, final long duration) { ValueAnimator animator = ValueAnimator.ofFloat(start, end); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { mSlideOffset = (float) animation.getAnimatedValue(); requestLayout(); } }); animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); if (changed) { if (mStatus == Status.OPEN) { checkAndFirstOpenPanel(); } if (null != mOnSlideDetailsListener) { mOnSlideDetailsListener.onStatusChanged(mStatus); } } } }); animator.setDuration(duration); animator.start(); } /** * Whether the closed pannel is opened at first time. * If open first, we should set the behind view's visibility as VISIBLE. */ private void checkAndFirstOpenPanel() { if (isFirstShowBehindView) { isFirstShowBehindView = false; mBehindView.setVisibility(VISIBLE); } } /** * When pulling, target view changed by the panel status. If panel opened, the target is behind view. * Front view is for otherwise. */ private void ensureTarget() { if (mStatus == Status.CLOSE) { mTarget = mFrontView; } else { mTarget = mBehindView; } } //ViewPager的当前所在位置 public int viewPagerCurrent = 0; public int getViewPagerCurrent() { return viewPagerCurrent; } public void setViewPagerCurrent(int viewPagerCurrent) { this.viewPagerCurrent = viewPagerCurrent; } /** * Check child view can srcollable in vertical direction. * * @param direction Negative to check scrolling up, positive to check scrolling down. * @return true if this view can be scrolled in the specified direction, false otherwise. */ protected boolean canChildScrollVertically(int direction) { if (mTarget instanceof AbsListView) { return canListViewSroll((AbsListView) mTarget); } else if (mTarget instanceof FrameLayout || mTarget instanceof RelativeLayout || mTarget instanceof LinearLayout) { View child; for (int i = 0; i < ((ViewGroup) mTarget).getChildCount(); i++) { child = ((ViewGroup) mTarget).getChildAt(i); if (child instanceof AbsListView) { return canListViewSroll((AbsListView) child); } else if (child instanceof ScrollView) { return canScrollViewSroll((ScrollView) child); } else if (child instanceof ViewPager) { ViewPager pager = (ViewPager) child; View child2 = pager.getChildAt(viewPagerCurrent); if (child2 instanceof RecyclerView) { return canRecyclerViewSroll((RecyclerView) child2); } else if (child2 instanceof ScrollView) { return canScrollViewSroll((ScrollView) child2); } } } } if (android.os.Build.VERSION.SDK_INT < 14) { return ViewCompat.canScrollVertically(mTarget, -direction) || mTarget.getScrollY() > 0; } else { return ViewCompat.canScrollVertically(mTarget, -direction); } } protected boolean canListViewSroll(AbsListView absListView) { if (mStatus == Status.OPEN) { return absListView.getChildCount() > 0 && (absListView.getFirstVisiblePosition() > 0 || absListView.getChildAt(0) .getTop() < absListView.getPaddingTop()); } else { final int count = absListView.getChildCount(); return count > 0 && (absListView.getLastVisiblePosition() < count - 1 || absListView.getChildAt(count - 1) .getBottom() > absListView.getMeasuredHeight()); } } protected boolean canRecyclerViewSroll(RecyclerView absListView) { if (mStatus == Status.OPEN) { L.i(absListView.getScrollY() + ":scaleY" + "\t"); return absListView.getChildCount() > 0 && (absListView.getScrollY() > 0 || absListView.getChildAt(0) .getTop() < absListView.getPaddingTop()); } else { final int count = absListView.getChildCount(); return count > 0 && (absListView.getScrollY() <= count - 1 || absListView.getChildAt(count - 1) .getBottom() > absListView.getMeasuredHeight()); } } protected boolean canScrollViewSroll(ScrollView absListView) { if (mStatus == Status.OPEN) { L.i(absListView.getScrollY() + ":scaleY" + "\t" + absListView.getChildAt(0) .getTop() + "=== " + absListView.getPaddingTop()); return absListView.getChildCount() > 0 && (absListView.getScrollY() > 0 || absListView.getChildAt(0) .getTop() < absListView.getPaddingTop()); } else { final int count = absListView.getChildCount(); return count > 0 && (absListView.getScrollY() <= count - 1 || absListView.getChildAt(count - 1) .getBottom() > absListView.getMeasuredHeight()); } } @Override protected Parcelable onSaveInstanceState() { SavedState ss = new SavedState(super.onSaveInstanceState()); ss.offset = mSlideOffset; ss.status = mStatus.ordinal(); return ss; } @Override protected void onRestoreInstanceState(Parcelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); mSlideOffset = ss.offset; mStatus = Status.valueOf(ss.status); if (mStatus == Status.OPEN) { mBehindView.setVisibility(VISIBLE); } requestLayout(); } static class SavedState extends BaseSavedState { private float offset; private int status; /** * Constructor used when reading from a parcel. Reads the state of the superclass. * * @param source */ public SavedState(Parcel source) { super(source); offset = source.readFloat(); status = source.readInt(); } /** * Constructor called by derived classes when creating their SavedState objects * * @param superState The state of the superclass of this view */ public SavedState(Parcelable superState) { super(superState); } @Override public void writeToParcel(Parcel out, int flags) { super.writeToParcel(out, flags); out.writeFloat(offset); out.writeInt(status); } public static final Creator<SavedState> CREATOR = new Creator<SavedState>() { public SavedState createFromParcel(Parcel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } }
2、这个自定义布局使用起来也非常的方便---还是代码直接点
这里面能放两个Viewgroup,第二个Viewgroup就是拖出来的viewgroup--下面的界面是直接仿照的一号店的
<com.storelibrary.ui.custom.widget.SlideDetailsLayout android:id="@+id/SlideDetailsLayout" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_above="@+id/ll_bottom_layout"> <ScrollView android:id="@+id/sl_top_details" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_above="@+id/ll_bottom_layout" android:focusable="true" android:focusableInTouchMode="true" android:gravity="center" android:scrollbars="none"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <android.support.v4.view.ViewPager android:id="@+id/vp_goods_details" android:layout_width="match_parent" android:layout_height="300dp" android:visibility="visible" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentEnd="true" android:layout_alignParentRight="true" android:orientation="horizontal" android:padding="10dp"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:clickable="true" android:src="@drawable/good_details_collection" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:clickable="true" android:src="@drawable/good_details_share" /> </LinearLayout> </RelativeLayout> <View android:layout_width="match_parent" android:layout_height="0.5dp" android:background="#d9d9d9" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="10dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/item_good_details_icon_style" android:text="自营" android:textColor="#ef4c4c" android:textSize="12sp" /> <TextView android:id="@+id/tv_goods_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:text="沙宣 修复水养 洗发露 750ml" /> </LinearLayout> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="5dp" android:hint="水感润养,发型丰盈可塑" android:textSize="12sp" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="5dp" android:gravity="center_vertical" android:orientation="horizontal"> <TextView android:id="@+id/tv_goods_price" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="¥58.9" android:textColor="#f23333" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:background="#e49a39" android:paddingLeft="2dp" android:paddingRight="2dp" android:text="比PC省¥1.0" android:textColor="#fff" android:textSize="12sp" /> </LinearLayout> </LinearLayout> <View android:layout_width="match_parent" android:layout_height="0.5dp" android:background="#dcdbdb" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="10dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:text="选择" /> <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_weight="1" android:gravity="center_vertical" android:text="选择规格" android:textColor="#1b1b1b" android:textSize="12sp" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/good_details_arrows_right" /> </LinearLayout> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="送至" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="山东省 济南市 历下区" android:textColor="#202020" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="5dp" android:hint="现货,12:00前完成订单,预计1天内到达" /> <View android:layout_width="match_parent" android:layout_height="0.5dp" android:layout_marginTop="10dp" android:background="#dedede" /> </LinearLayout> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginTop="10dp" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="服务" /> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginLeft="10dp" android:gravity="center_vertical" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:hint="支持货到付款" android:textSize="12sp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:hint="1贵就赔" android:textSize="12sp" /> </LinearLayout> </LinearLayout> </LinearLayout> <View android:layout_width="match_parent" android:layout_height="10dp" android:background="#e1e1e1" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="10dp"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="商品评价 (44804)" android:textColor="#393939" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentEnd="true" android:layout_alignParentRight="true" android:gravity="center_vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="97%" android:textColor="#f14d4d" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:drawableRight="@drawable/good_details_arrows_right" android:gravity="center_vertical" android:text="好评" /> </LinearLayout> </RelativeLayout> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center_vertical" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="评分" /> <RatingBar style="@android:style/Widget.Holo.RatingBar.Small" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:hint="还可以,不错不错" android:textSize="12sp" /> </LinearLayout> <View android:layout_width="match_parent" android:layout_height="10dp" android:background="#e1e1e1" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <RelativeLayout android:layout_width="match_parent" android:layout_height="40dp" android:paddingLeft="10dp" android:paddingRight="10dp"> <ImageView android:id="@+id/iv_search_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:src="@drawable/ic_skip_next_black_36dp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginLeft="20dp" android:layout_toRightOf="@+id/iv_search_icon" android:text="VS/沙宣" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:text="搜索" /> </RelativeLayout> <View android:layout_width="match_parent" android:layout_height="0.5dp" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:background="#e2e2e2" /> <LinearLayout android:layout_width="match_parent" android:layout_height="40dp" android:gravity="center" android:paddingLeft="10dp" android:paddingRight="10dp"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="联系客服" /> </LinearLayout> </LinearLayout> <View android:layout_width="match_parent" android:layout_height="10dp" android:background="#e1e1e1" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="10dp"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:hint="买的人还会买" /> <View android:layout_width="match_parent" android:layout_height="0.5dp" android:layout_marginTop="10dp" android:background="#dfdfdf" /> <android.support.v7.widget.RecyclerView android:id="@+id/rv_recommend_goodsDetails" android:layout_width="match_parent" android:layout_height="wrap_content" android:focusable="false" android:focusableInTouchMode="false" /> <View android:layout_width="match_parent" android:layout_height="0.5dp" android:background="#dfdfdf" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="45dp" android:background="#e7e7e7" android:gravity="center" android:orientation="horizontal"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/goods_details_look_more" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="继续拖动查看图文详情" /> </LinearLayout> </LinearLayout> </ScrollView> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <android.support.design.widget.TabLayout android:id="@+id/tl" android:layout_width="match_parent" android:layout_height="45dp" app:tabGravity="fill" app:tabIndicatorColor="@android:color/holo_red_light" app:tabIndicatorHeight="3dp" app:tabSelectedTextColor="@android:color/black" app:tabTextColor="@android:color/darker_gray" /> <android.support.v4.view.ViewPager android:id="@+id/vp" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout> </com.storelibrary.ui.custom.widget.SlideDetailsLayout>
3、如何使用呢---很方便
①、先介绍第一个,他有一个打开还是关闭的监听
slideDetailsLayout = (SlideDetailsLayout) findViewById(R.id.SlideDetailsLayout); slideDetailsLayout.setOnSlideDetailsListener(new SlideDetailsLayout.OnSlideDetailsListener() { @Override public void onStatusChanged(SlideDetailsLayout.Status status) { switch (status) { case CLOSE://关闭了 break; case OPEN://打开了 break; } } });
②、如果拖拽出来的布局里面放着TabLaoout和viewpager的,别忘了下面的代码
List<View> myData = new ArrayList<>();
View pager_1 = View.inflate(this, R.layout.pager_goods_details_1, null);
View pager_2 = View.inflate(this, R.layout.pager_goods_details_2, null);
View pager_3 = View.inflate(this, R.layout.pager_goods_details_3, null);
myData.add(pager_1);
myData.add(pager_2);
myData.add(pager_3);
//数据源放三个Layout,(感觉这样不好,放三个fragment应该不错,我没试过会不会出现问题,小伙伴们可以试一试)
myGoodsDetailsVPAdapter = new MyGoodsDetailsVPAdapter(this, myData);
tl = (TabLayout) findViewById(R.id.tl); vp = (ViewPager) findViewById(R.id.vp); vp.setOffscreenPageLimit(3);//设置viewpager的强制缓存为3个(这里的话,是几个就设置为缓存几个,否则会由于viewPager缓存的问题,导致拖拽出来的布局无法滑动) vp.setAdapter(myGoodsDetailsVPAdapter); tl.setupWithViewPager(vp); tl.setTabsFromPagerAdapter(myGoodsDetailsVPAdapter); tl.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { @Override public void onTabSelected(TabLayout.Tab tab) { vp.setCurrentItem(tab.getPosition()); slideDetailsLayout.setViewPagerCurrent(tab.getPosition()); } @Override public void onTabUnselected(TabLayout.Tab tab) { } @Override public void onTabReselected(TabLayout.Tab tab) { } });
新人学习中,也不太会总结,有做的不对的地方希望各位大神指出,谢谢。