Android仿淘寶商品詳情拖動查看圖文詳情效果
效果圖:

最近要在公司的項目中實現(xiàn)這種效果,就自己動手實現(xiàn)了一下。
使用
GraphicDetailsLayout gdLayout = (GraphicDetailsLayout) findViewById(R.id.gdlayout);gdLayout.addFragment(new Fragment[] {new SpFragment(), new DeFragment()}, getSupportFragmentManager());
還是很簡單的,把上下兩個fragment添加到GraphicDetailsLayout 中就可以了
思路
從效果中可以看到上下兩個控件都是可以滾動的,初始化狀態(tài)下,下面的控件是隱藏在屏幕下面的;那我們設計最外面的布局是LinearLayout,然后LinearLayout里面放兩個ScrollView,ScrollView滾動到頂部或頂部的時候,告訴LinearLayout攔截事件,來實現(xiàn)兩個ScrollView的上下拖動效果。
實現(xiàn)
首先自定義一個ScrollView
public class GDScrollView extends ScrollView {private LinearLayout mLl;private int mLlHeight;public static final String TAG_ONE = "up";public static final String TAG_TWO = "down";public static final int ID_ONE = 11111;public static final int ID_TWO = 22222;private GraphicDetailsLayout.ScrollListener mScrollListener;public GDScrollView(Context context) {super(context); }public GDScrollView(Context context, AttributeSet attrs) {super(context, attrs);}public GDScrollView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}(Build.VERSION_CODES.LOLLIPOP)public GDScrollView(Context context, AttributeSet attrs, int defStyleAttr,int defStyleRes) {super(context, attrs, defStyleAttr, defStyleRes);}public void setScrollListener(GraphicDetailsLayout.ScrollListener scrollListener) {mScrollListener = scrollListener;}public void addFragment(Fragment fragment, FragmentManager fragmentManager) {FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();if(mLl == null) mLl = (LinearLayout) getChildAt(0);fragmentTransaction.replace(mLl.getId(), fragment);fragmentTransaction.commit(); }protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);mLlHeight = mLl.getMeasuredHeight();}protected void onFinishInflate() {super.onFinishInflate();mLl = (LinearLayout) getChildAt(0);}protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {super.onOverScrolled(scrollX, scrollY, clampedX, clampedY);if(getTag().equals(TAG_ONE)) {//上面的界面滾動到底部的時候if(isScrollBottom()) {criticalPointOperation(false, true, TAG_ONE);}}if(getTag().equals(TAG_TWO)) {//下面的界面滾動到頂部的時候if(getScrollY() <= 0) {criticalPointOperation(false, true, TAG_TWO);}}}private void criticalPointOperation(boolean allow, boolean intercept, String tag) {getParent().requestDisallowInterceptTouchEvent(allow);if(mScrollListener != null) mScrollListener.scrollBottom(intercept, tag); }public boolean isScrollBottom() {return getScrollY() >= (mLlHeight - getMeasuredHeight());}}
重寫onOverScrolled方法監(jiān)控滾動的狀態(tài),判斷不同的ScrollView滾動到頂部或者頂部觸發(fā)回調(diào)事件,把觸摸事件交給上層LinarLayout控件,來看看LinearLayout的onTouchEvent方法
@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_MOVE:if(mInitY == 0) {mInitY = event.getY();} else {int offset = (int) Math.abs(event.getY() - mInitY);if(offset > mTouchSlop) {int delayOffset = offset * 7 / 10;if(mCurrentTag.equals(GDScrollView.TAG_ONE)) {mUpSVMarginTop = mInitMarginTop - delayOffset;} else {mUpSVMarginTop = - halfHeight + delayOffset;}if(mUpSVMarginTop > 0) mUpSVMarginTop = 0;requestLayout();}}break;case MotionEvent.ACTION_UP:mIntercept = false;mInitY = 0;if(mCurrentTag.equals(GDScrollView.TAG_ONE)) {if(Math.abs(mUpSVMarginTop) > halfHeight / 3) {startAnimation(mUpSVMarginTop, halfHeight - Math.abs(mUpSVMarginTop), false);} else {startAnimation(mUpSVMarginTop, Math.abs(mUpSVMarginTop), true);}} else {if(Math.abs(mUpSVMarginTop) < halfHeight * 2 / 3) {startAnimation(mUpSVMarginTop, Math.abs(mUpSVMarginTop), true);} else {startAnimation(mUpSVMarginTop, halfHeight - Math.abs(mUpSVMarginTop), false);}}requestLayout();break;}return true;}
LinearLayout攔截到事件以后重寫onTouchEvent方法,通過手勢拖動來不斷的計算ScrooView距離頂部的高度mUpSVMarginTop,調(diào)用requestLayout方法發(fā)起重新布局,重寫onLayout方法
protected void onLayout(boolean changed, int l, int t, int r, int b) {super.onLayout(changed, l, t, r, b);halfHeight = getMeasuredHeight() / 2;mUpScrollView.layout(0, mUpSVMarginTop, getMeasuredWidth(), mUpSVMarginTop + halfHeight);mBottomScrollView.layout(0, mUpSVMarginTop + halfHeight , getMeasuredWidth(), mUpSVMarginTop + getMeasuredHeight());}
大致的思路和實現(xiàn)已經(jīng)講解完成了,想看具體實現(xiàn)代碼
源碼地址:
https://github.com/chenpengfei88/GraphicDetailsLayout
到這里接結(jié)束啦。
評論
圖片
表情
