First, Taobao Product Details page effect
The effect of our
Second, the realization of ideas
Using two ScrollView, two scrollview are arranged vertically, and a custom viewgroup is used to control the vertical arrangement of two scrollview, as well as the handling of sliding events. The following figure
Third, the concrete realization
1, inherit ViewGroup custom layout view overrides the Onmeasure () and OnLayout methods to complete the vertical arrangement of two sub ScrollView in the OnLayout method, as follows:
Layout file:
<relativelayout xmlns:android= "http://schemas.android.com/apk/res/android" xmlns:tools= "http:// Schemas.android.com/tools "android:layout_width=" match_parent "android:layout_height=" Match_parent "Tools:context" = "Com.baoyunlong.view.pulluptoloadmore.MainActivity" > < Com.baoyunlong.view.pulluptoloadmore.PullUpToLoadMore android:layout_width= "Match_parent" android:layout_height= "Match_parent" android:orientation= "vertical" > <com.baoyunlong.view.pulluptoloadmore.myscrollview android: Layout_width= "Match_parent" android:layout_height= "Match_parent" android:fillviewport= "true" > <LinearLay Out android:layout_width= "match_parent" android:layout_height= "match_parent" android:orientation= "vertical" > <imageview android:scaletype= "fitxy" android:src= "@drawable/a1" match _parent "android:layout_height=" 180DP "/> <textview android:text=" This is the title "Android:tExtsize= "18DP" android:layout_marginright= "10DP" android:layout_marginleft= "10DP" Android:layout_margint
op= "10DP" android:layout_width= "match_parent" android:layout_height= "wrap_content"/> <TextView android:layout_margintop= "10DP" android:text= "sub title" Android:layout_marginleft= "10DP" Android:layout_ma rginright= "10DP" android:textsize= "18DP" android:layout_width= "match_parent" android:layout_height= "wrap _content "/> ... <linearlayout android:layout_height=" "0DP" android:layout_weight= "1". "android:gravity=" Bottom "android:layout_width=" match_parent "> <textview android:layout_wi Dth= "Match_parent" android:layout_height= "wrap_content" android:height= "50DP" android:background= "#b1 1 "android:gravity=" center "android:text=" continue dragging view text details "android:textcolor=" #000 "/> </linear Layout> </lineArlayout> </com.baoyunlong.view.pulluptoloadmore.MyScrollView> < Com.baoyunlong.view.pulluptoloadmore.MyScrollView android:layout_width= "Match_parent" android:layout_height= " Match_parent "android:fillviewport=" true "> <linearlayout android:layout_width=" match_parent "Andro
id:layout_height= "match_parent" android:gravity= "center" android:orientation= "vertical" > <imageview
Android:layout_width= "Wrap_content" android:layout_height= "wrap_content" android:src= "@drawable/a1"/> <imageview android:layout_width= "wrap_content" android:layout_height= "Wrap_content" android:src = "@drawable/a3"/> ... </LinearLayout> </com.baoyunlong.view.pulluptoloadmore.MyScrollView> </com.baoyunlong.view.pulluptoloadmore.PullUpToLoadMore> </RelativeLayout>
Code:
public class Pulluptoloadmore extends ViewGroup {public
Pulluptoloadmore (context) {
super);
Public
Pulluptoloadmore (context, AttributeSet attrs) {
Super (context, attrs);
}
Public Pulluptoloadmore (context, AttributeSet attrs, int defstyleattr) {
Super (context, Attrs, defstyleattr );
}
@Override
protected void onmeasure (int widthmeasurespec, int heightmeasurespec) {
super.onmeasure ( Widthmeasurespec, Heightmeasurespec);
Measurechildren (Widthmeasurespec, Heightmeasurespec);
}
@Override
protected void OnLayout (Boolean changed, int l, int t, int r, int b) {
int childcount = Getchildcount ( );
int childtop = t;
for (int i = 0; i < ChildCount. i++) {
View child = Getchildat (i);
Child.layout (L, Childtop, R, Childtop + Child.getmeasuredheight ());
Childtop + = Child.getmeasuredheight ();
}
2. Handle Sliding Events
The rules are as follows:
(1), when in the first screen, the first ScrollView has slipped to the bottom and the slide direction is to slide up, This time the slide event should be given to the parent view process, which is to intercept the event so that Onintercepttouchevent returns True. Then the parent view scrolls through the Scrollby () method, showing the second ScrollView.
(2), when in the second screen, the second scrollview has been sliding to the top and the sliding direction is sliding down, this time the slide event to the parent view processing, according to the sliding events show the first ScrollView.
(3), when the finger away from the screen, according to the sliding speed to determine whether the rebound to the first ScrollView or the second ScrollView, through the velocitytracker to get the sliding speed.
3, some details of the processing
(1), if you look closely at the realization of Taobao results you will find that, when you slide to just see "continue dragging, view the graphics and text details", the finger raised, and then press the back up drag you will find that the second page will not be drawn, but stay in the "continue to drag, see graphic Details" of the bottom, The effect of Jing Dong is the same. So the user experience is not very good, let's optimize it. In fact, by looking at the source of ScrollView, this is because the ScrollView class of the Ontouchevent method of the default implementation, called Parent.requestdisallowintercepttouchevent (True Method prevents us from intercepting the event, causing the Onintercepttouchevent method of our parent view to be unable to execute, intercepting the event, intercepting the event, our ontouchevent cannot be executed, ontouchevent cannot execute, The scrolling logic we write in the ontouchevent is not implemented, leading to the effect that we see above. The solution is that we need to rewrite the Dispatchtouchevent () method to prevent the child view from interfering with us so that we can coherent when we slide. The code is as follows:
@Override Public
Boolean dispatchtouchevent (motionevent ev) {
//Prevent child view from stopping the parent view blocking event
This.requestdisallowintercepttouchevent (false);
return super.dispatchtouchevent (EV);
(2) The problem of monitoring ScrollView sliding events
ScrollView does not provide a monitoring method for scrolling events, and cannot determine whether to scroll to the top, or the bottom, where we inherit scrollview to implement scrolling event monitoring.
/** * Created by Baoyunlong on 16/6/8.
* * public class Myscrollview extends ScrollView {private static String tag=myscrollview.class.getname ();
public void Setscrolllistener (Scrolllistener scrolllistener) {this.mscrolllistener = Scrolllistener;
Private Scrolllistener Mscrolllistener;
Public Myscrollview {Super (context);
Public Myscrollview (context, AttributeSet attrs) {Super (context, attrs);
Public Myscrollview (context, AttributeSet attrs, int defstyleattr) {Super (context, attrs, defstyleattr); @Override public boolean ontouchevent (motionevent ev) {switch (ev.getaction ()) {case Motionevent.action_mov
E:if (mscrolllistener!=null) {int Contentheight=getchildat (0). GetHeight ();
int Scrollheight=getheight ();
int scrolly=getscrolly ();
Mscrolllistener.onscroll (scrolly); if (scrolly+scrollheight>=contentheight| | Contentheight<=scrollheight) {MscrolllistenEr.onscrolltobottom ();
}else {mscrolllistener.notbottom ();
} if (scrolly==0) {mscrolllistener.onscrolltotop ();
}} break;
Boolean result=super.ontouchevent (EV);
Requestdisallowintercepttouchevent (FALSE);
return result;
public interface scrolllistener{void Onscrolltobottom ();
void Onscrolltotop ();
void onscroll (int scrolly);
void Notbottom (); }
4, complete code is as follows
/** * Created by Baoyunlong on 16/6/8.
* * public class Pulluptoloadmore extends ViewGroup {public static String TAG = PullUpToLoadMore.class.getName ();
Myscrollview Topscrollview, Bottomscrollview;
Velocitytracker Velocitytracker = Velocitytracker.obtain ();
Scroller scroller = new Scroller (GetContext ());
int currposition = 0;
int position1y;
int lasty;
public int scaledtouchslop;//minimum sliding distance int speed = 200;
Boolean isintercept;
public Boolean bottomscrollviewisintop = false;
public Boolean topscrollviewisbottom = false;
Public Pulluptoloadmore {Super (context);
Init ();
Public Pulluptoloadmore (context, AttributeSet attrs) {Super (context, attrs);
Init (); Pulluptoloadmore (context, AttributeSet attrs, int defstyleattr) {Super (context, Attrs, defstyleattr
);
Init (); } private void Init () {Post (new Runnable () {@Override public void run () {Topscrollview = Myscrollvie WGetchildat (0);
Bottomscrollview = (Myscrollview) getchildat (1);
Topscrollview.setscrolllistener (New Myscrollview.scrolllistener () {@Override public void Onscrolltobottom () {
Topscrollviewisbottom = true;
@Override public void Onscrolltotop () {} @Override public void onscroll (int scrolly) {
@Override public void Notbottom () {topscrollviewisbottom = false;
}
}); Bottomscrollview.setscrolllistener (New Myscrollview.scrolllistener () {@Override public void Onscrolltobottom ( {} @Override public void Onscrolltotop () {} @Override public void onscroll (int scr
Olly) {if (scrolly = = 0) {Bottomscrollviewisintop = true;
else {bottomscrollviewisintop = false;
@Override public void Notbottom () {}});
position1y = Topscrollview.getbottom (); Scaledtouchslop= Viewconfiguration.get (GetContext ()). Getscaledtouchslop ();
}
}); @Override public boolean dispatchtouchevent (motionevent ev) {//Prevent child view from preventing parent view from intercepting events This.requestdisallowinterce
Pttouchevent (FALSE);
return super.dispatchtouchevent (EV);
@Override public boolean onintercepttouchevent (motionevent ev) {int y = (int) ev.gety ();
Switch (ev.getaction ()) {case MotionEvent.ACTION_DOWN:lastY = y;
Break
Case Motionevent.action_move://Judge whether it has scrolled to the bottom if (topscrollviewisbottom) {int dy = lasty-y; Determine if it is sliding up and whether in the first screen if (dy > 0 && currposition = 0) {if (dy >= scaledtouchslop) {isIn
tercept = true;//intercept event lasty=y;
}} if (bottomscrollviewisintop) {int dy = lasty-y;
Determine if it is sliding down and whether in the second screen if (Dy < 0 && currposition = 1) {if (Math.Abs (dy) >= scaledtouchslop) {
Isintercept = true;
}
}
}Break
return isintercept;
@Override public boolean ontouchevent (Motionevent event) {int y = (int) event.gety ();
Velocitytracker.addmovement (event);
Switch (event.getaction ()) {case MotionEvent.ACTION_MOVE:int dy = lasty-y;
if (getscrolly () + dy < 0) {dy = getscrolly () + dy + math.abs (getscrolly () + dy); if (getscrolly () + dy + getheight () > Bottomscrollview.getbottom ()) {dy = dy-(getscrolly () + Dy-(bott
Omscrollview.getbottom ()-getheight ());
} scrollby (0, DY);
Break
Case MotionEvent.ACTION_UP:isIntercept = false;
Velocitytracker.computecurrentvelocity (1000);
float yvelocity = velocitytracker.getyvelocity ();
if (currposition = = 0) {if (yvelocity < 0 && yvelocity <-speed) {smoothscroll (position1y);
Currposition = 1;
else {smoothscroll (0); } else {if (yvelocity > 0 && yvelocity > Speed) {smoothscroll (0);
currposition = 0;
else {smoothscroll (position1y);
}} break;
} lasty = y;
return true; @Override protected void onmeasure (int widthmeasurespec, int heightmeasurespec) {super.onmeasure (Widthmeasurespe
c, Heightmeasurespec);
Measurechildren (Widthmeasurespec, Heightmeasurespec); @Override protected void OnLayout (Boolean changed, int l, int t, int r, int b) {int childcount = Getchildcount ()
;
int childtop = t;
for (int i = 0; i < ChildCount. i++) {View child = Getchildat (i);
Child.layout (L, Childtop, R, Childtop + Child.getmeasuredheight ());
Childtop + + child.getmeasuredheight ();
The flexible sliding is implemented through scroller private void smoothscroll (int tarty) {int dy = tarty-getscrolly ();
Scroller.startscroll (Getscrollx (), getscrolly (), 0, DY);
Invalidate (); @Override public void Computescroll () {if (Scroller.computescrolloffset ()) {Scrollto (scrollEr.getcurrx (), Scroller.getcurry ());
Postinvalidate (); }
}
}
Source:
GitHub Address
The above is a small set to introduce the Android imitation Taobao, Jingdong product Details page Up drag view details of the control demo, hope to help everyone, if you have any questions please give me a message, small series will promptly reply to everyone. Here also thank you very much for the cloud Habitat Community website support!