35

के साथ एक Viewpager अंदर एक कार्यक्षेत्र Recyclerview अंदर क्षैतिज Recyclerview इस एप्लिकेशन को मैं सब नीचे खंडों की तत्वों के साथ निर्माण करने के लिए कोशिश कर रहा हूँ है:एंड्रॉयड लेआउट: स्क्रॉल व्यवहार

Veggies app

सब कुछ काम करता है फिर भी, मैं आंतरिक क्षैतिज पुनर्नवीनीकरण चाहता हूं कि किसी लंबवत स्क्रॉल को कैप्चर न करें। सभी लंबवत स्क्रॉल को बाहरी लंबवत रीसाइक्लर्विव की ओर जाना चाहिए, क्षैतिज नहीं, ताकि वर्टिकल स्क्रॉल टूलबार के स्क्रॉल के अनुसार दृश्य से बाहर निकलने की अनुमति दे।

जब मैं recyclerview की "स्ट्रॉबेरी प्लांट" ओर से मेरी उंगली रख दिया और ऊपर स्क्रॉल, यह उपकरण पट्टी बाहर स्क्रॉल:

strawberry plant

अगर मैं क्षैतिज scrollview पर मेरी उंगली रख दिया और ऊपर स्क्रॉल , यह टूलबार को बिल्कुल भी स्क्रॉल नहीं करता है।

अब तक मेरा एक्सएमएल लेआउट कोड है।

गतिविधि XML लेआउट:

<?xml version="1.0" encoding="utf-8"?> 
<FrameLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:app="http://schemas.android.com/apk/res-auto" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:id="@+id/fragment_container" 
    android:clipChildren="false"> 

    <android.support.design.widget.CoordinatorLayout 
     android:orientation="vertical" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:id="@+id/container" 
     > 

    <android.support.design.widget.AppBarLayout 
     android:id="@+id/appBarLayout" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content"> 

     <android.support.v7.widget.Toolbar 
      android:id="@+id/toolbar" 
      android:minHeight="?attr/actionBarSize" 
      android:background="?attr/colorPrimary" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      app:layout_scrollFlags="scroll|enterAlways"> 

     </android.support.v7.widget.Toolbar> 

     <android.support.design.widget.TabLayout 
      android:id="@+id/sliding_tabs" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:background="?attr/colorPrimary" 
      style="@style/CustomTabLayout" 
      /> 

    </android.support.design.widget.AppBarLayout> 
    <android.support.v4.view.ViewPager 
     android:id="@+id/viewPager" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     app:layout_behavior="@string/appbar_scrolling_view_behavior" 
     /> 

    </android.support.design.widget.CoordinatorLayout> 

</FrameLayout> 

"फल" टुकड़ा XML लेआउट (जो टुकड़ा के लिए कोड है - टुकड़ा ऊपर चित्र में लेबल किया गया है):

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 

    <ProgressBar 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:id="@+id/progressBar" 
     android:visibility="gone" 
     android:layout_centerInParent="true" 
     android:indeterminate="true"/> 

<!-- <android.support.v7.widget.RecyclerView--> 
    <com.example.simon.customshapes.VerticallyScrollRecyclerView 
     android:id="@+id/main_recyclerview" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     /> 

</RelativeLayout> 

मैंने वर्टिकल स्क्रॉल रीसाइक्लिंग व्यू नामक एक कस्टम क्लास का उपयोग किया है जो व्यूग्रुप में टच इवेंट्स को संभालने के Google उदाहरण का पालन करता है। लेआउट

public class VerticallyScrollRecyclerView extends RecyclerView { 

    public VerticallyScrollRecyclerView(Context context) { 
     super(context); 
    } 

    public VerticallyScrollRecyclerView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    public VerticallyScrollRecyclerView(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
    } 

    ViewConfiguration vc = ViewConfiguration.get(this.getContext()); 
    private int mTouchSlop = vc.getScaledTouchSlop(); 
    private boolean mIsScrolling; 
    private float startY; 

    @Override 
    public boolean onInterceptTouchEvent(MotionEvent ev) { 
     final int action = MotionEventCompat.getActionMasked(ev); 
     // Always handle the case of the touch gesture being complete. 
     if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) { 
      // Release the scroll. 
      mIsScrolling = false; 
      startY = ev.getY(); 
      return super.onInterceptTouchEvent(ev); // Do not intercept touch event, let the child handle it 
     } 
     switch (action) { 
      case MotionEvent.ACTION_MOVE: { 
       Log.e("VRecView", "its moving"); 
       if (mIsScrolling) { 
        // We're currently scrolling, so yes, intercept the 
        // touch event! 
        return true; 
       } 
       // If the user has dragged her finger horizontally more than 
       // the touch slop, start the scroll 
       // left as an exercise for the reader 
       final float yDiff = calculateDistanceY(ev.getY()); 
       Log.e("yDiff ", ""+yDiff); 
       // Touch slop should be calculated using ViewConfiguration 
       // constants. 
       if (Math.abs(yDiff) > 5) { 
        // Start scrolling! 
        Log.e("Scroll", "we are scrolling vertically"); 
        mIsScrolling = true; 
        return true; 
       } 
       break; 
      } 
     } 
     return super.onInterceptTouchEvent(ev); 
    } 


    private float calculateDistanceY(float endY) { 
     return startY - endY; 
    } 

} 

"पसंदीदा": http://developer.android.com/training/gestures/viewgroup.html

VerticallyScrollRecyclerView के लिए कोड के नीचे है: इसका उद्देश्य रोकना और सभी ऊर्ध्वाधर स्क्रॉल ईवेंट उपभोग करने के लिए इतना है कि यह/बाहर उपकरण पट्टी में स्क्रॉल जाएगा जो ऊर्ध्वाधर recyclerview भीतर recyclerview है:

