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) { }
});
上一篇:用Window Authentication的方式去连接SQLServer


下一篇:使用 TypeScript,React,ANTLR 和 Monaco Editor 创建一个自定义 Web 编辑器(二)