A demo takes you through the sliding conflict of view

Source: Internet
Author: User

Recently in the re-learning of Android Custom view this piece of content, encountered in peacetime development often encountered a thorny problem: view of the sliding conflict. Believe that many small partners have the same feeling, seemingly simple really do it but do not know where to start. From a simple demo today, take you through the solution to the view sliding conflict.

The usual, first:

In the example diagram is a common pull-back and the entire layout slides together as the finger slides down. Drop down to a certain distance, the layout will automatically bounce back to the beginning of the position, when the finger swipe up, the layout of the sub-view will slide to the bottom, and then the finger down, the layout of the child view will slide to the top, the last finger continues to slide, the entire layout will slide together, Pull down to a certain distance and let go automatically bounce to the start position.

The effect of the final implementation, as shown above, is to see how to achieve the final result in one step:

I. Implementation of the pull-back rebound of the layout

The implementation of the pull-back is essentially the sliding of the view, the current implementation of the Android view of the sliding can be divided into three ways: by changing the layout parameters of the view to make the view re-layout to achieve sliding; Scrollto/scrollby method to realize the sliding of the view ; Apply a panning effect to the view by animating it to achieve sliding. Here we do this in the first way, considering that the entire layout is vertical, and we can customize a linearlayout directly as the parent layout. Then call layout (int l, int t, int r, int b) to re-layout, to achieve the effect of sliding.

 Public  class myparentview extends linearlayout {    Private intMmove;Private intYdown, Ymove;Private inti =0; Public Myparentview(context context, AttributeSet attrs) {Super(context, attrs); }@Override     Public Boolean ontouchevent(Motionevent event) {inty = (int) event.gety ();Switch(Event.getaction ()) { CaseMotionEvent.ACTION_DOWN:yDown = y; Break; CaseMotionEvent.ACTION_MOVE:yMove = y;if((Ymove-ydown) >0) {mmove = Ymove-ydown;                    i + = Mmove;                Layout (GetLeft (), GetTop () + Mmove, GetRight (), Getbottom () + mmove); } Break; CaseMotionEvent.ACTION_UP:layout (GetLeft (), GetTop ()-I, GetRight (), Getbottom ()-i); i =0; Break; }return true; }}

Motionevent.action_down: Gets the y-coordinate of the first touch
Motionevent.action_move: If it is sliding down, calculate the distance between each slide and the total distance of the slide, the distance of each slide as the parameters of layout (int l, int t, int r, int b) method, re-layout, to achieve the effect of layout slide.
MOTIONEVENT.ACTION_UP: The total distance of the slide as the parameter of layout (int l, int t, int r, int b) method, re-layout to achieve the effect of automatic rebound.

The layout file is like this:

    <org.tyk.android.artstudy.MyParentViewandroid:id="@+id/parent_view"  Android:layout_width="Match_parent"android:layout_height="Match_parent"  Android:orientation="vertical">                                                <Viewandroid:layout_width= "match_parent"android:layout_height=" 1DP "android:background=" @color/divider ">                                                            </View>                <relativelayoutandroid:layout_width="Match_parent"android:layout _height="70DP">                                                            <imageview  a Ndroid:layout_width  = "wrap_content"  android:layout_height  =" wrap_content " android:layout_centervertical  =" true " android:layout_marginleft  =" 10DP " android:background  = "@drawable/b" />                     <textview  an Droid:layout_width  = "wrap_content"  android:layout_height  =" wrap_content " android:layout_centervertical  =" true " android:layout_marginleft  =" 80DP " android:text  = "back home"  android:textsize  =" 20sp "/>                     <ImageViewandroid:layout_width="Wrap_content"android:layout_height= "Wrap_content" android:layout_alignparentright="true"android:layout_centervertical="true" android:layout_marginright="10DP"android:background="@drawable/right_ Arrow " />                                                                                                                                                               </relativelayout>    </org.tyk.android.artstudy.MyParentView>

The relativelayout of the middle repetition is not posted. At this point, a simple pull-back has been achieved, about the rapid sliding and inertial sliding can be added, here is not the focus of this blog is not discussed.

Two. Scrolling implementation of Sub view

As the finger slides down, the drop-back of the layout has been implemented, and now I want the child view of the layout to scroll when the finger slides up. Usually the most contact can scroll view is ScrollView, so my first reaction is in the custom linearlayout, add a scrollview, let the child view can scroll. Just do what you say:

<org. Tyk. Android. Artstudy. MyparentviewAndroid:id="@+id/parent_view"Android:layout_width="Match_parent"android:layout_height="Match_parent"> <scrollview android:layout_width="Match_parent"android:layout_height="Match_parent"> <linearlayout android:layout_width="Match_parent"android:layout_height="Match_parent"android:orientation="Vertical"> </LinearLayout> </ScrollView> </org. Tyk. Android. Artstudy. Myparentview>

