android - एक आंतरिक समन्वयकलेयआउट के साथ बॉटमशीटबहेवियर का उपयोग करना




android-support-library ontouchlistener (4)

डिजाइन सपोर्ट लाइब्रेरी v. 23.2 ने BottomSheetBehavior पेश BottomSheetBehavior , जो एक समन्वयक के बच्चों को नीचे की शीट के रूप में कार्य करने की अनुमति देता है (स्क्रीन के नीचे से BottomSheetBehavior करने योग्य दृश्य)।

मैं क्या करना चाहूंगा, एक नीचे शीट दृश्य के रूप में , निम्नलिखित दृश्य (विशिष्ट समन्वयक + सामान ढहना):

<CoordinatorLayout
    app:layout_behavior=“@string/bottom_sheet_behavior”>

   <AppBarLayout>
        <CollapsingToolbarLayout>
           <ImageView />
        </CollapsingToolbarLayout>
    </AppBarLayout>

    <NestedScrollView>
        <LinearLayout>
            < Content ... />
        </LinearLayout>
    </NestedScrollView>

</CoordinatorLayout>

दुर्भाग्य से, नीचे की शीट के विचारों को नेस्टेड स्क्रॉलिंग को लागू करना चाहिए, या उन्हें स्क्रॉल इवेंट नहीं मिलेगा। यदि आप एक मुख्य गतिविधि के साथ प्रयास करते हैं और फिर इस दृश्य को नीचे की शीट के रूप में लोड करते हैं, तो आप देखेंगे कि स्क्रॉल ईवेंट केवल कागज के "शीट" पर काम करते हैं, कुछ अजीब व्यवहार के साथ, जैसा कि आप देख सकते हैं कि क्या आप पढ़ते रहते हैं।

मुझे पूरा यकीन है कि यह CoordinatorLayout को उपवर्ग द्वारा नियंत्रित किया जा सकता है, या BottomSheetBehavior को उपवर्ग द्वारा भी बेहतर किया जा सकता है। क्या आपके पास कोई संकेत है?

कुछ विचार

  • requestDisallowInterceptTouchEvent() का उपयोग कुछ स्थितियों में माता-पिता से घटनाओं को चोरी करने के लिए किया जाना चाहिए:

    • जब AppBarLayout ऑफसेट> 0 है
    • जब AppBarLayout ऑफसेट == 0 है, लेकिन हम स्क्रॉल कर रहे हैं (इसके बारे में एक सेकंड के लिए सोचें और आप देखेंगे)
  • पहली शर्त को इनर ऐप बार में OnOffsetChanged सेट करके प्राप्त किया जा सकता है;

  • दूसरे को कुछ ईवेंट हैंडलिंग की आवश्यकता होती है, उदाहरण के लिए:

    switch (MotionEventCompat.getActionMasked(event)) {
        case MotionEvent.ACTION_DOWN:
            startY = event.getY();
            lastY = startY;
            userIsScrollingUp = false;
            break;
        case MotionEvent.ACTION_CANCEL:
        case MotionEvent.ACTION_UP:
            userIsScrollingUp = false;
            break;
        case MotionEvent.ACTION_MOVE:
            lastY = event.getY();
            float yDeltaTotal = startY - lastY;
            if (yDeltaTotal > touchSlop) { // Moving the finger up.
                userIsScrollingUp = true;
            }
            break;
    }

मुद्दे

कहने की जरूरत नहीं है, मैं अभी यह काम नहीं कर सकता। जब मैं शर्तों को पूरा करता हूं, तो मैं घटनाओं को नहीं पकड़ पाता हूं और न ही उन्हें अन्य मामलों में पकड़ पाता हूं। नीचे दी गई छवि में आप देख सकते हैं कि एक मानक समन्वयक के साथ क्या होता है

  • यदि आप एपबार पर स्क्रॉल करते हैं तो शीट खारिज हो जाती है, लेकिन यदि आप नेस्टेड सामग्री पर स्क्रॉल करते हैं तो नहीं। ऐसा लगता है कि नेस्टेड स्क्रॉल घटनाओं को समन्वयक व्यवहार के लिए प्रचारित नहीं किया जाता है;

  • आंतरिक एपबार के साथ एक समस्या यह भी है: नेस्टेड स्क्रॉल सामग्री एपबार का पालन नहीं करती है जब यह ढह जाता है ..

