Click on the product details page to view details

catalogue

  • 01. Introduction to the library
  • 02. Effect display
  • 03. How to use it
  • Pay attention to the main points
  • 05. Optimization problem
  • 06. Partial code logic
  • 07. Reference cases

01. Introduction to the library

  • Imitation of Taobao, Jingdong, Kaola and other commodity details page loading UI effect. You can nest RecyclerView, WebView, ViewPager, ScrollView, etc.
  • Project address: github.com/yangchong21…

02. Effect display

2.1 Use the SlideLayout effect

2.2 Using SlideAnimLayout with loading animation effects

03. How to use it

3.1. The first option is to load a page directly from a pull-up.

  • SlideDetailsLayout has two child ChildViews: a product page Layout and a detail page Layout
  • In the layout
    <com.ycbjie.slide.SlideLayout
        android:id="@+id/slideDetailsLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:default_panel="front"
        app:duration="200"
        app:percent="0.1"> <! <FrameLayout Android :id="@+id/fl_shop_main"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/ > <! -- webView layout --> <include Layout ="@layout/include_shop_detail"/>
    
    
    </com.ycbjie.slide.SlideLayout>
    Copy the code
  • In the code
    mSlideDetailsLayout.setOnSlideDetailsListener(new SlideLayout.OnSlideDetailsListener() {
        @Override
        public void onStatusChanged(SlideLayout.Status status) {
            if (status == SlideLayout.Status.OPEN) {
                //当前为图文详情页
                Log.e("FirstActivity"."Drop back to product details");
            } else{// Current is the commodity details page log.e ("FirstActivity"."Continue to pull up for graphic details."); }}}); / / close business details page mSlideDetailsLayout. SmoothClose (true); / / open the details page mSlideDetailsLayout. SmoothOpen (true);
    Copy the code

SlideAnimLayout has three child childViews.

  • SlideAnimLayout has three child ChildViews: a product page layout, a pull-up animation layout, and a detail page layout
  • In the layout
       <com.ycbjie.slide.SlideAnimLayout
            android:id="@+id/slideDetailsLayout"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            app:default_panel="front"
            app:duration="200"
            app:percent="0.1"> <! <FrameLayout Android :id="@+id/fl_shop_main2"
                android:layout_width="match_parent"
                android:layout_height="match_parent"/ > <! <LinearLayout Android :id="@+id/ll_page_more"
                android:orientation="vertical"
                android:background="@color/colorAccent"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">
                <ImageView
                    android:id="@+id/iv_more_img"
                    android:layout_width="40dp"
                    android:layout_height="40dp"
                    android:rotation="180"
                    android:layout_gravity="center_horizontal"
                    android:src="@mipmap/icon_details_page_down_loading" />
                <TextView
                    android:id="@+id/tv_more_text"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_horizontal"
                    android:layout_marginBottom="25dp"
                    android:gravity="center"
                    android:text="Test animation, continue to pull up to see graphic details"
                    android:textSize="13sp"/> </LinearLayout> <! -- webView layout --> <include Layout ="@layout/include_shop_detail"/>
    
    
        </com.ycbjie.slide.SlideAnimLayout>
    Copy the code
  • In the code
    mSlideDetailsLayout.setScrollStatusListener(new SlideAnimLayout.onScrollStatusListener() {
        @Override
        public void onStatusChanged(SlideAnimLayout.Status mNowStatus, boolean isHalf) {
            if(mNowStatus = = SlideAnimLayout. Status. The CLOSE) {/ / openif(isHalf){
                    mTvMoreText.setText("Release, view graphic details");
                    mIvMoreImg.animate().rotation(0);
                    LoggerUtils.i("OnStatusChanged - CLOSE - release"+isHalf);
                }else{/ / close mTvMoreText. SetText ("Continue to pull up for graphic details.");
                    mIvMoreImg.animate().rotation(180);
                    LoggerUtils.i("OnStatusChanged --CLOSE-- continue to pull up"+isHalf); }}else{/ / openif(isHalf){
                    mTvMoreText.setText("Drop back to product details");
                    mIvMoreImg.animate().rotation(0);
                    LoggerUtils.i("OnStatusChanged --OPEN-- drop down to product details"+isHalf);
                }else{/ / close mTvMoreText. SetText ("Release back to Commodity details");
                    mIvMoreImg.animate().rotation(180);
                    LoggerUtils.i("OnStatusChanged --OPEN-- release back to product details"+isHalf); }}}}); / / close business details page mSlideDetailsLayout. SmoothClose (true); / / open the details page mSlideDetailsLayout. SmoothOpen (true);
    Copy the code

Pay attention to the main points

  • Get only the first two views in the child node for SlideDetailsLayout
    • The first of these is the Front, the product page; The second one is Behind, which is the detailed WebView page. See the code:
    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        final int childCount = getChildCount();
        if (1 >= childCount) {
            throw new RuntimeException("SlideDetailsLayout only accept child more than 1!!");
        }
        mFrontView = getChildAt(0);
        mBehindView = getChildAt(1);
        if(mDefaultPanel == 1){
            post(new Runnable() {
                @Override
                public void run() {// Default is off for smoothOpen(false); }}); }}Copy the code
  • Get only three views from the child node for SlideAnimLayout, and the second View is the animation node View
    • The first of these is the Front, the product page; The second is anim, the uppull drawing view. The third one is Behind, which is the WebView page with graphic details. See the code:
    @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);
        mAnimView = getChildAt(1);
        mBehindView = getChildAt(2);
        mAnimView.post(new Runnable() {
            @Override
            public void run() {
                animHeight = mAnimView.getHeight();
                LoggerUtils.i("Get control height"+animHeight); }});if(mDefaultPanel == 1){
            post(new Runnable() {
                @Override
                public void run() {// Default is off for smoothOpen(false); }}); }}Copy the code

05. Optimization problem

  • Exceptions save the status
    @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();
    }
    Copy the code
  • When the page is destroyed, remove the listener to remove the animation resource
    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        setScrollStatusListener(null);
        setOnSlideStatusListener(null);
        if (animator!=null){
            animator.cancel();
            animator = null;
        }
    }
    Copy the code

06. Partial code logic

6.1 How can ScrollView consume no events when it is at the top or bottom

  • The logic is in dispatchTouchEvent to distribute the event, and when it slides to the top or bottom, the parent View directly consumes the event. In other cases, it is the parent node that will send events up to the View.
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            caseMotionEvent.ACTION_DOWN: downX = ev.getX(); downY = ev.getY(); // If the child node does not want the parent process to intercept touch events, then it is allowed to slide up to load the next pagetrue. getParent().requestDisallowInterceptTouchEvent(true);
                break;
            case MotionEvent.ACTION_MOVE:
                float dx = ev.getX() - downX;
                float dy = ev.getY() - downY;
                boolean allowParentTouchEvent;
                if (Math.abs(dy) > Math.abs(dx)) {
                    if(dy > 0) {// Pull down at the top to let the parent View consume the event allowParentTouchEvent = isTop(); }else{// Pull up at the bottom to let the parent View consume the event allowParentTouchEvent = isBottom(); }}else{// slide horizontally allowParentTouchEvent =true; } getParent().requestDisallowInterceptTouchEvent(! allowParentTouchEvent);break;
            default:
                break;
        }
        return super.dispatchTouchEvent(ev);
    }
    Copy the code

6.2 How to realize sliding between commodity page and detail page, and how to deal with animation effect of pull-up loading control

  • SlideAnimLayout has three child ChildViews: a product page layout, a pull-up animation layout, and a detail page layout
  • After intercepting the event via onInterceptTouchEvent, the touch information is further processed in the onTouchEvent method to achieve vertical sliding
    • When the product page ScrollView slides to the bottom, the event is consumed directly by the parent View, also known as SlideAnimLayout
    • In onInterceptTouchEvent, when the detail page is opened (in the CLOSE state), it is pulled down, when the absolute value of the Y-axis slide displacement is greater than the pixel distance moved by the touch, and when the Y-axis slide displacement is greater than zero, it intercepts the event to distribute its own consumption event
    • In onInterceptTouchEvent, when the detail page is closed (in the OPEN state) and pulled up, when the absolute value of the Y-axis slide displacement is greater than the pixel distance moved by the touch, and when the Y-axis slide displacement is less than zero, the intercepting event sends its own consumption event
    • When on the goods page, pull up; Or while on the detail page, pull down, changing the mSlideOffset value as you pull, and call requestLayout() to draw
    • To slide two panels across the screen area, you only need to change the displacement of both panels in the y direction (positive and negative). The sliding ruler is the movement of the control relative to Top, and all displacement calculations are based on this ruler. When switching panels, you only need to know the corresponding offset value……
  • How do I animate a pull-up control
    • Add a listener to listen to the status and whether the distance has reached the halfway point, which is compared with the offset point. When the distance has reached the halfway point, rotate the arrow view by 180 degrees with the property animation.
    • To listen for the slide distance, we first need to get the animHeight of the loaded control, so where is the appropriate place to get it? The height of the control is obtained in the post form in the onFinishInflate() method.
  • So how do you make sliding work and look consistent
    • There are two very important parts in custom layout: onMeasure and onLayout. Measurement determines the size of the View, and layout determines the position of the View. The key idea of sliding is here. In the onLayout method, according to the sliding information obtained by onInterceptTouchEvent and onTouchEvent, the location information of the layout is calculated, and the location information is set to the sub-view to achieve sliding.
  • How to achieve scrolling effect by releasing finger after sliding
    • In other words, when in the commodity page, pull up, pull displacement is more than half, release the finger, then directly slide to the next page details page page
    • The specific logic is in the finishTouchEvent method, which mainly records the offset value, the height of the view in the close or open state, and whether the switch changes
    • Finally, start the animation, add a listener to the animation update, add requestLayout() control in this method, and the scrolling effect is achieved. Make the detail page control visible if the animation is open and displayed for the first time after scrolling.
  • How to make scrolling look natural, or how to adjust the scrolling duration
    • You can customize the time set directly in the layout…

07. Reference cases

  • Thanks to the following big guy open source case
  • Github.com/jeasonlzy/V…
  • Github.com/hexianqiao3…
  • Github.com/cnbleu/Slid…

08. More

01. About blog summary links

  • 1. Tech blog round-up
  • 2. Open source project summary
  • 3. Life Blog Summary
  • 4. Himalayan audio summary
  • 5. Other summaries

02. About my blog

  • My personal website: www.yczbj.org, www.ycbjie.cn
  • Github:github.com/yangchong21…
  • Zhihu: www.zhihu.com/people/yczb…
  • Jane: www.jianshu.com/u/b7b2c6ed9…
  • csdn:my.csdn.net/m0_37700275
  • The Himalayan listening: www.ximalaya.com/zhubo/71989…
  • Source: China my.oschina.net/zbj1618/blo…
  • Soak in the days of online: www.jcodecraeer.com/member/cont.
  • Email address: [email protected]
  • Blog: ali cloud yq.aliyun.com/users/artic… 239.headeruserinfo.3.dT4bcV
  • Segmentfault headline: segmentfault.com/u/xiangjian…
  • The Denver nuggets: juejin. Cn/user / 197877…

Project Address:Github.com/yangchong21…