The happy addition to go, the result of the last operation is: the layout has completely become a scrollview, the previous pull back effect has completely disappeared!!! This is obviously not the result I expected.

A closer look at this phenomenon, in fact, is one of the common view sliding conflict scenarios: the external sliding direction is consistent with the internal sliding direction. The parent layout Myparentview needs to respond to the downward slide in the vertical direction, enabling the pull-back, and the sub-layout ScrollView also needs to respond to the vertical swipe up and down to achieve the child view scrolling. A logic problem arises when both the inner and outer layers can slide in the same direction. because when the finger slips, the system cannot know which layer the user wants to slide. So the sliding conflict in this scenario needs to be solved manually.

Workaround:
External interception method: The external interception method refers to the Click event is first through the parent container interception processing, if the parent container needs to handle this event to intercept, if this event is not required to intercept, so that the problem of sliding conflict can be resolved. The external interception method needs to rewrite the parent container's onintercepttouchevent () method to do the appropriate interception inside.

Specific implementation:

@Override PublicBooleanonintercepttouchevent(motioneventEvent) {inty = (int)Event. GetY ();Switch(Event. Getaction ()) { CaseMotionEvent.ACTION_DOWN:yDown = y; Break; CaseMotionEvent.ACTION_MOVE:yMove = y;if(Ymove-ydown <0) {isintercept =false; }Else if(Ymove-ydown >0) {isintercept =true; } Break; CaseMOTIONEVENT.ACTION_UP: Break; }returnisintercept; }

Implementation analysis:
The Onintercepttouchevent () method is overridden in the custom parent layout, and is motionevent.action_move. If the finger is sliding upward, onintercepttouchevent () returns false, indicating that the parent layout does not intercept the current event and the current event is given to the child view processing, then our sub view can scroll; if the finger is sliding down, Onintercepttouchevent () Returns True, indicating that the parent layout intercepts the current event, and the current event is handed over to the parent layout, so our parent layout can pull the bounce back.

Three. The realization of continuous sliding

At first I thought it would be all right, but then I found a very serious problem: when the finger swipe up, the child view began to scroll, and then the finger to slide, the entire parent layout began to slide, let go after the automatic rebound. In other words, the child view that you just scrolled is not back to the start position. A careful analysis of the results is expected, because as long as my finger is sliding down, onintercepttouchevent () returns True, and the parent layout intercepts the current event. Here is actually the above mentioned view sliding conflict: The ideal result is that when the child view scrolls, if the child view does not scroll to the beginning of the position, the parent layout does not intercept the sliding event, if the child view has scrolled to the beginning, the parent layout begins to intercept the sliding event.

Workaround:
Internal interception method: The internal interception method refers to the Click event first through the sub-view processing, if the child view needs this event is consumed directly, otherwise the parent container for processing, so that the problem of sliding conflicts can be resolved. The internal interception method needs to be matched with the requestdisallowintercepttouchevent () method to determine whether the child view allows the parent layout to intercept events.

Specific implementation:

 Public  class myscrollview extends ScrollView {     Public Myscrollview(Context context) { This(Context,NULL); } Public Myscrollview(context context, AttributeSet attrs) { This(Context, Attrs,0); } Public Myscrollview(context context, AttributeSet attrs,intDEFSTYLEATTR) {Super(Context, attrs, defstyleattr); }@Override     Public Boolean ontouchevent(Motionevent ev) {Switch(Ev.getaction ()) { CaseMotionevent.action_move:intscrolly = getscrolly ();if(scrolly = =0) {//Allow parent view to block eventsGetParent (). Requestdisallowintercepttouchevent (false); }Else{//Disable the parent view for event blockingGetParent (). Requestdisallowintercepttouchevent (true); } Break; }return Super. ontouchevent (EV); }}

Implementation analysis:
Customize a ScrollView, rewrite the Ontouchevent () method, and in Motionevent.action_move, get a sliding distance. If the distance to slide is 0, indicating that the child view has scrolled to the start position, call the GetParent (). Requestdisallowintercepttouchevent (False) method to allow the parent view to intercept the event If the sliding distance is not 0, indicating that the child view does not scroll to the start position, call the GetParent (). Requestdisallowintercepttouchevent (True) method to prevent the parent view from intercepting the event. This way, as long as the child view does not scroll to the beginning, the parent layout does not intercept the event, and once the Child view scrolls to the beginning, the parent layout begins to intercept the event, forming a continuous slide.

Well, for other scenes more complex sliding conflicts, the principle and way to solve the sliding conflict is nothing more than these two methods. Hope to read this blog can help you, next goodbye ~ ~ ~

A demo takes you through the sliding conflict of view

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.