मैंने github पर एक नमूना प्रोजेक्ट सेटअप किया है जो इन मुद्दों को दिखाता है।

बस स्पष्ट होना चाहिए, वांछित व्यवहार है:

  • शीट के अंदर एपबार / स्क्रॉल विचारों का सही व्यवहार;

  • जब शीट का विस्तार किया जाता है, तो यह स्क्रॉल डाउन पर गिर सकता है, लेकिन केवल अगर आंतरिक ऐपबार पूरी तरह से विस्तारित है । अभी यह ऐपबार स्थिति के संबंध में नहीं है, और केवल तभी जब आप ऐपबार को खींचते हैं;

  • जब शीट ढह जाती है, तो इशारों को स्क्रॉल करें इसका विस्तार होगा (आंतरिक ऐपबार पर कोई प्रभाव नहीं)।

कॉन्टैक्ट्स ऐप का एक उदाहरण (जो शायद बॉटमशीटबाइवर का उपयोग नहीं करता है, लेकिन यही मैं चाहता हूं):


अगर पहले बच्चे को nestedscroll है तो nestedscroll कुछ अन्य समस्याएं हो सकती हैं। यह समाधान मेरी समस्या तय कर रहा है मुझे आशा है कि आप को भी ठीक करेंगे

<CoordinatorLayout
    app:layout_behavior=“@string/bottom_sheet_behavior”>

   <AppBarLayout>
        <CollapsingToolbarLayout>
           <ImageView />
        </CollapsingToolbarLayout>
    </AppBarLayout>
</LinearLayout>
    <NestedScrollView>
        <LinearLayout>
            < Content ... />
        </LinearLayout>
    </NestedScrollView>
</LinearLayout>
</CoordinatorLayout>

अपबार लेआउट की पूर्ण स्क्रीन के लिए लेआउट इस प्रकार है: -

<android.support.design.widget.AppBarLayout
    android:id="@+id/appbar"
    android:layout_width="match_parent"
    android:layout_height="@dimen/detail_backdrop_height"
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
    android:fitsSystemWindows="true">

    <android.support.design.widget.CollapsingToolbarLayout
        android:id="@+id/collapsing_toolbar"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_scrollFlags="scroll|exitUntilCollapsed"
        android:fitsSystemWindows="true"
        app:contentScrim="?attr/colorPrimary"
        app:expandedTitleMarginStart="48dp"
        app:expandedTitleMarginEnd="64dp">

        <ImageView
            android:id="@+id/backdrop"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scaleType="centerCrop"
            android:fitsSystemWindows="true"
            app:layout_collapseMode="parallax" />

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
            app:layout_collapseMode="pin" />

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

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

<android.support.v4.widget.NestedScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:paddingTop="24dp">

        <android.support.v7.widget.CardView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/card_margin">

            <LinearLayout
                style="@style/Widget.CardContent"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="Info"
                    android:textAppearance="@style/TextAppearance.AppCompat.Title" />

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="@string/cheese_ipsum" />

            </LinearLayout>

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

        <android.support.v7.widget.CardView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="@dimen/card_margin"
            android:layout_marginLeft="@dimen/card_margin"
            android:layout_marginRight="@dimen/card_margin">

            <LinearLayout
                style="@style/Widget.CardContent"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="Friends"
                    android:textAppearance="@style/TextAppearance.AppCompat.Title" />

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="@string/cheese_ipsum" />

            </LinearLayout>

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

        <android.support.v7.widget.CardView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="@dimen/card_margin"
            android:layout_marginLeft="@dimen/card_margin"
            android:layout_marginRight="@dimen/card_margin">

            <LinearLayout
                style="@style/Widget.CardContent"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="Related"
                    android:textAppearance="@style/TextAppearance.AppCompat.Title" />

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="@string/cheese_ipsum" />

            </LinearLayout>

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

    </LinearLayout>

</android.support.v4.widget.NestedScrollView>

