1. Simple description
Taobao details page does not need me to introduce, yesterday Taobao see this effect, let me think of last year just learn Android will use ready-made time, at that time on the Internet to find a use of this effect, do not know how to achieve. Now you see an effect and want to do it yourself, I think it's just a curiosity to get in touch with a certain knowledge.
Let's go, this article is just to introduce a realization of ideas, the Internet has already had a lot of ways to achieve, please correct me.
The effect chart (I have very attentively to look for the beautiful picture)
2. Realize the idea
Inherit LinearLayout, set orientation to vertical
There are two scrollview in the control, and the reason for using ScrollView is that it eliminates the need to handle sliding when the content is more than one page
The key is event distribution processing. Monitoring two scrollview of sliding events, when the first page slides to the bottom, and then drag up, intercept the event, judge the distance, over the set value, slide to the second page, or rebound; Similarly, when the second page slides to the top, and then drags down, intercepting the event, judging the distance, exceeding the set value, Slide to the first page, or bounce back (there are a lot of details to be explained in conjunction with the code)
On the rebound and sliding pages used is scroller, for the use of scroller, this article does not do too much explaining
3. To achieve
3.1 Rewriting ScrollView
According to the implementation idea, we need to listen to whether the ScrollView slides to the top and bottom, but the ScrollView Setonscrollchangelistener () method is added in api23. The main is to rewrite the scrollviewonscrollchanged (int l, int t, int oldl, int Oldt) method.
L: Current horizontal scrolling value, equal to GETSCROLLX ()
T: Current vertical scrolling value, equal to getscrolly ()
OLDL: Last Horizontal scroll value
Oldt: Last Vertical scrolling value
Listener interface:
Public interface Onscrollendlistener {
void Scrolltobottom (view view);
void Scrolltotop (view view);
void Scrolltomiddle (view view);
}
Onscrollchanged method
@Override
protected void onscrollchanged (int l, int t, int oldl, int Oldt) {
super.onscrollchanged (L, T, OLDL, old t);
if (t = = 0) {
if (Monscrollbottomlistener!= null) {
monscrollbottomlistener.scrolltotop (this);
}
} else if (T + getmeasuredheight () >= getchildat (0). Getmeasuredheight ()) {
if (Monscrollbottomlistener!= null) { C15/>monscrollbottomlistener.scrolltobottom (this);
}
else {
if (Monscrollbottomlistener!= null) {
monscrollbottomlistener.scrolltomiddle (this);
}
}
}
3.2 Rewrite Onmeasure method, page's Get and set
Shows how to call the second child measurement, or the size may be 0
@Override
protected void onmeasure (int widthmeasurespec, int heightmeasurespec) {
super.onmeasure ( Widthmeasurespec, Heightmeasurespec);
/**
* shows how to call the second measurement from the child, otherwise the size may be
0
/View child2 = Getchildat (1);
if (child2!= null) {
child2.measure (Widthmeasurespec, Heightmeasurespec);
}
}
Initialize two pages in Onfinishinflate
@Override
protected void Onfinishinflate () {
super.onfinishinflate ();
if (getchildcount () = = 2) {
View child1 = getchildat (0);
if (child1 instanceof Scrollendscrollview) {
scrollView1 = (scrollendscrollview) child1;
}
View child2 = Getchildat (1);
if (child2 instanceof Scrollendscrollview) {
scrollView2 = (scrollendscrollview) child2;
}
}
Initevent ();
}
Set up slide monitoring for two pages
Private Scrollendscrollview.onscrollendlistener Scrollendlistener = new Scrollendscrollview.onscrollendlistener () {
@Override public
void Scrolltobottom (view view) {
if (view = = ScrollView1) {
Istobotttom = true;
}
}
@Override public
void Scrolltotop View {
if (view = = ScrollView2) {
istotop = true;
}
}
@Override public
void Scrolltomiddle (view view) {
if (view = = ScrollView1) {
istobotttom = false;
}
if (view = = ScrollView2) {
istotop = false;}}
;
3.3Scroller a few steps to use
Scroller The English explanation is:
This class encapsulates scrolling. can use Scrollers (scroller or Overscroller) to collect the data for you need to produce a scrolling animation-for example , in response to a fling gesture. Scrollers Track scroll offsets for your over time, but they don ' t automatically apply those positions to your view. It ' s your responsibility to get and apply new coordinates at a rate that'll make the scrolling look animation.
This class encapsulates scrolling. You can use the scroll bar (wheel or Overscroller) to collect data that you need to make a scrolling motion, for example, in response to a throw gesture. The scroll bars keep track of the scrolling offsets over time, but they do not automatically set the new location into view. Your task is to get and use a suitable speed so that the scrolling animation looks smoother.
In short, you can use this implementation for sliding.
Methods that need to be overridden
@Override public
void Computescroll () {
super.computescroll ();
First, determine if Mscroller scrolling completes if
(Mscroller.computescrolloffset ()) {
///This calls the view's Scrollto () to complete the actual scrolling
Scrollto ( Mscroller.getcurrx (), Mscroller.getcurry ());
You must call this method, or you will not necessarily see scrolling effects
postinvalidate ();
}
Auxiliary methods
Call this method to set the relative offset
of scrolling public void Smoothscrollby (int dx, int dy) {
//Set Mscroller's scrolling offset
Mscroller.startscroll (Mscroller.getfinalx (), mscroller.getfinaly (), DX, DY, Math.max (Math.Abs (dy));
Invalidate ()///Must call invalidate () to ensure that computescroll () will be invoked, otherwise it will not necessarily refresh the interface, do not see the scrolling effect
}
//Call this method to scroll to the target location
public void Smoothscrollto (int fx, int fy) {
int dx = FX-MSCROLLER.GETFINALX ();
int dy = Fy-mscroller.getfinaly ();
Smoothscrollby (dx, dy);
}
3.4 Event Distribution
The most critical part, the logic is slightly complex, the details of more processing. Rewrite dispatchtouchevent here.
When the first page is displayed
did not slide to the bottom, the event was handled by ScrollView1 itself
When sliding to the bottom, if you continue to drag up, block the event, the parent control handles the slide, and when you continue dragging down, if the parent control (that is, the control) is currently scrolling the last position (Mscroller.getfinaly ()) is not 0, If the parent control continues to scroll without a negative value (a negative value causes the head to be blank, because it is the parent control, ScrollView1 is not able to slide), does not intercept the event, the parent control handles the slide, or forces the slide to the 0 position and sends the event down to the child control
When the second page is displayed
Events are handled by SCROLLVIEW2 when they are not sliding to the top
Slide to the top, if you continue to drag down, intercept the event, the parent control handles sliding, and when you continue to drag upward, if the parent control is currently scrolling less than the first page height, intercepting the event, the parent control handles the slide, or slide to the start of the second page and send the event down
Action_move in the event distribution, in the action_up to switch pages, rebound
About the use of scroller sliding, to achieve elastic effect, simple implementation Please see here Simple flexible implementation Code
@Override public boolean dispatchtouchevent (motionevent ev) {int action = ev.getaction ();
int yposition = (int) ev.gety ();
Switch (action) {case MotionEvent.ACTION_DOWN:mScroller.abortAnimation ();
Mlasty = YPosition;
Mmovey = 0;
Break
Case MotionEvent.ACTION_MOVE:mMoveY = (mlasty-yposition);
Mlasty = YPosition;
if (Istobotttom) {if (Mmovey > 0) {//Up Smoothscrollby (0, Mmovey);
return true; else {//down if (mscroller.getfinaly ()!= 0) {//This is for the first page and the second page to display the connection at the if (getscrolly () + Mmovey > 0) {smoot
Hscrollby (0, Mmovey);
return true;
} else{Smoothscrollto (0, 0);
return super.dispatchtouchevent (EV);
else if (istotop) {if (Mmovey < 0) {//down Smoothscrollby (0, Mmovey);
return true; else {//Up if (Mscroller.getfinaly () < Scrollview1.getheight ()) {//This is for the first page and the second page to display the connection Smoothscrollby (0, M
Movey);
return true; else {smoothscrollto (0, Scrollview1.getheight());
return super.dispatchtouchevent (EV);
}////handle fast sliding two-page overlay problem if (PageIndex = 0) {smoothscrollto (0, 0);
else if (PageIndex = 1) {smoothscrollto (0, Scrollview1.getheight ());
} break; Case MotionEvent.ACTION_UP:case MotionEvent.ACTION_CANCEL:if (istobotttom) {if (Math.Abs (getscrolly ()) > To_next
_page_height) {//move to the second page PageIndex = 1;
Smoothscrollto (0, Scrollview1.getheight ());
Istobotttom = false;
Istotop = true;
else {//rebound Smoothscrollby (0,-mscroller.getfinaly ()); } else if (istotop) {if (Scrollview1.getheight ()-getscrolly () > To_next_page_height) {//Move to first page PageIndex =
0;
Smoothscrollto (0, 0);
Istobotttom = true;
Istotop = false;
else {//rebound Smoothscrollto (0, Scrollview1.getheight ());
}} break;
Default:break;
return super.dispatchtouchevent (EV);
}
4. Summary
To implement the control, you need to master the basic steps of customizing the control, the basic use of scroller, and event distribution, and of course the most critical processing here is event distribution. The beginning also said, although this has a lot of people to achieve, but still want to use their own way to achieve it again. Three loud laughs, hahaha, and implement a custom control ... Bloggers are also in the custom control learning phase, please use the control carefully to the project.
5. Download
Https://github.com/LineChen/TwoPageLayout
The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.