<?xml version="1.0" encoding="utf-8"?> 

<RelativeLayout 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:background="@color/white" 
    xmlns:app="http://schemas.android.com/apk/res-auto"> 

    <TextView 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:text="Favourite" 
     android:layout_marginTop="8dp" 
     android:layout_marginBottom="8dp" 
     android:layout_marginLeft="16dp" 
     android:id="@+id/header_fav"/> 

    <android.support.v7.widget.RecyclerView 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:orientation="horizontal" 
     android:layout_below="@+id/header_fav" 
     android:id="@+id/recyclerview_fav"> 
    </android.support.v7.widget.RecyclerView> 

</RelativeLayout> 

यह कर दिया गया अब थोड़ी देर के लिए मुझे गुस्सा दिलाना गया है और मैं n है ओटी एक समाधान के साथ आने में कामयाब रहे। किसी को इस समस्या को हल पता है?

सही उत्तर के लिए ग्रिफिंडर को 5 अंक और निश्चित रूप से, एसओ पर प्रतिष्ठा अंक।

उत्तर

85

परीक्षण समाधान:

आपको बस अपने भीतर RecyclerView रों स्पष्टीकरण पर


mInnerRecycler.setNestedScrollingEnabled(false); कॉल करने के लिए है:

RecyclerView को लागू करने के माध्यम से API 21 में पेश नेस्टेड स्क्रॉल के लिए समर्थन हासिल है NestedScrollingChild इंटरफ़ेस।यह एक मूल्यवान विशेषता है जब आपके पास एक ही दिशा में स्क्रॉल करने वाले दूसरे के अंदर स्क्रोलिंग दृश्य होता है और आप ध्यान केंद्रित करते समय आंतरिक View को स्क्रॉल करना चाहते हैं।

किसी भी मामले में, RecyclerView डिफ़ॉल्ट रूप से RecyclerView.setNestedScrollingEnabled(true); प्रारंभ करते समय स्वयं पर कॉल करता है। अब, समस्या पर वापस, क्योंकि आपके RecyclerView एस दोनों ViewPager के भीतर हैं, जिनमें AppBarBehavior है, CoordinateLayout यह तय करना है कि जब आप अपने आंतरिक RecyclerView से स्क्रॉल करते हैं तो किस स्क्रॉल का जवाब देना है; जब आपका आंतरिक RecyclerView की नेस्टेड स्क्रॉलिंग सक्षम होती है, तो उसे स्क्रॉलिंग फोकस मिल जाता है और CoordinateLayout बाहरी RecyclerView की स्क्रॉलिंग पर इसकी स्क्रॉलिंग का जवाब देना चुनता है। बात यह है कि, चूंकि आपके आंतरिक RecyclerView एस लंबवत स्क्रॉल नहीं करते हैं, इसलिए कोई लंबवत स्क्रॉल परिवर्तन नहीं होता है (CoordinateLayout के दृष्टिकोण से), और यदि कोई परिवर्तन नहीं है, तो AppBarLayout या तो नहीं बदलता है।

आपके मामले में, क्योंकि अपने भीतर RecyclerView रों एक अलग दिशा में स्क्रॉल कर रहे हैं, तो आप इस तरह अपनी स्क्रॉल उपेक्षा और बाहरी RecyclerView के स्क्रॉल करने के लिए प्रतिक्रिया करने के लिए CoordinateLayout के कारण अक्षम कर सकते हैं,।


सूचना:

XML विशेषता android:nestedScrollingEnabled="boolean"RecyclerView साथ प्रयोग के लिए इरादा नहीं है, और android:nestedScrollingEnabled="false" उपयोग करने के लिए एक java.lang.NullPointerException में परिणाम होगा तो, कम से कम अब के लिए, आप एक प्रयास कोड में इसे करना है।

+1

का सामना करना पड़ आप हालांकि बाध्यकारी डेटा उपयोग कर रहे हैं दूसरों के लिए काम करेंगे, तो आप एप्लिकेशन कर सकते हैं: nestedScrollingEnabled = "@ {true}", और कोड में ऐसा करने से दूर हो जाएं: डी – brAzzi64

+0

@ आपकी स्पष्टीकरण के लिए धन्यवाद। मैं इसी समस्या को हल करने के लिए setNestedScrollingEnabled (false) का उपयोग करने का प्रयास कर रहा हूं लेकिन मेरे पास न्यूनतम API स्तर 15 है। मैं नवीनतम समर्थन लाइब्रेरी का उपयोग कर रहा हूं। क्या यह केवल एपीआई 21 और ऊपर समर्थित है? – user2095470

+0

आपने मेरा दिन बचाया =) –

2

परीक्षण किया गया समाधान, कस्टम NestedScrollView() का उपयोग करें।

कोड:

public class CustomNestedScrollView extends NestedScrollView { 
    public CustomNestedScrollView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    @Override 
    public boolean onInterceptTouchEvent(MotionEvent ev) { 
     if (ev.getAction() == MotionEvent.ACTION_DOWN) { 
     // Explicitly call computeScroll() to make the Scroller compute itself 
      computeScroll(); 
     } 
     return super.onInterceptTouchEvent(ev); 
    } 
} 
2

मैं थोड़ी देर हो चुकी हूँ, लेकिन इस defintly एक ही समस्या

mRecyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() { 
      @Override 
      public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) { 
       int action = e.getAction(); 
       // Toast.makeText(getActivity(),"HERE",Toast.LENGTH_SHORT).show(); 
       switch (action) { 
        case MotionEvent.ACTION_POINTER_UP: 
         rv.getParent().requestDisallowInterceptTouchEvent(true); 

         break; 
       } 
       return false; 
      } 
संबंधित मुद्दे