<android.support.design.widget.FloatingActionButton
    android:layout_height="wrap_content"
    android:layout_width="wrap_content"
    app:layout_anchor="@id/appbar"
    app:layout_anchorGravity="bottom|right|end"
    android:src="@drawable/ic_discuss"
    android:layout_margin="@dimen/fab_margin"
    android:clickable="true"/>

और उसके बाद आपको अपनी कक्षा में AppBarLayout.OnOffsetChangedListener को लागू करना चाहिए और स्क्रीन के ऑफसेट को सेट करना चाहिए।


मैंने आखिरकार अपना कार्यान्वयन जारी कर दिया है। इसे गितुब पर या सीधे jcenter से खोजें:

compile 'com.otaliastudios:bottomsheetcoordinatorlayout:1.0.0’

आपको बस अपने बॉटम शीट के लिए रूट व्यू के रूप में BottomSheetCoordinatorLayout का इस्तेमाल करना है। यह स्वतः ही अपने लिए एक कार्य व्यवहार को बढ़ा देगा, इसलिए इसके बारे में चिंता न करें।

मैं लंबे समय से इसका उपयोग कर रहा हूं और इसमें स्क्रॉल मुद्दे नहीं होने चाहिए, एबीएल आदि पर खींचने का समर्थन करता है।


मैंने इस मुद्दे के बारे में लैंसेंजर की शुरुआती गितुब परीक्षण परियोजना का पालन किया है, और मुझे खुशी है कि जब आप अपने ऐप में भी इस व्यवहार की आवश्यकता थी, तो मैं आपको उनके कुछ मुद्दों के लिए समाधान साझा करना चाहता हूं।

यह उनकी समस्या का समाधान है: bar टूलबार कभी-कभी बहुत जल्दी ढह जाता है

इसे रोकने के लिए, आपको अपना कस्टम AppBarLayout.Behavior बनाने की आवश्यकता है, क्योंकि यह तब होता है जब आप स्क्रॉल करते हुए अभी भी खींच रहे हैं कि AppBarLayout.behavior को स्क्रॉल गति मिलती है। हमें यह पता लगाने की जरूरत है कि क्या STATE_DRAGGING में है और समय से पहले टूलबार को छिपाने / टकराने से बचने के लिए बस वापस आ जाता है।

public class CustomAppBarLayoutBehavior extends AppBarLayout.Behavior {

    private CoordinatorLayoutBottomSheetBehavior behavior;

    public CustomAppBarLayoutBehavior() {
    }

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

    @Override
    public boolean onStartNestedScroll(CoordinatorLayout parent, AppBarLayout child, View directTargetChild, View target, int nestedScrollAxes) {
        behavior = CoordinatorLayoutBottomSheetBehavior.from(parent);
        return super.onStartNestedScroll(parent, child, directTargetChild, target, nestedScrollAxes);
    }

    @Override
    public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, int dx, int dy, int[] consumed) {
        if(behavior.getState() == CoordinatorLayoutBottomSheetBehavior.STATE_DRAGGING){
            return;
        }else {
            super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed);
        }
    }

    @Override
    public void setDragCallback(@Nullable DragCallback callback) {
        super.setDragCallback(callback);
    }
}

यह एक अच्छी शुरुआत हो सकती है कि हम दूसरे मुद्दों को कैसे हल करें:

❌ टूलबार को ड्रग्स के माध्यम से नहीं ढहाया जा सकता है

❌ मुख्य समन्वयक लेआउट कुछ स्क्रॉल का उपभोग करता है

मैं वास्तव में एक अच्छा यूआई / एनीमेशन व्यक्ति नहीं हूं, लेकिन हार्डवर्क कभी-कभी कोड को समझने के लिए भुगतान करता है, लागू करने के लिए सही कॉलबैक / ओवरराइड फ़ंक्शन ढूंढता है।

इसे व्यवहार के रूप में सेट करें

<android.support.design.widget.AppBarLayout
    android:id="@+id/bottom_sheet_appbar"
    style="@style/BottomSheetAppBarStyle"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:layout_behavior="your.package.CustomAppBarLayoutBehavior">




android-support-design