Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
12 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by jhow77 · Apr 19, 2017 at 10:19 AM · dragscrollviewscrollscrollingscroll view

Nested Scroll Views: How can I pass drag control from an inner scroll view to its outer scroll view?

I currently have an outer horizontal scroll view. Somewhere within the content of that horizontal scrollview, I have an inner vertical scroll view.

Current functionality: If I drag my finger inside the inner scroll view, it only moves the inner scroll view. The outer scroll view does not respond to the drag movement.

Desired functionality: If I drag my finger vertically inside the inner scroll view, the inner scroll view will scroll vertically. If I drag my finger horizontally inside (or outside) the inner scroll view, the outer scroll view will scroll horizontally.

How can I achieve this functionality? How can I pass drag control from an inner scroll view to its outer scroll view?

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
1

Answer by nnikolas · May 02, 2019 at 10:23 PM

Hi,

there are a few ways to do it. One could be extending EventTrigger, scripting it to be a kind of event dispatcher and puting that script on content gameobject to intercept pointer drags. Caveat of that approach would be that it will intercept all events, but that might be the intended functionality.

An another way would be extending ScrollRect with that kind of dispatcher and using it instead of inner scroll view. Possible implementation (so inspector view remains the same):

 using UnityEngine;
 using UnityEngine.EventSystems;
 using UnityEngine.UI;
 
 public class InnerScrollRect : ScrollRect
 {
     //Reference to outer scroll rect
     ScrollRect outerScroll;
 
     //Helper flags
     bool sendToOuter;
     bool enteringDrag;
 
     protected override void Awake ()
     {
         base.Awake ();
 
         //Try to find outer scrollrect
         outerScroll = this.transform.parent.GetComponentInParent<ScrollRect> ();
     }
 
     public override void OnInitializePotentialDrag (PointerEventData eventData)
     {
         //Send through potential drag event (stoping inertia movement on both
         //scrollrect)
         if (outerScroll)
             outerScroll.OnInitializePotentialDrag (eventData);
 
         base.OnInitializePotentialDrag (eventData);
     }
 
     public override void OnBeginDrag (PointerEventData eventData)
     {
         //React only to touch (button) to which scrollrect normaly react
         if (eventData.button != PointerEventData.InputButton.Left)
             return;
 
         //Set flag to know when first drag frame occurs
         enteringDrag = true;
 
         if (outerScroll)
             outerScroll.OnBeginDrag (eventData);
 
         base.OnBeginDrag (eventData);
     }
 
     public override void OnDrag (PointerEventData eventData)
     {
         if (eventData.button != PointerEventData.InputButton.Left)
             return;
 
         //If this is first frame of drag we need to find out if drag
         //is horizontal or vertical
         if (enteringDrag && outerScroll != null)
         {
             bool horizontalDrag =
                 (Mathf.Abs (eventData.pressPosition.x - eventData.position.x) >
                     Mathf.Abs (eventData.pressPosition.y - eventData.position.y));
 
             //Decide if future draging is to be sent to outer scrollrect
             if (horizontalDrag == outerScroll.horizontal)
                 sendToOuter = true;
 
             //... and send end drag event to the other one.
             if (sendToOuter)
                 base.OnEndDrag (eventData);
             else
                 outerScroll.OnEndDrag (eventData);
         }
         enteringDrag = false;
 
         //Dispatch drag event to the correct scrollrect
         if (sendToOuter)
             outerScroll.OnDrag (eventData);
         else
             base.OnDrag (eventData);
     }
 
     public override void OnEndDrag (PointerEventData eventData)
     {
         if (eventData.button != PointerEventData.InputButton.Left)
             return;
 
         //Dispatch EndDrag event to the correct scrollrect
         if (sendToOuter)
         {
             outerScroll.OnEndDrag (eventData);
             sendToOuter = false;
         }
         else
         {
             base.OnEndDrag (eventData);
         }
     }
 
 }


In this script, drag is "locked" after the first frame to allow only horizontal or only vertical. If it's needed that control always flows through, then it's simpler script where in every event method (OnBeginDrag, OnDrag...) it's calling both objects (just like in OnInitializePotentialDrag in this example).

The setup (hierarchy):

 ScrollView (default Unity ScrollRect, both vertical and horizontal enabled)
    Viewport
       Content
          InnerScrollView (this script, only vertical or horizontal)
             Viewport2
                Content2

Working summary: mouse button press on InnerScrollView will be intercepted with this script and used to stop inertia on itself and also on parent ScrollView. This script will then wait for the first frame when drag occurs to decide if drag is in its enabled direction or not:

  1. If it is, then, this script will enter "self mode" and act upon the cursor drag movement, until the mouse button is released. It will not send any mouse events to the parent ScrollView.

  2. Otherwise, if the drag in the first frame is not in enabled direction, it will enter "other mode" and just send all the drag events to the parent ScrollView, until the mouse button is released.

Hope this helps. Cheers.

Comment
Add comment · Show 5 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image echolink · Nov 29, 2020 at 03:38 AM 0
Share

hi @nnikolas,

i tried to use your code, and i understand the intention, but somehow when in release my horizontal drag, the content snap back to position of the innerscroll rect.

do you have the same experience?

avatar image gsshewalkar · Jan 04, 2021 at 02:11 PM 0
Share

Hi @nnikolas , $$anonymous$$y intention is same but somehow it's not working with the above code. Horizontal drag into inner scroll rect is not having horizontal drag of outer scroll rect. Please help.

avatar image nnikolas · Jan 12, 2021 at 07:51 PM 0
Share

Hi, just tried the test rig again on 2018.4.30 and it works for me. The hierarchy is like this:

 ScrollView
   Viewport
      Content
          InnerScrollView
              Viewport2
                  Content2
                      Image

so that "ScrollView" has horizontal and vertical allowed (size 600x600, default settings), "Content" is large (lets say 2000x2000), "InnerScrollView" is only vertical, size for example 1000x1000, in the center of "Content"; and "Content2" is again large (2000x2000). When you drag anywhere out of "InnerScrollView", only "Content" will move, if you start to drag verticaly inside "InnerScrollView" only "Content2" will move. If you start to drag horizontaly inside "InnerScrollView" (and then you can drag how you like since only the start is important) again only "Content" will move. I don't know if this helps.

avatar image AhmadYusaf · Jun 08, 2021 at 10:43 AM 0
Share

@nnikolas this code is very helpful and works. Can you please explain it in some sort of short summary?

avatar image nnikolas · Jun 08, 2021 at 11:46 AM 0
Share

@AhmadYusaf I've added setup and short summary in the answer. I hope this answers all of the unknowns.

avatar image
0

Answer by Uzair-Mahmood · Apr 30, 2019 at 04:12 PM

Hi, Working on the same thing now and require the same result as you. Wondering if you got it working?

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

8 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

How can i implement a scroll speed for a scroll view/rect so that my content travels slower when I drag? 1 Answer

Scroll rect snaps everytime with drag 0 Answers

I am still able to scroll even though scroll type is clamped? 0 Answers

Scroll A Text Once It Reaches The End Of The Viewport 0 Answers

Unity scroll unknown length, runtime adding items 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges